tests,style: add RISC-V assembly tests

This patch adds a subset (rv64*) of RISC-V assembly tests. The original
riscv-test project can be found here:
https://github.com/riscv/riscv-tests. The riscv-test project is under the
BSD license (https://github.com/riscv/riscv-tests/blob/master/LICENSE)
and is maintained separately from gem5 project.

The tests have been slightly modified to work in gem5 SE mode:

(1) Removed a trap handler used in riscv-tests for bare-metal systems

(2) Instead of throwing an exception, the tests call the exit syscall
with
the exit code of
    - '0' if SUCCESS
    - Failed test case's number (non-zero) if FAILURE
The exit code can be captured after a simuation completes.

In addition to original RISC-V assembly tests, this patch adds several
assembly tests specifically for AMO, LR, SC and system calls. Those
tests target a multi-core system.

(1) rv64uamt: multi-threaded tests for A-extension instructions

(2) rv64samt: multi-threaded tests for clone and futex system calls

This patch also makes the style checker ignore RISC-V assembly test
directory. The assembly tests are maintained in an external project
that does not follow the gem5 coding conventions.

Please find more details in the README file included in this patch.

Change-Id: Id1015d9a2c6c7d0341fa8b81483289e5f0bfcec0
Reviewed-on: https://gem5-review.googlesource.com/6703
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
diff --git a/tests/test-progs/asmtest/src/riscv/LICENSE b/tests/test-progs/asmtest/src/riscv/LICENSE
new file mode 100644
index 0000000..48fe522
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2012-2015, 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/tests/test-progs/asmtest/src/riscv/Makefile b/tests/test-progs/asmtest/src/riscv/Makefile
new file mode 100644
index 0000000..c1fe47d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/Makefile
@@ -0,0 +1,89 @@
+#=======================================================================
+# Makefile for riscv-tests/isa
+#-----------------------------------------------------------------------
+
+XLEN ?= 64
+
+src_dir 	:= ./isa
+bin_dir 	:= ../../bin/riscv
+dump_dir 	:= ../../dump/riscv
+
+include $(src_dir)/rv64ui/Makefrag
+include $(src_dir)/rv64uc/Makefrag
+include $(src_dir)/rv64um/Makefrag
+include $(src_dir)/rv64ua/Makefrag
+include $(src_dir)/rv64uf/Makefrag
+include $(src_dir)/rv64ud/Makefrag
+include $(src_dir)/rv64si/Makefrag
+include $(src_dir)/rv64mi/Makefrag
+include $(src_dir)/rv64uamt/Makefrag
+include $(src_dir)/rv64samt/Makefrag
+
+default: all
+
+#--------------------------------------------------------------------
+# Build rules
+#--------------------------------------------------------------------
+
+RISCV_PREFIX ?= riscv$(XLEN)-unknown-elf-
+RISCV_GCC ?= $(RISCV_PREFIX)gcc
+RISCV_GCC_OPTS ?= -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles
+RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump --disassemble-all --disassemble-zeroes --section=.text --section=.text.startup --section=.text.init --section=.data
+RISCV_SIM ?= spike
+
+vpath %.S $(src_dir)
+
+#------------------------------------------------------------
+# Build assembly tests
+
+%.dump: %
+	mkdir -p $(dump_dir)
+	$(RISCV_OBJDUMP) $(bin_dir)/$< > $(dump_dir)/$@
+
+%.out: %
+	$(RISCV_SIM) --isa=rv64gc $< 2> $@
+
+define compile_template
+
+$$($(1)_ps_tests): $(1)-ps-%: $(1)/%.S
+	mkdir -p $(bin_dir)
+	$$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) -I$(src_dir)/../env/ps -I$(src_dir)/macros/scalar -I$(src_dir)/macros/mt -T$(src_dir)/../env/ps/link.ld $$< -o $(bin_dir)/$$@
+$(1)_ps_env_tests += $$($(1)_ps_tests)
+
+$(1)_tests_dump = $$(addsuffix .dump, $$($(1)_tests))
+
+$(1): $$($(1)_tests_dump)
+
+.PHONY: $(1)
+
+p_env_tests 	+= $$($(1)_p_env_tests)
+v_env_tests 	+= $$($(1)_v_env_tests)
+ps_env_tests 	+= $$($(1)_ps_env_tests)
+
+endef
+
+$(eval $(call compile_template,rv64ui,-march=rv64g -mabi=lp64))
+$(eval $(call compile_template,rv64uc,-march=rv64g -mabi=lp64))
+$(eval $(call compile_template,rv64um,-march=rv64g -mabi=lp64))
+$(eval $(call compile_template,rv64ua,-march=rv64g -mabi=lp64))
+$(eval $(call compile_template,rv64uf,-march=rv64g -mabi=lp64))
+$(eval $(call compile_template,rv64ud,-march=rv64g -mabi=lp64))
+$(eval $(call compile_template,rv64si,-march=rv64g -mabi=lp64))
+$(eval $(call compile_template,rv64mi,-march=rv64g -mabi=lp64))
+$(eval $(call compile_template,rv64uamt,-march=rv64g -mabi=lp64))
+$(eval $(call compile_template,rv64samt,-march=rv64g -mabi=lp64))
+
+ps_env_tests_dump = $(addsuffix .dump, $(ps_env_tests))
+
+#------------------------------------------------------------
+# Targets
+
+all: 	ps
+# build tests with ps environment
+ps: 	$(ps_env_tests_dump)
+
+#------------------------------------------------------------
+# Clean up
+
+clean:
+	rm -rf $(bin_dir) $(dump_dir)
diff --git a/tests/test-progs/asmtest/src/riscv/README.md b/tests/test-progs/asmtest/src/riscv/README.md
new file mode 100644
index 0000000..0b86559
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/README.md
@@ -0,0 +1,92 @@
+gem5 Specifc RISC-V tests
+=========================
+
+About
+-----
+
+This work provides assembly testing infrastructure including single-threaded
+and multi-threaded tests for RISC-V ISA in gem5. Each test targets an
+individual RISC-V instruction or a Linux system call. This work targets
+system call emulation (SE) mode in gem5.
+
+This work is based on the riscv-tests project.
+
+Link to the orignal riscv-tests projects can be found here:
+  https://github.com/riscv/riscv-tests
+
+Link to the original riscv-tests project's LICENSE and README can be found
+here:
+  https://github.com/riscv/riscv-tests/blob/master/LICENSE
+  https://github.com/riscv/riscv-tests/blob/master/README.md
+
+Specific commit ID that this work is based off:
+  68cad7baf3ed0a4553fffd14726d24519ee1296a
+
+Changes from the orignal riscv-tests project
+--------------------------------------------
+
+1. Only rv64 tests are imported into this work
+
+The original project offers both rv64 and rv32 tests. Since the current
+implementation of RISC-V in gem5 is focused on its 64-bit version, only
+64-bit tests (rv64) are imported from the original project. Future work
+on 32-bit can easily integrate all 32-bit tests into gem5.
+
+2. New testing environment for gem5
+
+Since the original riscv-tests project is designed for bare-metal system (i.e.,
+without OS support), it offers several environments to control how a test
+interacts with a host machine (to-host communication). However, in gem5 SE
+mode, gem5 emulates an OS, and there is no host machine. Therefore, we
+developed a new testing environment called `ps` for gem5.
+
+This testing environment uses system call `exit` to return test results as an
+exit code of a particular test instead of writing them to a host machine. This
+environment requires the testing platform to implement/emulate at least `exit`
+system call.
+
+3. Minimal threading library written in assembly (`isa/macros/mt`)
+
+To simplify debugging multi-threading systems, we developed a minimal threading
+library that supports very basic threading functionality including creating a
+thread, exiting a thread, waiting for some thread(s) on a condition, and waking
+up some thread(s).
+
+Multi-threaded tests can rely on this library to manage multiple threads.
+
+4. RISC-V AMO, LR, and SC instruction tests (`isa/rv64uamt`)
+
+This is a set of assembly tests that target multi-core systems and test AMO
+instructions. This test set uses a minimal number of system calls (i.e., clone,
+mmap, munmap and exit) to create and manage threads.  It does not use any
+complex sleep/wakeup mechanism to manage and synchronize threads to avoid
+adding extra unnecessary complexity. The major goal of this test set is to
+stress AMO instructions. Threads only synchronize at the end of their
+execution. The master thread does a spin-wait to wait for all threads to
+complete before it checks final results.
+
+5. Thread-related system call tests (`isa/rv64samt`)
+
+This is a set of assembly tests that target thread-related system calls and
+thread wait/wakeup behaviors. This set reuses some of the tests in
+`isa/rv64uamt` but uses more advanced futex system call operations to make
+threads wait and wake up in certain cases. This test set also checks functional
+behaviors of threads after a wait/wakeup operation.
+
+How to compile this test suite
+------------------------------
+
+1. Install RISC-V GNU toolchain. Source code and instruction on how to install
+it can be found here: https://github.com/riscv/riscv-gnu-toolchain
+
+2. Run `make`
+
+3. Test binaries are in `$GEM5/tests/test-progs/asmtest/bin/riscv/` ($GEM5 is
+your gem5 directory)
+
+How to run all tests
+--------------------
+
+1. Run `./run-tests.py`
+
+2. Test outputs are in ./test-summary.out
diff --git a/tests/test-progs/asmtest/src/riscv/env/LICENSE b/tests/test-progs/asmtest/src/riscv/env/LICENSE
new file mode 100644
index 0000000..48fe522
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2012-2015, 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/tests/test-progs/asmtest/src/riscv/env/encoding.h b/tests/test-progs/asmtest/src/riscv/env/encoding.h
new file mode 100644
index 0000000..c109ce1
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/encoding.h
@@ -0,0 +1,1471 @@
+// 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     0x00001000
+#define CLINT_BASE         0x02000000
+#define CLINT_SIZE         0x000c0000
+#define EXT_IO_BASE        0x40000000
+#define DRAM_BASE          0x80000000
+
+// 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/tests/test-progs/asmtest/src/riscv/env/p/link.ld b/tests/test-progs/asmtest/src/riscv/env/p/link.ld
new file mode 100644
index 0000000..b3e315e
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/p/link.ld
@@ -0,0 +1,17 @@
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+SECTIONS
+{
+  . = 0x80000000;
+  .text.init : { *(.text.init) }
+  . = ALIGN(0x1000);
+  .tohost : { *(.tohost) }
+  . = ALIGN(0x1000);
+  .text : { *(.text) }
+  . = ALIGN(0x1000);
+  .data : { *(.data) }
+  .bss : { *(.bss) }
+  _end = .;
+}
+
diff --git a/tests/test-progs/asmtest/src/riscv/env/p/riscv_test.h b/tests/test-progs/asmtest/src/riscv/env/p/riscv_test.h
new file mode 100644
index 0000000..3fbcb50
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/p/riscv_test.h
@@ -0,0 +1,215 @@
+// See LICENSE for license details.
+
+#ifndef _ENV_PHYSICAL_SINGLE_CORE_H
+#define _ENV_PHYSICAL_SINGLE_CORE_H
+
+#include "../encoding.h"
+
+//-----------------------------------------------------------------------
+// Begin Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_RV64U                                                    \
+  .macro init;                                                          \
+  .endm
+
+#define RVTEST_RV64UF                                                   \
+  .macro init;                                                          \
+  RVTEST_FP_ENABLE;                                                     \
+  .endm
+
+#define RVTEST_RV32U                                                    \
+  .macro init;                                                          \
+  .endm
+
+#define RVTEST_RV32UF                                                   \
+  .macro init;                                                          \
+  RVTEST_FP_ENABLE;                                                     \
+  .endm
+
+#define RVTEST_RV64M                                                    \
+  .macro init;                                                          \
+  RVTEST_ENABLE_MACHINE;                                                \
+  .endm
+
+#define RVTEST_RV64S                                                    \
+  .macro init;                                                          \
+  RVTEST_ENABLE_SUPERVISOR;                                             \
+  .endm
+
+#define RVTEST_RV32M                                                    \
+  .macro init;                                                          \
+  RVTEST_ENABLE_MACHINE;                                                \
+  .endm
+
+#define RVTEST_RV32S                                                    \
+  .macro init;                                                          \
+  RVTEST_ENABLE_SUPERVISOR;                                             \
+  .endm
+
+#if __riscv_xlen == 64
+# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bgez a0, 1f; RVTEST_PASS; 1:
+#else
+# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bltz a0, 1f; RVTEST_PASS; 1:
+#endif
+
+#define INIT_PMP                                                        \
+  la t0, 1f;                                                            \
+  csrw mtvec, t0;                                                       \
+  li t0, -1;        /* Set up a PMP to permit all accesses */           \
+  csrw pmpaddr0, t0;                                                    \
+  li t0, PMP_NAPOT | PMP_R | PMP_W | PMP_X;                             \
+  csrw pmpcfg0, t0;                                                     \
+  .align 2;                                                             \
+1:
+
+#define INIT_SATP                                                      \
+  la t0, 1f;                                                            \
+  csrw mtvec, t0;                                                       \
+  csrwi sptbr, 0;                                                       \
+  .align 2;                                                             \
+1:
+
+#define DELEGATE_NO_TRAPS                                               \
+  la t0, 1f;                                                            \
+  csrw mtvec, t0;                                                       \
+  csrwi medeleg, 0;                                                     \
+  csrwi mideleg, 0;                                                     \
+  csrwi mie, 0;                                                         \
+  .align 2;                                                             \
+1:
+
+#define RVTEST_ENABLE_SUPERVISOR                                        \
+  li a0, MSTATUS_MPP & (MSTATUS_MPP >> 1);                              \
+  csrs mstatus, a0;                                                     \
+  li a0, SIP_SSIP | SIP_STIP;                                           \
+  csrs mideleg, a0;                                                     \
+
+#define RVTEST_ENABLE_MACHINE                                           \
+  li a0, MSTATUS_MPP;                                                   \
+  csrs mstatus, a0;                                                     \
+
+#define RVTEST_FP_ENABLE                                                \
+  li a0, MSTATUS_FS & (MSTATUS_FS >> 1);                                \
+  csrs mstatus, a0;                                                     \
+  csrwi fcsr, 0
+
+#define RISCV_MULTICORE_DISABLE                                         \
+  csrr a0, mhartid;                                                     \
+  1: bnez a0, 1b
+
+#define EXTRA_TVEC_USER
+#define EXTRA_TVEC_MACHINE
+#define EXTRA_INIT
+#define EXTRA_INIT_TIMER
+
+#define INTERRUPT_HANDLER j other_exception /* No interrupts should occur */
+
+#define RVTEST_CODE_BEGIN                                               \
+        .section .text.init;                                            \
+        .align  6;                                                      \
+        .weak stvec_handler;                                            \
+        .weak mtvec_handler;                                            \
+        .globl _start;                                                  \
+_start:                                                                 \
+        /* reset vector */                                              \
+        j reset_vector;                                                 \
+        .align 2;                                                       \
+trap_vector:                                                            \
+        /* test whether the test came from pass/fail */                 \
+        csrr t5, mcause;                                                \
+        li t6, CAUSE_USER_ECALL;                                        \
+        beq t5, t6, write_tohost;                                       \
+        li t6, CAUSE_SUPERVISOR_ECALL;                                  \
+        beq t5, t6, write_tohost;                                       \
+        li t6, CAUSE_MACHINE_ECALL;                                     \
+        beq t5, t6, write_tohost;                                       \
+        /* if an mtvec_handler is defined, jump to it */                \
+        la t5, mtvec_handler;                                           \
+        beqz t5, 1f;                                                    \
+        jr t5;                                                          \
+        /* was it an interrupt or an exception? */                      \
+  1:    csrr t5, mcause;                                                \
+        bgez t5, handle_exception;                                      \
+        INTERRUPT_HANDLER;                                              \
+handle_exception:                                                       \
+        /* we don't know how to handle whatever the exception was */    \
+  other_exception:                                                      \
+        /* some unhandlable exception occurred */                       \
+  1:    ori TESTNUM, TESTNUM, 1337;                                     \
+  write_tohost:                                                         \
+        sw TESTNUM, tohost, t5;                                         \
+        j write_tohost;                                                 \
+reset_vector:                                                           \
+        RISCV_MULTICORE_DISABLE;                                        \
+        INIT_SATP;                                                     \
+        INIT_PMP;                                                       \
+        DELEGATE_NO_TRAPS;                                              \
+        li TESTNUM, 0;                                                  \
+        la t0, trap_vector;                                             \
+        csrw mtvec, t0;                                                 \
+        CHECK_XLEN;                                                     \
+        /* if an stvec_handler is defined, delegate exceptions to it */ \
+        la t0, stvec_handler;                                           \
+        beqz t0, 1f;                                                    \
+        csrw stvec, t0;                                                 \
+        li t0, (1 << CAUSE_LOAD_PAGE_FAULT) |                           \
+               (1 << CAUSE_STORE_PAGE_FAULT) |                          \
+               (1 << CAUSE_FETCH_PAGE_FAULT) |                          \
+               (1 << CAUSE_MISALIGNED_FETCH) |                          \
+               (1 << CAUSE_USER_ECALL) |                                \
+               (1 << CAUSE_BREAKPOINT);                                 \
+        csrw medeleg, t0;                                               \
+        csrr t1, medeleg;                                               \
+        bne t0, t1, other_exception;                                    \
+1:      csrwi mstatus, 0;                                               \
+        init;                                                           \
+        EXTRA_INIT;                                                     \
+        EXTRA_INIT_TIMER;                                               \
+        la t0, 1f;                                                      \
+        csrw mepc, t0;                                                  \
+        csrr a0, mhartid;                                               \
+        mret;                                                           \
+1:
+
+//-----------------------------------------------------------------------
+// End Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_CODE_END                                                 \
+        unimp
+
+//-----------------------------------------------------------------------
+// Pass/Fail Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_PASS                                                     \
+        fence;                                                          \
+        li TESTNUM, 1;                                                  \
+        ecall
+
+#define TESTNUM gp
+#define RVTEST_FAIL                                                     \
+        fence;                                                          \
+1:      beqz TESTNUM, 1b;                                               \
+        sll TESTNUM, TESTNUM, 1;                                        \
+        or TESTNUM, TESTNUM, 1;                                         \
+        ecall
+
+//-----------------------------------------------------------------------
+// Data Section Macro
+//-----------------------------------------------------------------------
+
+#define EXTRA_DATA
+
+#define RVTEST_DATA_BEGIN                                               \
+        EXTRA_DATA                                                      \
+        .pushsection .tohost,"aw",@progbits;                            \
+        .align 6; .global tohost; tohost: .dword 0;                     \
+        .align 6; .global fromhost; fromhost: .dword 0;                 \
+        .popsection;                                                    \
+        .align 4; .global begin_signature; begin_signature:
+
+#define RVTEST_DATA_END .align 4; .global end_signature; end_signature:
+
+#endif
diff --git a/tests/test-progs/asmtest/src/riscv/env/pm/link.ld b/tests/test-progs/asmtest/src/riscv/env/pm/link.ld
new file mode 120000
index 0000000..86b45f9
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/pm/link.ld
@@ -0,0 +1 @@
+../p/link.ld
\ No newline at end of file
diff --git a/tests/test-progs/asmtest/src/riscv/env/pm/riscv_test.h b/tests/test-progs/asmtest/src/riscv/env/pm/riscv_test.h
new file mode 100644
index 0000000..38a0e86
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/pm/riscv_test.h
@@ -0,0 +1,11 @@
+// See LICENSE for license details.
+
+#ifndef _ENV_PHYSICAL_MULTI_CORE_H
+#define _ENV_PHYSICAL_MULTI_CORE_H
+
+#include "../p/riscv_test.h"
+
+#undef RISCV_MULTICORE_DISABLE
+#define RISCV_MULTICORE_DISABLE
+
+#endif
diff --git a/tests/test-progs/asmtest/src/riscv/env/ps/link.ld b/tests/test-progs/asmtest/src/riscv/env/ps/link.ld
new file mode 100644
index 0000000..b3e315e
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/ps/link.ld
@@ -0,0 +1,17 @@
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+SECTIONS
+{
+  . = 0x80000000;
+  .text.init : { *(.text.init) }
+  . = ALIGN(0x1000);
+  .tohost : { *(.tohost) }
+  . = ALIGN(0x1000);
+  .text : { *(.text) }
+  . = ALIGN(0x1000);
+  .data : { *(.data) }
+  .bss : { *(.bss) }
+  _end = .;
+}
+
diff --git a/tests/test-progs/asmtest/src/riscv/env/ps/riscv_test.h b/tests/test-progs/asmtest/src/riscv/env/ps/riscv_test.h
new file mode 100644
index 0000000..8fcb7ab
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/ps/riscv_test.h
@@ -0,0 +1,170 @@
+// See LICENSE for license details.
+
+#ifndef _ENV_PHYSICAL_SINGLE_CORE_H
+#define _ENV_PHYSICAL_SINGLE_CORE_H
+
+#include "../encoding.h"
+
+//-----------------------------------------------------------------------
+// Begin Macro
+//-----------------------------------------------------------------------
+
+#define RVTEST_RV64U                                                    \
+  .macro init;                                                          \
+  .endm
+
+#define RVTEST_RV64UF                                                   \
+  .macro init;                                                          \
+  RVTEST_FP_ENABLE;                                                     \
+  .endm
+
+#define RVTEST_RV32U                                                    \
+  .macro init;                                                          \
+  .endm
+
+#define RVTEST_RV32UF                                                   \
+  .macro init;                                                          \
+  RVTEST_FP_ENABLE;                                                     \
+  .endm
+
+#define RVTEST_RV64M                                                    \
+  .macro init;                                                          \
+  RVTEST_ENABLE_MACHINE;                                                \
+  .endm
+
+#define RVTEST_RV64S                                                    \
+  .macro init;                                                          \
+  RVTEST_ENABLE_SUPERVISOR;                                             \
+  .endm
+
+#define RVTEST_RV32M                                                    \
+  .macro init;                                                          \
+  RVTEST_ENABLE_MACHINE;                                                \
+  .endm
+
+#define RVTEST_RV32S                                                    \
+  .macro init;                                                          \
+  RVTEST_ENABLE_SUPERVISOR;                                             \
+  .endm
+
+#if __riscv_xlen == 64
+# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bgez a0, 1f; RVTEST_PASS; 1:
+#else
+# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bltz a0, 1f; RVTEST_PASS; 1:
+#endif
+
+#define INIT_PMP                                                        \
+  la t0, 1f;                                                            \
+  csrw mtvec, t0;                                                       \
+  li t0, -1;        /* Set up a PMP to permit all accesses */           \
+  csrw pmpaddr0, t0;                                                    \
+  li t0, PMP_NAPOT | PMP_R | PMP_W | PMP_X;                             \
+  csrw pmpcfg0, t0;                                                     \
+  .align 2;                                                             \
+1:
+
+#define INIT_SATP                                                      \
+  la t0, 1f;                                                            \
+  csrw mtvec, t0;                                                       \
+  csrwi sptbr, 0;                                                       \
+  .align 2;                                                             \
+1:
+
+#define DELEGATE_NO_TRAPS                                               \
+  la t0, 1f;                                                            \
+  csrw mtvec, t0;                                                       \
+  csrwi medeleg, 0;                                                     \
+  csrwi mideleg, 0;                                                     \
+  csrwi mie, 0;                                                         \
+  .align 2;                                                             \
+1:
+
+#define RVTEST_ENABLE_SUPERVISOR                                        \
+  li a0, MSTATUS_MPP & (MSTATUS_MPP >> 1);                              \
+  csrs mstatus, a0;                                                     \
+  li a0, SIP_SSIP | SIP_STIP;                                           \
+  csrs mideleg, a0;                                                     \
+
+#define RVTEST_ENABLE_MACHINE                                           \
+  li a0, MSTATUS_MPP;                                                   \
+  csrs mstatus, a0;                                                     \
+
+#define RVTEST_FP_ENABLE                                                \
+  li a0, MSTATUS_FS & (MSTATUS_FS >> 1);                                \
+  csrs mstatus, a0;                                                     \
+  csrwi fcsr, 0
+
+#define RISCV_MULTICORE_DISABLE                                         \
+  csrr a0, mhartid;                                                     \
+  1: bnez a0, 1b
+
+#define EXTRA_TVEC_USER
+#define EXTRA_TVEC_MACHINE
+#define EXTRA_INIT
+#define EXTRA_INIT_TIMER
+
+//-----------------------------------------------------------------------
+// Begin Macro
+//    Jump to the first test case
+//-----------------------------------------------------------------------
+
+#define RVTEST_CODE_BEGIN                                               \
+        .section .text.init;                                            \
+        .align  6;                                                      \
+        .weak stvec_handler;                                            \
+        .weak mtvec_handler;                                            \
+        .globl _start;                                                  \
+_start:                                                                 \
+        la t0, 1f;                                                      \
+        jr t0;                                                          \
+        .align 2;                                                       \
+1:
+
+//-----------------------------------------------------------------------
+// RVTEST_CODE_END Macro
+//    Call exit syscall to terminate the simulation
+//-----------------------------------------------------------------------
+
+#define EXIT_SYSCALL 93
+#define RVTEST_CODE_END                                                 \
+        li a7, EXIT_SYSCALL;                                            \
+        ecall
+
+//-----------------------------------------------------------------------
+// RVTEST_PASS Macro
+//    Pass 0 as a return code to an EXIT ecall
+//-----------------------------------------------------------------------
+
+#define TESTNUM gp
+#define RVTEST_PASS                                                     \
+        fence;                                                          \
+        li a0, 0;
+
+//-----------------------------------------------------------------------
+// RVTEST_FAIL Macro
+//    Pass test case number as a return code to an EXIT ecall
+//-----------------------------------------------------------------------
+
+#define TESTNUM gp
+#define RVTEST_FAIL                                                     \
+        fence;                                                          \
+        mv a0, TESTNUM;                                                 \
+        RVTEST_CODE_END
+
+//-----------------------------------------------------------------------
+// Data Section Macro
+//-----------------------------------------------------------------------
+
+#define EXTRA_DATA
+
+#define RVTEST_DATA_BEGIN                                               \
+        EXTRA_DATA                                                      \
+        .pushsection .tohost,"aw",@progbits;                            \
+        .align 6; .global tohost; tohost: .dword 0;                     \
+        .align 6; .global fromhost; fromhost: .dword 0;                 \
+        .popsection;                                                    \
+        .align 4; .global begin_signature; begin_signature:
+
+#define RVTEST_DATA_END .align 4; .global end_signature; end_signature:
+
+#endif
diff --git a/tests/test-progs/asmtest/src/riscv/env/pt/link.ld b/tests/test-progs/asmtest/src/riscv/env/pt/link.ld
new file mode 120000
index 0000000..86b45f9
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/pt/link.ld
@@ -0,0 +1 @@
+../p/link.ld
\ No newline at end of file
diff --git a/tests/test-progs/asmtest/src/riscv/env/pt/riscv_test.h b/tests/test-progs/asmtest/src/riscv/env/pt/riscv_test.h
new file mode 100644
index 0000000..34c2a33
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/pt/riscv_test.h
@@ -0,0 +1,69 @@
+// See LICENSE for license details.
+
+#ifndef _ENV_PHYSICAL_SINGLE_CORE_TIMER_H
+#define _ENV_PHYSICAL_SINGLE_CORE_TIMER_H
+
+#include "../p/riscv_test.h"
+
+#define TIMER_INTERVAL 2
+
+#undef EXTRA_INIT_TIMER
+#define EXTRA_INIT_TIMER                                                \
+        li a0, MIP_MTIP;                                                \
+        csrs mie, a0;                                                   \
+        csrr a0, mtime;                                                 \
+        addi a0, a0, TIMER_INTERVAL;                                    \
+        csrw mtimecmp, a0;                                              \
+
+#if SSTATUS_XS != 0x18000
+# error
+#endif
+#define XS_SHIFT 15
+
+#undef INTERRUPT_HANDLER
+#define INTERRUPT_HANDLER                                               \
+        slli t5, t5, 1;                                                 \
+        srli t5, t5, 1;                                                 \
+        add t5, t5, -IRQ_M_TIMER;                                       \
+        bnez t5, other_exception; /* other interrups shouldn't happen */\
+        csrr t5, mtime;                                                 \
+        addi t5, t5, TIMER_INTERVAL;                                    \
+        csrw mtimecmp, t5;                                              \
+        mret;                                                           \
+
+//-----------------------------------------------------------------------
+// Data Section Macro
+//-----------------------------------------------------------------------
+
+#undef EXTRA_DATA
+#define EXTRA_DATA                                                      \
+        .align 3;                                                       \
+regspill:                                                               \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+        .dword 0xdeadbeefcafebabe;                                      \
+evac:                                                                   \
+        .skip 32768;                                                    \
+
+#endif
diff --git a/tests/test-progs/asmtest/src/riscv/env/v/entry.S b/tests/test-progs/asmtest/src/riscv/env/v/entry.S
new file mode 100644
index 0000000..9719662
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/v/entry.S
@@ -0,0 +1,125 @@
+#include "riscv_test.h"
+
+#if __riscv_xlen == 64
+# define STORE    sd
+# define LOAD     ld
+# define REGBYTES 8
+#else
+# define STORE    sw
+# define LOAD     lw
+# define REGBYTES 4
+#endif
+
+#define STACK_TOP (_end + 4096)
+
+  .section ".text.init","ax",@progbits
+  .globl _start
+_start:
+  j handle_reset
+
+  /* NMI vector */
+nmi_vector:
+  j wtf
+
+trap_vector:
+  j wtf
+
+handle_reset:
+  la t0, trap_vector
+  csrw mtvec, t0
+  la sp, STACK_TOP - SIZEOF_TRAPFRAME_T
+  csrr t0, mhartid
+  slli t0, t0, 12
+  add sp, sp, t0
+  csrw mscratch, sp
+  la a0, userstart
+  j vm_boot
+
+  .globl  pop_tf
+pop_tf:
+  LOAD  t0,33*REGBYTES(a0)
+  csrw  sepc,t0
+  LOAD  x1,1*REGBYTES(a0)
+  LOAD  x2,2*REGBYTES(a0)
+  LOAD  x3,3*REGBYTES(a0)
+  LOAD  x4,4*REGBYTES(a0)
+  LOAD  x5,5*REGBYTES(a0)
+  LOAD  x6,6*REGBYTES(a0)
+  LOAD  x7,7*REGBYTES(a0)
+  LOAD  x8,8*REGBYTES(a0)
+  LOAD  x9,9*REGBYTES(a0)
+  LOAD  x11,11*REGBYTES(a0)
+  LOAD  x12,12*REGBYTES(a0)
+  LOAD  x13,13*REGBYTES(a0)
+  LOAD  x14,14*REGBYTES(a0)
+  LOAD  x15,15*REGBYTES(a0)
+  LOAD  x16,16*REGBYTES(a0)
+  LOAD  x17,17*REGBYTES(a0)
+  LOAD  x18,18*REGBYTES(a0)
+  LOAD  x19,19*REGBYTES(a0)
+  LOAD  x20,20*REGBYTES(a0)
+  LOAD  x21,21*REGBYTES(a0)
+  LOAD  x22,22*REGBYTES(a0)
+  LOAD  x23,23*REGBYTES(a0)
+  LOAD  x24,24*REGBYTES(a0)
+  LOAD  x25,25*REGBYTES(a0)
+  LOAD  x26,26*REGBYTES(a0)
+  LOAD  x27,27*REGBYTES(a0)
+  LOAD  x28,28*REGBYTES(a0)
+  LOAD  x29,29*REGBYTES(a0)
+  LOAD  x30,30*REGBYTES(a0)
+  LOAD  x31,31*REGBYTES(a0)
+  LOAD  a0,10*REGBYTES(a0)
+  sret
+
+  .global  trap_entry
+trap_entry:
+  csrrw sp, sscratch, sp
+
+  # save gprs
+  STORE  x1,1*REGBYTES(sp)
+  STORE  x3,3*REGBYTES(sp)
+  STORE  x4,4*REGBYTES(sp)
+  STORE  x5,5*REGBYTES(sp)
+  STORE  x6,6*REGBYTES(sp)
+  STORE  x7,7*REGBYTES(sp)
+  STORE  x8,8*REGBYTES(sp)
+  STORE  x9,9*REGBYTES(sp)
+  STORE  x10,10*REGBYTES(sp)
+  STORE  x11,11*REGBYTES(sp)
+  STORE  x12,12*REGBYTES(sp)
+  STORE  x13,13*REGBYTES(sp)
+  STORE  x14,14*REGBYTES(sp)
+  STORE  x15,15*REGBYTES(sp)
+  STORE  x16,16*REGBYTES(sp)
+  STORE  x17,17*REGBYTES(sp)
+  STORE  x18,18*REGBYTES(sp)
+  STORE  x19,19*REGBYTES(sp)
+  STORE  x20,20*REGBYTES(sp)
+  STORE  x21,21*REGBYTES(sp)
+  STORE  x22,22*REGBYTES(sp)
+  STORE  x23,23*REGBYTES(sp)
+  STORE  x24,24*REGBYTES(sp)
+  STORE  x25,25*REGBYTES(sp)
+  STORE  x26,26*REGBYTES(sp)
+  STORE  x27,27*REGBYTES(sp)
+  STORE  x28,28*REGBYTES(sp)
+  STORE  x29,29*REGBYTES(sp)
+  STORE  x30,30*REGBYTES(sp)
+  STORE  x31,31*REGBYTES(sp)
+
+  csrrw  t0,sscratch,sp
+  STORE  t0,2*REGBYTES(sp)
+
+  # get sr, epc, badvaddr, cause
+  csrr   t0,sstatus
+  STORE  t0,32*REGBYTES(sp)
+  csrr   t0,sepc
+  STORE  t0,33*REGBYTES(sp)
+  csrr   t0,sbadaddr
+  STORE  t0,34*REGBYTES(sp)
+  csrr   t0,scause
+  STORE  t0,35*REGBYTES(sp)
+
+  move  a0, sp
+  j handle_trap
diff --git a/tests/test-progs/asmtest/src/riscv/env/v/link.ld b/tests/test-progs/asmtest/src/riscv/env/v/link.ld
new file mode 120000
index 0000000..86b45f9
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/v/link.ld
@@ -0,0 +1 @@
+../p/link.ld
\ No newline at end of file
diff --git a/tests/test-progs/asmtest/src/riscv/env/v/riscv_test.h b/tests/test-progs/asmtest/src/riscv/env/v/riscv_test.h
new file mode 100644
index 0000000..8ca9ffd
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/v/riscv_test.h
@@ -0,0 +1,71 @@
+// See LICENSE for license details.
+
+#ifndef _ENV_VIRTUAL_SINGLE_CORE_H
+#define _ENV_VIRTUAL_SINGLE_CORE_H
+
+#include "../p/riscv_test.h"
+
+//-----------------------------------------------------------------------
+// Begin Macro
+//-----------------------------------------------------------------------
+
+#undef RVTEST_FP_ENABLE
+#define RVTEST_FP_ENABLE fssr x0
+
+#undef RVTEST_CODE_BEGIN
+#define RVTEST_CODE_BEGIN                                               \
+        .text;                                                          \
+        .global userstart;                                              \
+userstart:                                                              \
+        init
+
+//-----------------------------------------------------------------------
+// Pass/Fail Macro
+//-----------------------------------------------------------------------
+
+#undef RVTEST_PASS
+#define RVTEST_PASS li a0, 1; scall
+
+#undef RVTEST_FAIL
+#define RVTEST_FAIL sll a0, TESTNUM, 1; 1:beqz a0, 1b; or a0, a0, 1; scall;
+
+//-----------------------------------------------------------------------
+// Data Section Macro
+//-----------------------------------------------------------------------
+
+#undef RVTEST_DATA_END
+#define RVTEST_DATA_END
+
+//-----------------------------------------------------------------------
+// Supervisor mode definitions and macros
+//-----------------------------------------------------------------------
+
+#define MAX_TEST_PAGES 63 // this must be the period of the LFSR below
+#define LFSR_NEXT(x) (((((x)^((x)>>1)) & 1) << 5) | ((x) >> 1))
+
+#define PGSHIFT 12
+#define PGSIZE (1UL << PGSHIFT)
+
+#define SIZEOF_TRAPFRAME_T ((__riscv_xlen / 8) * 36)
+
+#ifndef __ASSEMBLER__
+
+typedef unsigned long pte_t;
+#define LEVELS (sizeof(pte_t) == sizeof(uint64_t) ? 3 : 2)
+#define PTIDXBITS (PGSHIFT - (sizeof(pte_t) == 8 ? 3 : 2))
+#define VPN_BITS (PTIDXBITS * LEVELS)
+#define VA_BITS (VPN_BITS + PGSHIFT)
+#define PTES_PER_PT (1UL << RISCV_PGLEVEL_BITS)
+#define MEGAPAGE_SIZE (PTES_PER_PT * PGSIZE)
+
+typedef struct
+{
+  long gpr[32];
+  long sr;
+  long epc;
+  long badvaddr;
+  long cause;
+} trapframe_t;
+#endif
+
+#endif
diff --git a/tests/test-progs/asmtest/src/riscv/env/v/string.c b/tests/test-progs/asmtest/src/riscv/env/v/string.c
new file mode 100644
index 0000000..4ffedc0
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/v/string.c
@@ -0,0 +1,114 @@
+#include <string.h>
+#include <stdint.h>
+#include <ctype.h>
+
+void* memcpy(void* dest, const void* src, size_t len)
+{
+  if ((((uintptr_t)dest | (uintptr_t)src | len) & (sizeof(uintptr_t)-1)) == 0) {
+    const uintptr_t* s = src;
+    uintptr_t *d = dest;
+    while (d < (uintptr_t*)(dest + len))
+      *d++ = *s++;
+  } else {
+    const char* s = src;
+    char *d = dest;
+    while (d < (char*)(dest + len))
+      *d++ = *s++;
+  }
+  return dest;
+}
+
+void* memset(void* dest, int byte, size_t len)
+{
+  if ((((uintptr_t)dest | len) & (sizeof(uintptr_t)-1)) == 0) {
+    uintptr_t word = byte & 0xFF;
+    word |= word << 8;
+    word |= word << 16;
+    word |= word << 16 << 16;
+
+    uintptr_t *d = dest;
+    while (d < (uintptr_t*)(dest + len))
+      *d++ = word;
+  } else {
+    char *d = dest;
+    while (d < (char*)(dest + len))
+      *d++ = byte;
+  }
+  return dest;
+}
+
+size_t strlen(const char *s)
+{
+  const char *p = s;
+  while (*p)
+    p++;
+  return p - s;
+}
+
+int strcmp(const char* s1, const char* s2)
+{
+  unsigned char c1, c2;
+
+  do {
+    c1 = *s1++;
+    c2 = *s2++;
+  } while (c1 != 0 && c1 == c2);
+
+  return c1 - c2;
+}
+
+int memcmp(const void* s1, const void* s2, size_t n)
+{
+  if ((((uintptr_t)s1 | (uintptr_t)s2) & (sizeof(uintptr_t)-1)) == 0) {
+    const uintptr_t* u1 = s1;
+    const uintptr_t* u2 = s2;
+    const uintptr_t* end = u1 + (n / sizeof(uintptr_t));
+    while (u1 < end) {
+      if (*u1 != *u2)
+        break;
+      u1++;
+      u2++;
+    }
+    n -= (const void*)u1 - s1;
+    s1 = u1;
+    s2 = u2;
+  }
+
+  while (n--) {
+    unsigned char c1 = *(const unsigned char*)s1++;
+    unsigned char c2 = *(const unsigned char*)s2++;
+    if (c1 != c2)
+      return c1 - c2;
+  }
+
+  return 0;
+}
+
+char* strcpy(char* dest, const char* src)
+{
+  char* d = dest;
+  while ((*d++ = *src++))
+    ;
+  return dest;
+}
+
+long atol(const char* str)
+{
+  long res = 0;
+  int sign = 0;
+
+  while (*str == ' ')
+    str++;
+
+  if (*str == '-' || *str == '+') {
+    sign = *str == '-';
+    str++;
+  }
+
+  while (*str) {
+    res *= 10;
+    res += *str++ - '0';
+  }
+
+  return sign ? -res : res;
+}
diff --git a/tests/test-progs/asmtest/src/riscv/env/v/vm.c b/tests/test-progs/asmtest/src/riscv/env/v/vm.c
new file mode 100644
index 0000000..a2e5533
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/env/v/vm.c
@@ -0,0 +1,273 @@
+// See LICENSE for license details.
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "riscv_test.h"
+
+void trap_entry();
+void pop_tf(trapframe_t*);
+
+volatile uint64_t tohost;
+volatile uint64_t fromhost;
+
+static void do_tohost(uint64_t tohost_value)
+{
+  while (tohost)
+    fromhost = 0;
+  tohost = tohost_value;
+}
+
+#define pa2kva(pa) ((void*)(pa) - DRAM_BASE - MEGAPAGE_SIZE)
+#define uva2kva(pa) ((void*)(pa) - MEGAPAGE_SIZE)
+
+#define flush_page(addr) asm volatile ("sfence.vma %0" : : "r" (addr) : "memory")
+
+static uint64_t lfsr63(uint64_t x)
+{
+  uint64_t bit = (x ^ (x >> 1)) & 1;
+  return (x >> 1) | (bit << 62);
+}
+
+static void cputchar(int x)
+{
+  do_tohost(0x0101000000000000 | (unsigned char)x);
+}
+
+static void cputstring(const char* s)
+{
+  while (*s)
+    cputchar(*s++);
+}
+
+static void terminate(int code)
+{
+  do_tohost(code);
+  while (1);
+}
+
+void wtf()
+{
+  terminate(841);
+}
+
+#define stringify1(x) #x
+#define stringify(x) stringify1(x)
+#define assert(x) do { \
+  if (x) break; \
+  cputstring("Assertion failed: " stringify(x) "\n"); \
+  terminate(3); \
+} while(0)
+
+#define l1pt pt[0]
+#define user_l2pt pt[1]
+#if __riscv_xlen == 64
+# define NPT 4
+#define kernel_l2pt pt[2]
+# define user_l3pt pt[3]
+#else
+# define NPT 2
+# define user_l3pt user_l2pt
+#endif
+pte_t pt[NPT][PTES_PER_PT] __attribute__((aligned(PGSIZE)));
+
+typedef struct { pte_t addr; void* next; } freelist_t;
+
+freelist_t user_mapping[MAX_TEST_PAGES];
+freelist_t freelist_nodes[MAX_TEST_PAGES];
+freelist_t *freelist_head, *freelist_tail;
+
+void printhex(uint64_t x)
+{
+  char str[17];
+  for (int i = 0; i < 16; i++)
+  {
+    str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10);
+    x >>= 4;
+  }
+  str[16] = 0;
+
+  cputstring(str);
+}
+
+static void evict(unsigned long addr)
+{
+  assert(addr >= PGSIZE && addr < MAX_TEST_PAGES * PGSIZE);
+  addr = addr/PGSIZE*PGSIZE;
+
+  freelist_t* node = &user_mapping[addr/PGSIZE];
+  if (node->addr)
+  {
+    // check accessed and dirty bits
+    assert(user_l3pt[addr/PGSIZE] & PTE_A);
+    uintptr_t sstatus = set_csr(sstatus, SSTATUS_SUM);
+    if (memcmp((void*)addr, uva2kva(addr), PGSIZE)) {
+      assert(user_l3pt[addr/PGSIZE] & PTE_D);
+      memcpy((void*)addr, uva2kva(addr), PGSIZE);
+    }
+    write_csr(sstatus, sstatus);
+
+    user_mapping[addr/PGSIZE].addr = 0;
+
+    if (freelist_tail == 0)
+      freelist_head = freelist_tail = node;
+    else
+    {
+      freelist_tail->next = node;
+      freelist_tail = node;
+    }
+  }
+}
+
+void handle_fault(uintptr_t addr, uintptr_t cause)
+{
+  assert(addr >= PGSIZE && addr < MAX_TEST_PAGES * PGSIZE);
+  addr = addr/PGSIZE*PGSIZE;
+
+  if (user_l3pt[addr/PGSIZE]) {
+    if (!(user_l3pt[addr/PGSIZE] & PTE_A)) {
+      user_l3pt[addr/PGSIZE] |= PTE_A;
+    } else {
+      assert(!(user_l3pt[addr/PGSIZE] & PTE_D) && cause == CAUSE_STORE_PAGE_FAULT);
+      user_l3pt[addr/PGSIZE] |= PTE_D;
+    }
+    flush_page(addr);
+    return;
+  }
+
+  freelist_t* node = freelist_head;
+  assert(node);
+  freelist_head = node->next;
+  if (freelist_head == freelist_tail)
+    freelist_tail = 0;
+
+  uintptr_t new_pte = (node->addr >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V | PTE_U | PTE_R | PTE_W | PTE_X;
+  user_l3pt[addr/PGSIZE] = new_pte | PTE_A | PTE_D;
+  flush_page(addr);
+
+  assert(user_mapping[addr/PGSIZE].addr == 0);
+  user_mapping[addr/PGSIZE] = *node;
+
+  uintptr_t sstatus = set_csr(sstatus, SSTATUS_SUM);
+  memcpy((void*)addr, uva2kva(addr), PGSIZE);
+  write_csr(sstatus, sstatus);
+
+  user_l3pt[addr/PGSIZE] = new_pte;
+  flush_page(addr);
+
+  __builtin___clear_cache(0,0);
+}
+
+void handle_trap(trapframe_t* tf)
+{
+  if (tf->cause == CAUSE_USER_ECALL)
+  {
+    int n = tf->gpr[10];
+
+    for (long i = 1; i < MAX_TEST_PAGES; i++)
+      evict(i*PGSIZE);
+
+    terminate(n);
+  }
+  else if (tf->cause == CAUSE_ILLEGAL_INSTRUCTION)
+  {
+    assert(tf->epc % 4 == 0);
+
+    int* fssr;
+    asm ("jal %0, 1f; fssr x0; 1:" : "=r"(fssr));
+
+    if (*(int*)tf->epc == *fssr)
+      terminate(1); // FP test on non-FP hardware.  "succeed."
+    else
+      assert(!"illegal instruction");
+    tf->epc += 4;
+  }
+  else if (tf->cause == CAUSE_FETCH_PAGE_FAULT || tf->cause == CAUSE_LOAD_PAGE_FAULT || tf->cause == CAUSE_STORE_PAGE_FAULT)
+    handle_fault(tf->badvaddr, tf->cause);
+  else
+    assert(!"unexpected exception");
+
+  pop_tf(tf);
+}
+
+static void coherence_torture()
+{
+  // cause coherence misses without affecting program semantics
+  unsigned int random = ENTROPY;
+  while (1) {
+    uintptr_t paddr = DRAM_BASE + ((random % (2 * (MAX_TEST_PAGES + 1) * PGSIZE)) & -4);
+#ifdef __riscv_atomic
+    if (random & 1) // perform a no-op write
+      asm volatile ("amoadd.w zero, zero, (%0)" :: "r"(paddr));
+    else // perform a read
+#endif
+      asm volatile ("lw zero, (%0)" :: "r"(paddr));
+    random = lfsr63(random);
+  }
+}
+
+void vm_boot(uintptr_t test_addr)
+{
+  unsigned int random = ENTROPY;
+  if (read_csr(mhartid) > 0)
+    coherence_torture();
+
+  _Static_assert(SIZEOF_TRAPFRAME_T == sizeof(trapframe_t), "???");
+
+#if (MAX_TEST_PAGES > PTES_PER_PT) || (DRAM_BASE % MEGAPAGE_SIZE) != 0
+# error
+#endif
+  // map user to lowermost megapage
+  l1pt[0] = ((pte_t)user_l2pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V;
+  // map kernel to uppermost megapage
+#if __riscv_xlen == 64
+  l1pt[PTES_PER_PT-1] = ((pte_t)kernel_l2pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V;
+  kernel_l2pt[PTES_PER_PT-1] = (DRAM_BASE/RISCV_PGSIZE << PTE_PPN_SHIFT) | PTE_V | PTE_R | PTE_W | PTE_X | PTE_A | PTE_D;
+  user_l2pt[0] = ((pte_t)user_l3pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V;
+  uintptr_t vm_choice = SATP_MODE_SV39;
+#else
+  l1pt[PTES_PER_PT-1] = (DRAM_BASE/RISCV_PGSIZE << PTE_PPN_SHIFT) | PTE_V | PTE_R | PTE_W | PTE_X | PTE_A | PTE_D;
+  uintptr_t vm_choice = SATP_MODE_SV32;
+#endif
+  write_csr(sptbr, ((uintptr_t)l1pt >> PGSHIFT) |
+                   (vm_choice * (SATP_MODE & ~(SATP_MODE<<1))));
+
+  // Set up PMPs if present, ignoring illegal instruction trap if not.
+  uintptr_t pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X;
+  asm volatile ("la t0, 1f\n\t"
+                "csrrw t0, mtvec, t0\n\t"
+                "csrw pmpaddr0, %1\n\t"
+                "csrw pmpcfg0, %0\n\t"
+                ".align 2\n\t"
+                "1:"
+                : : "r" (pmpc), "r" (-1UL) : "t0");
+
+  // set up supervisor trap handling
+  write_csr(stvec, pa2kva(trap_entry));
+  write_csr(sscratch, pa2kva(read_csr(mscratch)));
+  write_csr(medeleg,
+    (1 << CAUSE_USER_ECALL) |
+    (1 << CAUSE_FETCH_PAGE_FAULT) |
+    (1 << CAUSE_LOAD_PAGE_FAULT) |
+    (1 << CAUSE_STORE_PAGE_FAULT));
+  // FPU on; accelerator on; allow supervisor access to user memory access
+  write_csr(mstatus, MSTATUS_FS | MSTATUS_XS);
+  write_csr(mie, 0);
+
+  random = 1 + (random % MAX_TEST_PAGES);
+  freelist_head = pa2kva((void*)&freelist_nodes[0]);
+  freelist_tail = pa2kva(&freelist_nodes[MAX_TEST_PAGES-1]);
+  for (long i = 0; i < MAX_TEST_PAGES; i++)
+  {
+    freelist_nodes[i].addr = DRAM_BASE + (MAX_TEST_PAGES + random)*PGSIZE;
+    freelist_nodes[i].next = pa2kva(&freelist_nodes[i+1]);
+    random = LFSR_NEXT(random);
+  }
+  freelist_nodes[MAX_TEST_PAGES-1].next = 0;
+
+  trapframe_t tf;
+  memset(&tf, 0, sizeof(tf));
+  tf.epc = test_addr - DRAM_BASE;
+  pop_tf(&tf);
+}
diff --git a/tests/test-progs/asmtest/src/riscv/isa/.gitignore b/tests/test-progs/asmtest/src/riscv/isa/.gitignore
new file mode 100644
index 0000000..c93c5ff
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/.gitignore
@@ -0,0 +1 @@
+rv*-*
diff --git a/tests/test-progs/asmtest/src/riscv/isa/macros/mt/test_macros_mt.h b/tests/test-progs/asmtest/src/riscv/isa/macros/mt/test_macros_mt.h
new file mode 100644
index 0000000..26559cc
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/macros/mt/test_macros_mt.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This test_macros includes necessary functions and macros to create
+// and exit threads. They're used in multi-threaded assembly tests.
+// This assumes the target system can concurrently support 4 different
+// threads (i.e., 1 master thread and 3 child threads)
+//------------------------------------------------------------------------
+
+#ifndef __TEST_MACROS_MT_H
+#define __TEST_MACROS_MT_H
+
+#define SYSCALL_MMAP    222
+#define SYSCALL_MUNMAP  215
+#define SYSCALL_CLONE   220
+
+#define STACK_SIZE      (4096 * 1024)
+
+#define PROT_READ	      0x1
+#define PROT_WRITE	    0x2
+#define MMAP_PROT_FLAGS (PROT_READ | PROT_WRITE)
+
+#define MAP_PRIVATE	    0x02
+#define MAP_ANONYMOUS	  0x20
+#define MAP_STACK	      0x20000
+#define MMAP_MAP_FLAGS  (MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK)
+
+#define CLONE_VM	      0x00000100
+#define CLONE_FS	      0x00000200
+#define CLONE_FILES	    0x00000400
+#define CLONE_SIGHAND	  0x00000800
+#define CLONE_PARENT	  0x00008000
+#define CLONE_THREAD	  0x00010000
+#define CLONE_IO		    0x80000000
+#define CLONE_FLAGS     (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND\
+                         | CLONE_PARENT | CLONE_THREAD | CLONE_IO)
+
+#define NUM_THREADS     3
+
+#define FAILURE         1
+#define SUCCESS         0
+
+#define HARTID          0xF14
+
+//------------------------------------------------------------------------
+// create NUM_THREADS child threads
+//------------------------------------------------------------------------
+_create_threads:
+  li      t0, NUM_THREADS
+  mv      s0, ra                  // save return register
+1:
+  jal     ra, _alloc_stack
+  addi    sp, sp, -8
+  sd      a0, (sp)                // save pointer to the new stack
+  jal     ra, _clone_thread       // clone a new thread
+  addi    t0, t0, -1
+  bnez    t0, 1b
+  mv      ra, s0                  // restore return register
+  ret
+
+_alloc_stack:
+  li      a0, 0
+  li      a1, STACK_SIZE
+  li      a2, MMAP_PROT_FLAGS
+  li      a3, MMAP_MAP_FLAGS
+  li      a4, -1
+  li      a5, 0
+  li      a7, SYSCALL_MMAP
+  ecall
+  ret
+
+_clone_thread:
+  li      a1, STACK_SIZE
+  add     a1, a1, a0
+  li      a0, CLONE_FLAGS
+  li      a7, SYSCALL_CLONE
+  ecall
+  beqz    a0, _mt_test
+  ret
+
+//------------------------------------------------------------------------
+// wait for all child threads to exit
+//------------------------------------------------------------------------
+_join:
+  la      t0, barrier
+  li      t1, NUM_THREADS
+1:
+  ld      t2, (t0)
+  bne     t1, t2, 1b
+  ret
+
+//------------------------------------------------------------------------
+// deallocate NUM_THREADS child threads
+//------------------------------------------------------------------------
+_delete_threads:
+  li      t0, NUM_THREADS
+  mv      s0, ra                  // save return register
+1:
+  ld      a0, (sp)                // pop the new stack's pointer
+  addi    sp, sp, 8
+  jal     ra, _dealloc_stack
+  addi    t0, t0, -1
+  bnez    t0, 1b
+  mv      ra, s0                  // restore return register
+  ret
+
+_dealloc_stack:
+  li      a1, STACK_SIZE
+  li      a7, SYSCALL_MUNMAP
+  ecall
+  ret
+
+#define MT_DATA                                                           \
+  shared_var:   .dword    0;                                              \
+  barrier:      .dword    0;                                              \
+  array:        .dword    0x00000000deadbeef,                             \
+                          0xdeadbeefdeadbeef,                             \
+                          0x12343eeaaf423451;                             \
+
+#endif
diff --git a/tests/test-progs/asmtest/src/riscv/isa/macros/mt/test_macros_mt_ecall.h b/tests/test-progs/asmtest/src/riscv/isa/macros/mt/test_macros_mt_ecall.h
new file mode 100644
index 0000000..cbc4343
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/macros/mt/test_macros_mt_ecall.h
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This test_macros includes necessary functions and macros to create
+// and exit threads. They're used in multi-threaded assembly tests.
+// This assumes the target system can concurrently support 4 different
+// threads (i.e., 1 master thread and 3 child threads).
+//
+// Threads are synchronized through futex system call (i.e., wait and
+// wakeup operations).
+//------------------------------------------------------------------------
+
+#ifndef __TEST_MACROS_MT_FUTEX_H
+#define __TEST_MACROS_MT_FUTEX_H
+
+#define SYSCALL_FUTEX         98
+#define SYSCALL_GETTID        178
+#define SYSCALL_MUNMAP        215
+#define SYSCALL_CLONE         220
+#define SYSCALL_MMAP          222
+
+#define MEM_SIZE              (4096 * 1024)
+
+#define PROT_READ             0x1
+#define PROT_WRITE            0x2
+#define MMAP_PROT_FLAGS       (PROT_READ | PROT_WRITE)
+
+#define MAP_PRIVATE           0x02
+#define MAP_ANONYMOUS         0x20
+#define MAP_STACK             0x20000
+#define MMAP_MAP_FLAGS        (MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK)
+
+#define CLONE_VM              0x00000100
+#define CLONE_FS              0x00000200
+#define CLONE_FILES           0x00000400
+#define CLONE_SIGHAND         0x00000800
+#define CLONE_PARENT          0x00008000
+#define CLONE_THREAD          0x00010000
+#define CLONE_IO              0x80000000
+#define CLONE_PARENT_SETTID   0x00100000	/* set the TID in the parent */
+#define CLONE_CHILD_CLEARTID  0x00200000	/* clear the TID in the child */
+#define CLONE_SETTLS          0x00080000
+#define CLONE_FLAGS           (CLONE_VM | CLONE_FS | CLONE_FILES \
+                              | CLONE_SIGHAND | CLONE_PARENT \
+                              | CLONE_THREAD | CLONE_IO \
+                              | CLONE_PARENT_SETTID \
+                              | CLONE_CHILD_CLEARTID \
+                              | CLONE_SETTLS)
+
+#define FUTEX_WAIT            0
+#define FUTEX_WAKE            1
+#define FUTEX_CMP_REQUEUE     4
+#define FUTEX_WAKE_OP         5
+#define FUTEX_WAIT_BITSET     9
+#define FUTEX_WAKE_BITSET     10
+#define FUTEX_PRIVATE_FLAG    128
+#define FUTEX_CLOCK_REALTIME  256
+#define FUTEX_CMD_MASK        ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
+
+#define FUTEX_OP_SET          0  /* uaddr2 = oparg; */
+#define FUTEX_OP_ADD          1  /* uaddr2 += oparg; */
+#define FUTEX_OP_OR           2  /* uaddr2 |= oparg; */
+#define FUTEX_OP_ANDN         3  /* uaddr2 &= ~oparg; */
+#define FUTEX_OP_XOR          4  /* uaddr2 ^= oparg; */
+#define FUTEX_OP_ARG_SHIFT    8  /* Use (1 << oparg) as operand */
+
+#define FUTEX_OP_CMP_EQ       0  /* if (oldval == cmparg) wake */
+#define FUTEX_OP_CMP_NE       1  /* if (oldval != cmparg) wake */
+#define FUTEX_OP_CMP_LT       2  /* if (oldval < cmparg) wake */
+#define FUTEX_OP_CMP_LE       3  /* if (oldval <= cmparg) wake */
+#define FUTEX_OP_CMP_GT       4  /* if (oldval > cmparg) wake */
+#define FUTEX_OP_CMP_GE       5  /* if (oldval >= cmparg) wake */
+
+#define FUTEX_OP(op, oparg, cmp, cmparg)                    \
+                (((op & 0xf) << 28) |                       \
+                 ((cmp & 0xf) << 24) |                      \
+                 ((oparg & 0xfff) << 12) |                  \
+                 (cmparg & 0xfff))
+
+#define FUTEX_WAIT_PRIVATE        (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_PRIVATE        (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAIT_BITSET_PRIVATE (FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_BITSET_PRIVATE (FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG)
+
+#define FAILURE               1
+#define SUCCESS               0
+
+//------------------------------------------------------------------------
+// _create_threads: create a given number of threads
+//
+//    The calling thread (a.k.a, master thread) saves information about its
+//    child threads in its stack in the following structure:
+//
+//    | child_stack_ptr_0       |  << fp: frame pointer
+//    | child_tls_ptr_0         |
+//    | child_thread_id_0       |
+//    | saved_child_thread_id_0 |
+//    | child_stack_ptr_1       |
+//    | child_tls_ptr_1         |
+//    | child_thread_id_1       |
+//    | saved_child_thread_id_1 |
+//    | ...                     |  << sp: stack pointer
+//
+//    For each child thread, we need to save the following information
+//    in the parent thread's stack frame:
+//
+//    - child_stack_ptr stores the lower address of the child thread's
+//      stack space
+//
+//    - child_tls_ptr stores the lower address of the child thread's
+//      thread local storage (TLS)
+//
+//    - child_thread_id stores the thread ID of the child thread. This
+//      variable will be cleared by the child thread when it exits.
+//
+//    - saved_child_thread_id also stores the thread ID of the child
+//      thread, but this variable is used only by the parent thread.
+//
+//    This function takes the number of threads to create in a0. It
+//    updates n_child_threads variable to the number of successfully
+//    created threads.
+//------------------------------------------------------------------------
+
+_create_threads:
+  mv      t0, a0                // get the number of threads
+  mv      s0, ra                // save return register
+  la      t3, n_worker_threads
+1:
+  // allocate a new stack space and save its pointer in the caller's stack
+  jal     ra, _alloc_mem
+  addi    sp, sp, -8
+  sd      a0, (sp)
+  mv      t1, a0
+
+  // allocate a new thread local storage (TLS) and save its pointer in the
+  // caller's stack
+  jal     ra, _alloc_mem
+  addi    sp, sp, -8
+  sd      a0, (sp)
+  mv      t2, a0
+
+  // allocate space in the caller's stack to store new thread ID
+  addi    sp, sp, -8
+
+  // clone a new thread
+  li      a0, CLONE_FLAGS
+  li      s2, MEM_SIZE
+  add     a1, t1, s2        // pointer to the high address of the new stack
+  mv      a2, sp            // ptid
+  mv      a3, t2            // pointer to the low address of the new TLS,
+                            // assuming TLS grows upward
+  mv      a4, sp            // ctid
+  li      a7, SYSCALL_CLONE // clone syscall number
+  ecall                     // call clone syscall
+  bltz    a0, 2f            // syscall error
+  beqz    a0, _mt_test      // only the new thread jumps to _mt_test
+
+  // save child thread ID in the caller's stack
+  addi      sp, sp, -8
+  sd        a0, (sp)
+
+  // decrement the number of threads to create
+  addi      t0, t0, -1
+
+  // increment the number of successfully created threads sofar
+  addi      t4, zero, 1
+  amoadd.d  zero, t4, (t3)
+
+  // check if we still need to spawn more threads
+  bnez      t0, 1b
+  j         3f
+2:
+  // handle clone syscall error by deleting the last memory frame created
+  // for the unsuccessfully spawned thread.
+  addi      sp, sp, 8       // skip child_thread_id
+
+  // deallocate last allocated tls
+  ld        a0, (sp)
+  jal       ra, _dealloc_mem
+  addi      sp, sp, 8
+
+  // deallocate last allocated stack
+  ld        a0, (sp)
+  jal       ra, _dealloc_mem
+  addi      sp, sp, 8
+3:
+  // finish creating threads
+  mv        ra, s0
+  ret
+
+//------------------------------------------------------------------------
+// _alloc_mem: allocate a memory space with size MEM_SIZE
+//
+//    This function returns the pointer to the newly allocated memory
+//    space in a0
+//------------------------------------------------------------------------
+
+_alloc_mem:
+  li      a0, 0
+  li      a1, MEM_SIZE
+  li      a2, MMAP_PROT_FLAGS
+  li      a3, MMAP_MAP_FLAGS
+  li      a4, -1
+  li      a5, 0
+  li      a7, SYSCALL_MMAP
+  ecall
+  ret
+
+//------------------------------------------------------------------------
+// _delete_threads: deallocate all child threads
+//
+//    This function assumes the following structure in the calling thread's
+//    stack frame
+//
+//    | child_stack_ptr_0       |  << fp: frame pointer
+//    | child_tls_ptr_0         |
+//    | child_thread_id_0       |
+//    | saved_child_thread_id_0 |
+//    | child_stack_ptr_1       |
+//    | child_tls_ptr_1         |
+//    | child_thread_id_1       |
+//    | saved_child_thread_id_1 |
+//    | ...                     |  << sp: stack pointer
+//
+//    This function takes the number of threads to delete in a0
+//------------------------------------------------------------------------
+
+_delete_threads:
+  mv      t0, a0                  // get the number of threads to delete
+  mv      s0, ra                  // save return register
+1:
+  addi    sp, sp, 8               // skip saved_child_thread_id
+  addi    sp, sp, 8               // skip child_thread_id
+
+  // deallocate thread's tls
+  ld      a0, (sp)
+  jal     ra, _dealloc_mem
+  addi    sp, sp, 8
+
+  // deallocate thread's stack
+  ld      a0, (sp)
+  jal     ra, _dealloc_mem
+  addi    sp, sp, 8
+
+  // decrement the number of threads to delete
+  addi    t0, t0, -1
+  bnez    t0, 1b
+
+  // finish deleting all threads
+  mv      ra, s0                  // restore return register
+  ret
+
+//------------------------------------------------------------------------
+// _dealloc_mem: deallocate memory space of size MEM_SIZE
+//
+//    This function takes the pointer to the memory space in a0
+//------------------------------------------------------------------------
+
+_dealloc_mem:
+  li      a1, MEM_SIZE
+  li      a7, SYSCALL_MUNMAP
+  ecall
+  ret
+
+//------------------------------------------------------------------------
+// _join: wait for all child threads to exit
+//
+//    Child threads are created with CLONE_CHILD_CLEARTID flag, so when
+//    they exit, they will clear the ctid/ptid variable and wake up their
+//    parent thread.
+//
+//    This function assumes the following structure in the calling thread's
+//    stack frame
+//
+//    | child_stack_ptr_0       |  << fp: frame pointer
+//    | child_tls_ptr_0         |
+//    | child_thread_id_0       |
+//    | saved_child_thread_id_0 |
+//    | child_stack_ptr_1       |
+//    | child_tls_ptr_1         |
+//    | child_thread_id_1       |
+//    | saved_child_thread_id_1 |
+//    | ...                     |  << sp: stack pointer
+//
+//    This function takes a number of threads to wait in a0
+//------------------------------------------------------------------------
+
+_join:
+  mv      t0, a0          // get the number of threads
+  mv      s0, ra          // save return register
+  mv      s1, sp          // save stack pointer
+1:
+  // Calling futex_wait on ctidptr
+  ld      a2, (sp)                // get child thread ID from
+                                  // saved_child_thread_id
+  addi    sp, sp, 8
+  mv      a0, sp                  // futex address (child_thread_id)
+  li      a1, FUTEX_WAIT_PRIVATE
+  li      a7, SYSCALL_FUTEX
+  ecall
+
+  addi    sp, sp, 8              // skip child_tls_ptr
+  addi    sp, sp, 8              // skip child_stack_ptr
+
+  // decrement the number of threads to wait for
+  addi    t0, t0, -1
+  bnez    t0, 1b
+
+  // finish waiting for all threads
+  mv      ra, s0                  // restore return register
+  mv      sp, s1                  // restore stack pointer
+  ret
+
+#define MT_DATA                                                           \
+  n_worker_threads:     .dword    0;                                      \
+  shared_var:           .dword    0;                                      \
+  barrier:              .dword    0;                                      \
+  array:                .dword    0x00000000deadbeef,                     \
+                                  0xdeadbeefdeadbeef,                     \
+                                  0x12343eeaaf423451;                     \
+
+#endif
diff --git a/tests/test-progs/asmtest/src/riscv/isa/macros/scalar/test_macros.h b/tests/test-progs/asmtest/src/riscv/isa/macros/scalar/test_macros.h
new file mode 100644
index 0000000..58e389f
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/macros/scalar/test_macros.h
@@ -0,0 +1,649 @@
+// See LICENSE for license details.
+
+#ifndef __TEST_MACROS_SCALAR_H
+#define __TEST_MACROS_SCALAR_H
+
+
+#-----------------------------------------------------------------------
+# Helper macros
+#-----------------------------------------------------------------------
+
+#define MASK_XLEN(x) ((x) & ((1 << (__riscv_xlen - 1) << 1) - 1))
+
+#define TEST_CASE( testnum, testreg, correctval, code... ) \
+test_ ## testnum: \
+    code; \
+    li  x29, MASK_XLEN(correctval); \
+    li  TESTNUM, testnum; \
+    bne testreg, x29, fail;
+
+# We use a macro hack to simpify code generation for various numbers
+# of bubble cycles.
+
+#define TEST_INSERT_NOPS_0
+#define TEST_INSERT_NOPS_1  nop; TEST_INSERT_NOPS_0
+#define TEST_INSERT_NOPS_2  nop; TEST_INSERT_NOPS_1
+#define TEST_INSERT_NOPS_3  nop; TEST_INSERT_NOPS_2
+#define TEST_INSERT_NOPS_4  nop; TEST_INSERT_NOPS_3
+#define TEST_INSERT_NOPS_5  nop; TEST_INSERT_NOPS_4
+#define TEST_INSERT_NOPS_6  nop; TEST_INSERT_NOPS_5
+#define TEST_INSERT_NOPS_7  nop; TEST_INSERT_NOPS_6
+#define TEST_INSERT_NOPS_8  nop; TEST_INSERT_NOPS_7
+#define TEST_INSERT_NOPS_9  nop; TEST_INSERT_NOPS_8
+#define TEST_INSERT_NOPS_10 nop; TEST_INSERT_NOPS_9
+
+
+#-----------------------------------------------------------------------
+# RV64UI MACROS
+#-----------------------------------------------------------------------
+
+#-----------------------------------------------------------------------
+# Tests for instructions with immediate operand
+#-----------------------------------------------------------------------
+
+#define SEXT_IMM(x) ((x) | (-(((x) >> 11) & 1) << 11))
+
+#define TEST_IMM_OP( testnum, inst, result, val1, imm ) \
+    TEST_CASE( testnum, x30, result, \
+      li  x1, MASK_XLEN(val1); \
+      inst x30, x1, SEXT_IMM(imm); \
+    )
+
+#define TEST_IMM_SRC1_EQ_DEST( testnum, inst, result, val1, imm ) \
+    TEST_CASE( testnum, x1, result, \
+      li  x1, MASK_XLEN(val1); \
+      inst x1, x1, SEXT_IMM(imm); \
+    )
+
+#define TEST_IMM_DEST_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
+    TEST_CASE( testnum, x6, result, \
+      li  x4, 0; \
+1:    li  x1, MASK_XLEN(val1); \
+      inst x30, x1, SEXT_IMM(imm); \
+      TEST_INSERT_NOPS_ ## nop_cycles \
+      addi  x6, x30, 0; \
+      addi  x4, x4, 1; \
+      li  x5, 2; \
+      bne x4, x5, 1b \
+    )
+
+#define TEST_IMM_SRC1_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
+    TEST_CASE( testnum, x30, result, \
+      li  x4, 0; \
+1:    li  x1, MASK_XLEN(val1); \
+      TEST_INSERT_NOPS_ ## nop_cycles \
+      inst x30, x1, SEXT_IMM(imm); \
+      addi  x4, x4, 1; \
+      li  x5, 2; \
+      bne x4, x5, 1b \
+    )
+
+#define TEST_IMM_ZEROSRC1( testnum, inst, result, imm ) \
+    TEST_CASE( testnum, x1, result, \
+      inst x1, x0, SEXT_IMM(imm); \
+    )
+
+#define TEST_IMM_ZERODEST( testnum, inst, val1, imm ) \
+    TEST_CASE( testnum, x0, 0, \
+      li  x1, MASK_XLEN(val1); \
+      inst x0, x1, SEXT_IMM(imm); \
+    )
+
+#-----------------------------------------------------------------------
+# Tests for an instruction with register operands
+#-----------------------------------------------------------------------
+
+#define TEST_R_OP( testnum, inst, result, val1 ) \
+    TEST_CASE( testnum, x30, result, \
+      li  x1, val1; \
+      inst x30, x1; \
+    )
+
+#define TEST_R_SRC1_EQ_DEST( testnum, inst, result, val1 ) \
+    TEST_CASE( testnum, x1, result, \
+      li  x1, val1; \
+      inst x1, x1; \
+    )
+
+#define TEST_R_DEST_BYPASS( testnum, nop_cycles, inst, result, val1 ) \
+    TEST_CASE( testnum, x6, result, \
+      li  x4, 0; \
+1:    li  x1, val1; \
+      inst x30, x1; \
+      TEST_INSERT_NOPS_ ## nop_cycles \
+      addi  x6, x30, 0; \
+      addi  x4, x4, 1; \
+      li  x5, 2; \
+      bne x4, x5, 1b \
+    )
+
+#-----------------------------------------------------------------------
+# Tests for an instruction with register-register operands
+#-----------------------------------------------------------------------
+
+#define TEST_RR_OP( testnum, inst, result, val1, val2 ) \
+    TEST_CASE( testnum, x30, result, \
+      li  x1, MASK_XLEN(val1); \
+      li  x2, MASK_XLEN(val2); \
+      inst x30, x1, x2; \
+    )
+
+#define TEST_RR_SRC1_EQ_DEST( testnum, inst, result, val1, val2 ) \
+    TEST_CASE( testnum, x1, result, \
+      li  x1, MASK_XLEN(val1); \
+      li  x2, MASK_XLEN(val2); \
+      inst x1, x1, x2; \
+    )
+
+#define TEST_RR_SRC2_EQ_DEST( testnum, inst, result, val1, val2 ) \
+    TEST_CASE( testnum, x2, result, \
+      li  x1, MASK_XLEN(val1); \
+      li  x2, MASK_XLEN(val2); \
+      inst x2, x1, x2; \
+    )
+
+#define TEST_RR_SRC12_EQ_DEST( testnum, inst, result, val1 ) \
+    TEST_CASE( testnum, x1, result, \
+      li  x1, MASK_XLEN(val1); \
+      inst x1, x1, x1; \
+    )
+
+#define TEST_RR_DEST_BYPASS( testnum, nop_cycles, inst, result, val1, val2 ) \
+    TEST_CASE( testnum, x6, result, \
+      li  x4, 0; \
+1:    li  x1, MASK_XLEN(val1); \
+      li  x2, MASK_XLEN(val2); \
+      inst x30, x1, x2; \
+      TEST_INSERT_NOPS_ ## nop_cycles \
+      addi  x6, x30, 0; \
+      addi  x4, x4, 1; \
+      li  x5, 2; \
+      bne x4, x5, 1b \
+    )
+
+#define TEST_RR_SRC12_BYPASS( testnum, src1_nops, src2_nops, inst, result, val1, val2 ) \
+    TEST_CASE( testnum, x30, result, \
+      li  x4, 0; \
+1:    li  x1, MASK_XLEN(val1); \
+      TEST_INSERT_NOPS_ ## src1_nops \
+      li  x2, MASK_XLEN(val2); \
+      TEST_INSERT_NOPS_ ## src2_nops \
+      inst x30, x1, x2; \
+      addi  x4, x4, 1; \
+      li  x5, 2; \
+      bne x4, x5, 1b \
+    )
+
+#define TEST_RR_SRC21_BYPASS( testnum, src1_nops, src2_nops, inst, result, val1, val2 ) \
+    TEST_CASE( testnum, x30, result, \
+      li  x4, 0; \
+1:    li  x2, MASK_XLEN(val2); \
+      TEST_INSERT_NOPS_ ## src1_nops \
+      li  x1, MASK_XLEN(val1); \
+      TEST_INSERT_NOPS_ ## src2_nops \
+      inst x30, x1, x2; \
+      addi  x4, x4, 1; \
+      li  x5, 2; \
+      bne x4, x5, 1b \
+    )
+
+#define TEST_RR_ZEROSRC1( testnum, inst, result, val ) \
+    TEST_CASE( testnum, x2, result, \
+      li x1, MASK_XLEN(val); \
+      inst x2, x0, x1; \
+    )
+
+#define TEST_RR_ZEROSRC2( testnum, inst, result, val ) \
+    TEST_CASE( testnum, x2, result, \
+      li x1, MASK_XLEN(val); \
+      inst x2, x1, x0; \
+    )
+
+#define TEST_RR_ZEROSRC12( testnum, inst, result ) \
+    TEST_CASE( testnum, x1, result, \
+      inst x1, x0, x0; \
+    )
+
+#define TEST_RR_ZERODEST( testnum, inst, val1, val2 ) \
+    TEST_CASE( testnum, x0, 0, \
+      li x1, MASK_XLEN(val1); \
+      li x2, MASK_XLEN(val2); \
+      inst x0, x1, x2; \
+    )
+
+#-----------------------------------------------------------------------
+# Test memory instructions
+#-----------------------------------------------------------------------
+
+#define TEST_LD_OP( testnum, inst, result, offset, base ) \
+    TEST_CASE( testnum, x30, result, \
+      la  x1, base; \
+      inst x30, offset(x1); \
+    )
+
+#define TEST_ST_OP( testnum, load_inst, store_inst, result, offset, base ) \
+    TEST_CASE( testnum, x30, result, \
+      la  x1, base; \
+      li  x2, result; \
+      store_inst x2, offset(x1); \
+      load_inst x30, offset(x1); \
+    )
+
+#define TEST_LD_DEST_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x4, 0; \
+1:  la  x1, base; \
+    inst x30, offset(x1); \
+    TEST_INSERT_NOPS_ ## nop_cycles \
+    addi  x6, x30, 0; \
+    li  x29, result; \
+    bne x6, x29, fail; \
+    addi  x4, x4, 1; \
+    li  x5, 2; \
+    bne x4, x5, 1b; \
+
+#define TEST_LD_SRC1_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x4, 0; \
+1:  la  x1, base; \
+    TEST_INSERT_NOPS_ ## nop_cycles \
+    inst x30, offset(x1); \
+    li  x29, result; \
+    bne x30, x29, fail; \
+    addi  x4, x4, 1; \
+    li  x5, 2; \
+    bne x4, x5, 1b \
+
+#define TEST_ST_SRC12_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x4, 0; \
+1:  li  x1, result; \
+    TEST_INSERT_NOPS_ ## src1_nops \
+    la  x2, base; \
+    TEST_INSERT_NOPS_ ## src2_nops \
+    store_inst x1, offset(x2); \
+    load_inst x30, offset(x2); \
+    li  x29, result; \
+    bne x30, x29, fail; \
+    addi  x4, x4, 1; \
+    li  x5, 2; \
+    bne x4, x5, 1b \
+
+#define TEST_ST_SRC21_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x4, 0; \
+1:  la  x2, base; \
+    TEST_INSERT_NOPS_ ## src1_nops \
+    li  x1, result; \
+    TEST_INSERT_NOPS_ ## src2_nops \
+    store_inst x1, offset(x2); \
+    load_inst x30, offset(x2); \
+    li  x29, result; \
+    bne x30, x29, fail; \
+    addi  x4, x4, 1; \
+    li  x5, 2; \
+    bne x4, x5, 1b \
+
+#define TEST_BR2_OP_TAKEN( testnum, inst, val1, val2 ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x1, val1; \
+    li  x2, val2; \
+    inst x1, x2, 2f; \
+    bne x0, TESTNUM, fail; \
+1:  bne x0, TESTNUM, 3f; \
+2:  inst x1, x2, 1b; \
+    bne x0, TESTNUM, fail; \
+3:
+
+#define TEST_BR2_OP_NOTTAKEN( testnum, inst, val1, val2 ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x1, val1; \
+    li  x2, val2; \
+    inst x1, x2, 1f; \
+    bne x0, TESTNUM, 2f; \
+1:  bne x0, TESTNUM, fail; \
+2:  inst x1, x2, 1b; \
+3:
+
+#define TEST_BR2_SRC12_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x4, 0; \
+1:  li  x1, val1; \
+    TEST_INSERT_NOPS_ ## src1_nops \
+    li  x2, val2; \
+    TEST_INSERT_NOPS_ ## src2_nops \
+    inst x1, x2, fail; \
+    addi  x4, x4, 1; \
+    li  x5, 2; \
+    bne x4, x5, 1b \
+
+#define TEST_BR2_SRC21_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x4, 0; \
+1:  li  x2, val2; \
+    TEST_INSERT_NOPS_ ## src1_nops \
+    li  x1, val1; \
+    TEST_INSERT_NOPS_ ## src2_nops \
+    inst x1, x2, fail; \
+    addi  x4, x4, 1; \
+    li  x5, 2; \
+    bne x4, x5, 1b \
+
+#-----------------------------------------------------------------------
+# Test jump instructions
+#-----------------------------------------------------------------------
+
+#define TEST_JR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x4, 0; \
+1:  la  x6, 2f; \
+    TEST_INSERT_NOPS_ ## nop_cycles \
+    inst x6; \
+    bne x0, TESTNUM, fail; \
+2:  addi  x4, x4, 1; \
+    li  x5, 2; \
+    bne x4, x5, 1b \
+
+#define TEST_JALR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
+test_ ## testnum: \
+    li  TESTNUM, testnum; \
+    li  x4, 0; \
+1:  la  x6, 2f; \
+    TEST_INSERT_NOPS_ ## nop_cycles \
+    inst x19, x6, 0; \
+    bne x0, TESTNUM, fail; \
+2:  addi  x4, x4, 1; \
+    li  x5, 2; \
+    bne x4, x5, 1b \
+
+
+#-----------------------------------------------------------------------
+# RV64UF MACROS
+#-----------------------------------------------------------------------
+
+#-----------------------------------------------------------------------
+# Tests floating-point instructions
+#-----------------------------------------------------------------------
+
+#define qNaNf 0f:7fc00000
+#define sNaNf 0f:7f800001
+#define qNaN 0d:7ff8000000000000
+#define sNaN 0d:7ff0000000000001
+
+#define TEST_FP_OP_S_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
+test_ ## testnum: \
+  li  TESTNUM, testnum; \
+  la  a0, test_ ## testnum ## _data ;\
+  flw f0, 0(a0); \
+  flw f1, 4(a0); \
+  flw f2, 8(a0); \
+  lw  a3, 12(a0); \
+  code; \
+  fsflags a1, x0; \
+  li a2, flags; \
+  bne a0, a3, fail; \
+  bne a1, a2, fail; \
+  .pushsection .data; \
+  .align 2; \
+  test_ ## testnum ## _data: \
+  .float val1; \
+  .float val2; \
+  .float val3; \
+  .result; \
+  .popsection
+
+#define TEST_FP_OP_D_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
+test_ ## testnum: \
+  li  TESTNUM, testnum; \
+  la  a0, test_ ## testnum ## _data ;\
+  fld f0, 0(a0); \
+  fld f1, 8(a0); \
+  fld f2, 16(a0); \
+  ld  a3, 24(a0); \
+  code; \
+  fsflags a1, x0; \
+  li a2, flags; \
+  bne a0, a3, fail; \
+  bne a1, a2, fail; \
+  .pushsection .data; \
+  .align 3; \
+  test_ ## testnum ## _data: \
+  .double val1; \
+  .double val2; \
+  .double val3; \
+  .result; \
+  .popsection
+
+// TODO: assign a separate mem location for the comparison address?
+#define TEST_FP_OP_D32_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
+test_ ## testnum: \
+  li  TESTNUM, testnum; \
+  la  a0, test_ ## testnum ## _data ;\
+  fld f0, 0(a0); \
+  fld f1, 8(a0); \
+  fld f2, 16(a0); \
+  lw  a3, 24(a0); \
+  lw  t1, 28(a0); \
+  code; \
+  fsflags a1, x0; \
+  li a2, flags; \
+  bne a0, a3, fail; \
+  bne t1, t2, fail; \
+  bne a1, a2, fail; \
+  .pushsection .data; \
+  .align 3; \
+  test_ ## testnum ## _data: \
+  .double val1; \
+  .double val2; \
+  .double val3; \
+  .result; \
+  .popsection
+
+#define TEST_FCVT_S_D32( testnum, result, val1 ) \
+  TEST_FP_OP_D32_INTERNAL( testnum, 0, double result, val1, 0.0, 0.0, \
+                    fcvt.s.d f3, f0; fcvt.d.s f3, f3; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
+
+#define TEST_FCVT_S_D( testnum, result, val1 ) \
+  TEST_FP_OP_D_INTERNAL( testnum, 0, double result, val1, 0.0, 0.0, \
+                    fcvt.s.d f3, f0; fcvt.d.s f3, f3; fmv.x.d a0, f3)
+
+#define TEST_FCVT_D_S( testnum, result, val1 ) \
+  TEST_FP_OP_S_INTERNAL( testnum, 0, float result, val1, 0.0, 0.0, \
+                    fcvt.d.s f3, f0; fcvt.s.d f3, f3; fmv.x.s a0, f3)
+
+#define TEST_FP_OP1_S( testnum, inst, flags, result, val1 ) \
+  TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, 0.0, 0.0, \
+                    inst f3, f0; fmv.x.s a0, f3)
+
+#define TEST_FP_OP1_D32( testnum, inst, flags, result, val1 ) \
+  TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, 0.0, 0.0, \
+                    inst f3, f0; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
+// ^: store computation result in address from a0, load high-word into t2
+
+#define TEST_FP_OP1_D( testnum, inst, flags, result, val1 ) \
+  TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, 0.0, 0.0, \
+                    inst f3, f0; fmv.x.d a0, f3)
+
+#define TEST_FP_OP1_S_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
+  TEST_FP_OP_S_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
+                    inst f3, f0; fmv.x.s a0, f3)
+
+#define TEST_FP_OP1_D32_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
+  TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
+                    inst f3, f0; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
+// ^: store computation result in address from a0, load high-word into t2
+
+#define TEST_FP_OP1_D_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
+  TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
+                    inst f3, f0; fmv.x.d a0, f3)
+
+#define TEST_FP_OP2_S( testnum, inst, flags, result, val1, val2 ) \
+  TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, val2, 0.0, \
+                    inst f3, f0, f1; fmv.x.s a0, f3)
+
+#define TEST_FP_OP2_D32( testnum, inst, flags, result, val1, val2 ) \
+  TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, val2, 0.0, \
+                    inst f3, f0, f1; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
+// ^: store computation result in address from a0, load high-word into t2
+
+#define TEST_FP_OP2_D( testnum, inst, flags, result, val1, val2 ) \
+  TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, val2, 0.0, \
+                    inst f3, f0, f1; fmv.x.d a0, f3)
+
+#define TEST_FP_OP3_S( testnum, inst, flags, result, val1, val2, val3 ) \
+  TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, val2, val3, \
+                    inst f3, f0, f1, f2; fmv.x.s a0, f3)
+
+#define TEST_FP_OP3_D32( testnum, inst, flags, result, val1, val2, val3 ) \
+  TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, val2, val3, \
+                    inst f3, f0, f1, f2; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
+// ^: store computation result in address from a0, load high-word into t2
+
+#define TEST_FP_OP3_D( testnum, inst, flags, result, val1, val2, val3 ) \
+  TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, val2, val3, \
+                    inst f3, f0, f1, f2; fmv.x.d a0, f3)
+
+#define TEST_FP_INT_OP_S( testnum, inst, flags, result, val1, rm ) \
+  TEST_FP_OP_S_INTERNAL( testnum, flags, word result, val1, 0.0, 0.0, \
+                    inst a0, f0, rm)
+
+#define TEST_FP_INT_OP_D32( testnum, inst, flags, result, val1, rm ) \
+  TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
+                    inst a0, f0, f1; li t2, 0)
+
+#define TEST_FP_INT_OP_D( testnum, inst, flags, result, val1, rm ) \
+  TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
+                    inst a0, f0, rm)
+
+#define TEST_FP_CMP_OP_S( testnum, inst, flags, result, val1, val2 ) \
+  TEST_FP_OP_S_INTERNAL( testnum, flags, word result, val1, val2, 0.0, \
+                    inst a0, f0, f1)
+
+#define TEST_FP_CMP_OP_D32( testnum, inst, flags, result, val1, val2 ) \
+  TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, val2, 0.0, \
+                    inst a0, f0, f1; li t2, 0)
+
+#define TEST_FP_CMP_OP_D( testnum, inst, flags, result, val1, val2 ) \
+  TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, val2, 0.0, \
+                    inst a0, f0, f1)
+
+#define TEST_FCLASS_S(testnum, correct, input) \
+  TEST_CASE(testnum, a0, correct, li a0, input; fmv.s.x fa0, a0; \
+                    fclass.s a0, fa0)
+
+#define TEST_FCLASS_D32(testnum, correct, input) \
+  TEST_CASE(testnum, a0, correct, \
+            la a0, test_ ## testnum ## _data ;\
+            fld fa0, 0(a0); \
+            fclass.d a0, fa0) \
+    .pushsection .data; \
+    .align 3; \
+    test_ ## testnum ## _data: \
+    .dword input; \
+    .popsection
+
+#define TEST_FCLASS_D(testnum, correct, input) \
+  TEST_CASE(testnum, a0, correct, li a0, input; fmv.d.x fa0, a0; \
+                    fclass.d a0, fa0)
+
+#define TEST_INT_FP_OP_S( testnum, inst, result, val1 ) \
+test_ ## testnum: \
+  li  TESTNUM, testnum; \
+  la  a0, test_ ## testnum ## _data ;\
+  lw  a3, 0(a0); \
+  li  a0, val1; \
+  inst f0, a0; \
+  fsflags x0; \
+  fmv.x.s a0, f0; \
+  bne a0, a3, fail; \
+  .pushsection .data; \
+  .align 2; \
+  test_ ## testnum ## _data: \
+  .float result; \
+  .popsection
+
+#define TEST_INT_FP_OP_D32( testnum, inst, result, val1 ) \
+test_ ## testnum: \
+  li  TESTNUM, testnum; \
+  la  a0, test_ ## testnum ## _data ;\
+  lw  a3, 0(a0); \
+  lw  a4, 4(a0); \
+  li  a1, val1; \
+  inst f0, a1; \
+  \
+  fsd f0, 0(a0); \
+  lw a1, 4(a0); \
+  lw a0, 0(a0); \
+  \
+  fsflags x0; \
+  bne a0, a3, fail; \
+  bne a1, a4, fail; \
+  .pushsection .data; \
+  .align 3; \
+  test_ ## testnum ## _data: \
+  .double result; \
+  .popsection
+
+#define TEST_INT_FP_OP_D( testnum, inst, result, val1 ) \
+test_ ## testnum: \
+  li  TESTNUM, testnum; \
+  la  a0, test_ ## testnum ## _data ;\
+  ld  a3, 0(a0); \
+  li  a0, val1; \
+  inst f0, a0; \
+  fsflags x0; \
+  fmv.x.d a0, f0; \
+  bne a0, a3, fail; \
+  .pushsection .data; \
+  .align 3; \
+  test_ ## testnum ## _data: \
+  .double result; \
+  .popsection
+
+// We need some special handling here to allow 64-bit comparison in 32-bit arch
+// TODO: find a better name and clean up when intended for general usage?
+#define TEST_CASE_D32( testnum, testreg1, testreg2, correctval, code... ) \
+test_ ## testnum: \
+    code; \
+    la  x31, test_ ## testnum ## _data ; \
+    lw  x29, 0(x31); \
+    lw  x31, 4(x31); \
+    li  TESTNUM, testnum; \
+    bne testreg1, x29, fail;\
+    bne testreg2, x31, fail;\
+    .pushsection .data; \
+    .align 3; \
+    test_ ## testnum ## _data: \
+    .dword correctval; \
+    .popsection
+
+// ^ x30 is used in some other macros, to avoid issues we use x31 for upper word
+
+#-----------------------------------------------------------------------
+# Pass and fail code (assumes test num is in TESTNUM)
+#-----------------------------------------------------------------------
+
+#define TEST_PASSFAIL \
+        bne x0, TESTNUM, pass; \
+fail: \
+        RVTEST_FAIL; \
+pass: \
+        RVTEST_PASS \
+
+
+#-----------------------------------------------------------------------
+# Test data section
+#-----------------------------------------------------------------------
+
+#define TEST_DATA
+
+#endif
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/Makefrag
new file mode 100644
index 0000000..b0ddefe
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/Makefrag
@@ -0,0 +1,19 @@
+#=======================================================================
+# Makefrag for rv64mi tests
+#-----------------------------------------------------------------------
+
+rv64mi_sc_tests = \
+	access \
+	breakpoint \
+	csr \
+	mcsr \
+	illegal \
+	ma_fetch \
+	ma_addr \
+	scall \
+	sbreak \
+
+rv32ud_p_tests = $(addprefix rv32ud-p-, $(rv32ud_sc_tests))
+#rv32ud_ps_tests = $(addprefix rv32ud-ps-, $(rv32ud_sc_tests))
+
+spike_tests += $(rv64mi_p_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/access.S b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/access.S
new file mode 100644
index 0000000..202a364
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/access.S
@@ -0,0 +1,70 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# access.S
+#-----------------------------------------------------------------------------
+#
+# Test access-exception behavior.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64M
+RVTEST_CODE_BEGIN
+
+  .align 2
+
+  # Flipping just the MSB should result in an illegal address for RV64.
+  la t2, fail
+  li t0, 1 << (__riscv_xlen - 1)
+  xor t0, t0, t2
+
+  # jalr to an illegal address should commit (hence should write rd).
+  # after the pc is set to rs1, an access exception should be raised.
+  li TESTNUM, 2
+  li t1, CAUSE_FETCH_ACCESS
+  la t3, 1f
+  li t2, 0
+  jalr t2, t0
+1:
+
+  # A load to an illegal address should not commit.
+  li TESTNUM, 3
+  li t1, CAUSE_LOAD_ACCESS
+  la t3, 1f
+  mv t2, t3
+  lb t2, (t0)
+  j fail
+1:
+
+  j pass
+
+  TEST_PASSFAIL
+
+  .align 2
+  .global mtvec_handler
+mtvec_handler:
+  li a0, 2
+  beq TESTNUM, a0, 2f
+  li a0, 3
+  beq TESTNUM, a0, 2f
+  j fail
+
+2:
+  bne t2, t3, fail
+
+  csrr t2, mcause
+  bne t2, t1, fail
+
+  csrw mepc, t3
+  mret
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/breakpoint.S b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/breakpoint.S
new file mode 100644
index 0000000..647430b
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/breakpoint.S
@@ -0,0 +1,144 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# breakpoint.S
+#-----------------------------------------------------------------------------
+#
+# Test breakpoints, if they are implemented.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64M
+RVTEST_CODE_BEGIN
+
+  # Set up breakpoint to trap on M-mode fetches.
+  li TESTNUM, 2
+
+  # Skip tselect if hard-wired.
+  csrw tselect, x0
+  csrr a1, tselect
+  bne x0, a1, pass
+
+  # Make sure there's a breakpoint there.
+  csrr a0, tdata1
+  srli a0, a0, __riscv_xlen - 4
+  li a1, 2
+  bne a0, a1, pass
+
+  la a2, 1f
+  csrw tdata2, a2
+  li a0, MCONTROL_M | MCONTROL_EXECUTE
+  csrw tdata1, a0
+  # Skip if breakpoint type is unsupported.
+  csrr a1, tdata1
+  andi a1, a1, 0x7ff
+  bne a0, a1, 2f
+  .align 2
+1:
+  # Trap handler should skip this instruction.
+  beqz x0, fail
+
+  # Make sure reads don't trap.
+  li TESTNUM, 3
+  lw a0, (a2)
+
+2:
+  # Set up breakpoint to trap on M-mode reads.
+  li TESTNUM, 4
+  li a0, MCONTROL_M | MCONTROL_LOAD
+  csrw tdata1, a0
+  # Skip if breakpoint type is unsupported.
+  csrr a1, tdata1
+  andi a1, a1, 0x7ff
+  bne a0, a1, 2f
+  la a2, data1
+  csrw tdata2, a2
+
+  # Trap handler should skip this instruction.
+  lw a2, (a2)
+  beqz a2, fail
+
+  # Make sure writes don't trap.
+  li TESTNUM, 5
+  sw x0, (a2)
+
+2:
+  # Set up breakpoint to trap on M-mode stores.
+  li TESTNUM, 6
+  li a0, MCONTROL_M | MCONTROL_STORE
+  csrw tdata1, a0
+  # Skip if breakpoint type is unsupported.
+  csrr a1, tdata1
+  andi a1, a1, 0x7ff
+  bne a0, a1, 2f
+
+  # Trap handler should skip this instruction.
+  sw a2, (a2)
+
+  # Make sure store didn't succeed.
+  li TESTNUM, 7
+  lw a2, (a2)
+  bnez a2, fail
+
+  # Try to set up a second breakpoint.
+  li a0, 1
+  csrw tselect, a0
+  csrr a1, tselect
+  bne a0, a1, pass
+
+  # Make sure there's a breakpoint there.
+  csrr a0, tdata1
+  srli a0, a0, __riscv_xlen - 4
+  li a1, 2
+  bne a0, a1, pass
+
+  li a0, MCONTROL_M | MCONTROL_LOAD
+  csrw tdata1, a0
+  la a3, data2
+  csrw tdata2, a3
+
+  # Make sure the second breakpoint triggers.
+  li TESTNUM, 8
+  lw a3, (a3)
+  beqz a3, fail
+
+  # Make sure the first breakpoint still triggers.
+  li TESTNUM, 10
+  la a2, data1
+  sw a2, (a2)
+  li TESTNUM, 11
+  lw a2, (a2)
+  bnez a2, fail
+
+2:
+  TEST_PASSFAIL
+
+  .align 2
+  .global mtvec_handler
+mtvec_handler:
+  # Only even-numbered tests should trap.
+  andi t0, TESTNUM, 1
+  bnez t0, fail
+
+  li t0, CAUSE_BREAKPOINT
+  csrr t1, mcause
+  bne t0, t1, fail
+
+  csrr t0, mepc
+  addi t0, t0, 4
+  csrw mepc, t0
+  mret
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+data1: .word 0
+data2: .word 0
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/csr.S b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/csr.S
new file mode 100644
index 0000000..77e7619
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/csr.S
@@ -0,0 +1,8 @@
+# See LICENSE for license details.
+
+#include "riscv_test.h"
+#undef RVTEST_RV64S
+#define RVTEST_RV64S RVTEST_RV64M
+#define __MACHINE_MODE
+
+#include "../rv64si/csr.S"
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/illegal.S b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/illegal.S
new file mode 100644
index 0000000..d825c44
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/illegal.S
@@ -0,0 +1,194 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# illegal.S
+#-----------------------------------------------------------------------------
+#
+# Test illegal instruction trap.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64M
+RVTEST_CODE_BEGIN
+
+  .align 2
+  .option norvc
+
+  li TESTNUM, 2
+bad2:
+  .word 0
+  j fail
+
+  # Skip the rest of the test if S-mode is not present.
+  li t0, MSTATUS_MPP
+  csrc mstatus, t0
+  li t1, (MSTATUS_MPP & -MSTATUS_MPP) * PRV_S
+  csrs mstatus, t1
+  csrr t2, mstatus
+  and t2, t2, t0
+  bne t1, t2, pass
+
+  # Test vectored interrupts if they are supported.
+test_vectored_interrupts:
+  csrwi mip, MIP_SSIP
+  csrwi mie, MIP_SSIP
+  la t0, mtvec_handler + 1
+  csrrw s0, mtvec, t0
+  csrr t0, mtvec
+  andi t0, t0, 1
+  beqz t0, msip
+  csrsi mstatus, MSTATUS_MIE
+1:
+  j 1b
+msip:
+  csrw mtvec, s0
+
+  # Delegate supervisor software interrupts so WFI won't stall.
+  csrwi mideleg, MIP_SSIP
+  # Enter supervisor mode.
+  la t0, 1f
+  csrw mepc, t0
+  li t0, MSTATUS_MPP
+  csrc mstatus, t0
+  li t1, (MSTATUS_MPP & -MSTATUS_MPP) * PRV_S
+  csrs mstatus, t1
+  mret
+
+1:
+  # Make sure WFI doesn't trap when TW=0.
+  wfi
+bad3:
+  .word 0
+  j fail
+
+bad4:
+  # Make sure WFI does trap when TW=1.
+  wfi
+  j fail
+
+  # Make sure SFENCE.VMA and sptbr don't trap when TVM=0.
+  sfence.vma
+  csrr t0, sptbr
+bad5:
+  .word 0
+  j fail
+
+bad6:
+  # Make sure SFENCE.VMA and sptbr do trap when TVM=1.
+  sfence.vma
+  j fail
+bad7:
+  csrr t0, sptbr
+  j fail
+
+  # Make sure SRET doesn't trap when TSR=0.
+  la t0, bad8
+  csrw sepc, t0
+  li t0, SSTATUS_SPP
+  csrs sstatus, t0
+  li t0, SSTATUS_SPIE
+  csrc sstatus, t0
+  sret
+bad8:
+  .word 0
+  j fail
+
+  # Make sure SRET does trap when TSR=1.
+  la t0, 1f
+  csrw sepc, t0
+bad9:
+  sret
+1:
+  j fail
+
+  TEST_PASSFAIL
+
+  .align 8
+  .global mtvec_handler
+mtvec_handler:
+  j synchronous_exception
+  j msip
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+  j fail
+
+synchronous_exception:
+  li t1, CAUSE_ILLEGAL_INSTRUCTION
+  csrr t0, mcause
+  bne t0, t1, fail
+  csrr t0, mepc
+
+  # Make sure mtval contains either 0 or the instruction word.
+  csrr t2, mbadaddr
+  beqz t2, 1f
+  lhu t3, 0(t0)
+  lhu t4, 2(t0)
+  slli t4, t4, 16
+  or t3, t3, t4
+  bne t2, t3, fail
+1:
+
+  la t1, bad2
+  beq t0, t1, 2f
+  la t1, bad3
+  beq t0, t1, 3f
+  la t1, bad4
+  beq t0, t1, 4f
+  la t1, bad5
+  beq t0, t1, 5f
+  la t1, bad6
+  beq t0, t1, 6f
+  la t1, bad7
+  beq t0, t1, 7f
+  la t1, bad8
+  beq t0, t1, 8f
+  la t1, bad9
+  beq t0, t1, 9f
+  j fail
+2:
+4:
+6:
+7:
+  addi t0, t0, 8
+  csrw mepc, t0
+  mret
+
+3:
+  li t1, MSTATUS_TW
+  csrs mstatus, t1
+  j 2b
+
+5:
+  li t1, MSTATUS_TVM
+  csrs mstatus, t1
+  j 2b
+
+8:
+  li t1, MSTATUS_TSR
+  csrs mstatus, t1
+  j 2b
+
+9:
+  j 2b
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/ma_addr.S b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/ma_addr.S
new file mode 100644
index 0000000..721ac6a
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/ma_addr.S
@@ -0,0 +1,126 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# ma_addr.S
+#-----------------------------------------------------------------------------
+#
+# Test misaligned ld/st trap.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64M
+RVTEST_CODE_BEGIN
+
+  .align 2
+  .option norvc
+
+  la s0, data
+
+  # indicate it's a load test
+  li s1, CAUSE_MISALIGNED_LOAD
+
+#define SEXT(x, n) ((-((x) >> ((n)-1)) << (n)) | ((x) & ((1 << (n))-1)))
+
+/* Check that a misaligned load either writes the correct value, or
+   takes an exception and performs no writeback.  */
+#define MISALIGNED_LOAD_TEST(testnum, insn, base, offset, res) \
+  li TESTNUM, testnum; \
+  la t2, 1f; \
+  addi t1, base, offset; \
+  insn t1, offset(base); \
+  li t2, res; \
+  bne t1, t2, fail; \
+1:
+
+  MISALIGNED_LOAD_TEST(2,  lh,  s0, 1, SEXT(0xbbcc, 16))
+  MISALIGNED_LOAD_TEST(3,  lhu, s0, 1, 0xbbcc)
+  MISALIGNED_LOAD_TEST(4,  lw,  s0, 1, SEXT(0x99aabbcc, 32))
+  MISALIGNED_LOAD_TEST(5,  lw,  s0, 2, SEXT(0x8899aabb, 32))
+  MISALIGNED_LOAD_TEST(6,  lw,  s0, 3, SEXT(0x778899aa, 32))
+
+#if __riscv_xlen == 64
+  MISALIGNED_LOAD_TEST(7,  lwu, s0, 1, 0x99aabbcc)
+  MISALIGNED_LOAD_TEST(8,  lwu, s0, 2, 0x8899aabb)
+  MISALIGNED_LOAD_TEST(9,  lwu, s0, 3, 0x778899aa)
+
+  MISALIGNED_LOAD_TEST(10, ld, s0, 1, 0x5566778899aabbcc)
+  MISALIGNED_LOAD_TEST(11, ld, s0, 2, 0x445566778899aabb)
+  MISALIGNED_LOAD_TEST(12, ld, s0, 3, 0x33445566778899aa)
+  MISALIGNED_LOAD_TEST(13, ld, s0, 4, 0x2233445566778899)
+  MISALIGNED_LOAD_TEST(14, ld, s0, 5, 0x1122334455667788)
+  MISALIGNED_LOAD_TEST(15, ld, s0, 6, 0xee11223344556677)
+  MISALIGNED_LOAD_TEST(16, ld, s0, 7, 0xffee112233445566)
+#endif
+
+  # indicate it's a store test
+  li s1, CAUSE_MISALIGNED_STORE
+
+/* Check that a misaligned store has some effect and takes no exception,
+   or takes no effect and generates an exception.  This is not very
+   thorough.  */
+#define MISALIGNED_STORE_TEST(testnum, insn, base, offset, size) \
+  li TESTNUM, testnum; \
+  la t2, 1f; \
+  addi t1, base, offset; \
+  insn x0, offset(base); \
+  lb t1, (offset - 1)(base); \
+  beqz t1, fail; \
+  lb t1, (offset + size)(base); \
+  beqz t1, fail; \
+  lb t1, (offset + 0)(base); \
+  bnez t1, fail; \
+  lb t1, (offset + size - 1)(base); \
+  bnez t1, fail; \
+1:
+
+  MISALIGNED_STORE_TEST(22,  sh,  s0, 1, 2)
+  MISALIGNED_STORE_TEST(23,  sw,  s0, 5, 4)
+  MISALIGNED_STORE_TEST(24,  sw,  s0, 10, 4)
+  MISALIGNED_STORE_TEST(25,  sw,  s0, 15, 4)
+
+#if __riscv_xlen == 64
+  MISALIGNED_STORE_TEST(26, sd, s0, 25, 8)
+  MISALIGNED_STORE_TEST(27, sd, s0, 34, 8)
+  MISALIGNED_STORE_TEST(28, sd, s0, 43, 8)
+  MISALIGNED_STORE_TEST(29, sd, s0, 52, 8)
+  MISALIGNED_STORE_TEST(30, sd, s0, 61, 8)
+  MISALIGNED_STORE_TEST(31, sd, s0, 70, 8)
+  MISALIGNED_STORE_TEST(32, sd, s0, 79, 8)
+#endif
+
+  TEST_PASSFAIL
+
+  .align 3
+  .global mtvec_handler
+mtvec_handler:
+  csrr t0, mcause
+  bne t0, s1, fail
+
+  csrr t0, mbadaddr
+  bne t0, t1, fail
+
+  lb t0, (t0)
+  beqz t0, fail
+
+  csrw mepc, t2
+  mret
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+data:
+  .align 3
+.word 0xaabbccdd
+.word 0x66778899
+.word 0x22334455
+.word 0xeeffee11
+.fill 0xff, 1, 80
+
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/ma_fetch.S b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/ma_fetch.S
new file mode 100644
index 0000000..cfcb90c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/ma_fetch.S
@@ -0,0 +1,8 @@
+# See LICENSE for license details.
+
+#include "riscv_test.h"
+#undef RVTEST_RV64S
+#define RVTEST_RV64S RVTEST_RV64M
+#define __MACHINE_MODE
+
+#include "../rv64si/ma_fetch.S"
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/mcsr.S b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/mcsr.S
new file mode 100644
index 0000000..e0256e7
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/mcsr.S
@@ -0,0 +1,45 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# mcsr.S
+#-----------------------------------------------------------------------------
+#
+# Test various M-mode CSRs.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64M
+RVTEST_CODE_BEGIN
+
+  # Check that mcpuid reports the correct XLEN
+#if __riscv_xlen == 64
+  TEST_CASE(2, a0, 0x2, csrr a0, misa; srl a0, a0, 62)
+#else
+  TEST_CASE(2, a0, 0x1, csrr a0, misa; srl a0, a0, 30)
+#endif
+
+  # Check that mhartid reports 0
+  TEST_CASE(3, a0, 0x0, csrr a0, mhartid)
+
+  # Check that reading the following CSRs doesn't cause an exception
+  csrr a0, mimpid
+  csrr a0, marchid
+  csrr a0, mvendorid
+
+  # Check that writing hte following CSRs doesn't cause an exception
+  li t0, 0
+  csrs mtvec, t0
+  csrs mepc, t0
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/sbreak.S b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/sbreak.S
new file mode 100644
index 0000000..f36a9f8
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/sbreak.S
@@ -0,0 +1,8 @@
+# See LICENSE for license details.
+
+#include "riscv_test.h"
+#undef RVTEST_RV64S
+#define RVTEST_RV64S RVTEST_RV64M
+#define __MACHINE_MODE
+
+#include "../rv64si/sbreak.S"
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64mi/scall.S b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/scall.S
new file mode 100644
index 0000000..22e9eb5
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64mi/scall.S
@@ -0,0 +1,8 @@
+# See LICENSE for license details.
+
+#include "riscv_test.h"
+#undef RVTEST_RV64S
+#define RVTEST_RV64S RVTEST_RV64M
+#define __MACHINE_MODE
+
+#include "../rv64si/scall.S"
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64samt/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/Makefrag
new file mode 100644
index 0000000..5fb3710
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/Makefrag
@@ -0,0 +1,13 @@
+#=========================================================================
+# Makefrag for rv64samt tests
+#=========================================================================
+
+rv64sa_mt_tests = sysclone_d \
+                  sysfutex_d \
+                  sysfutex1_d \
+                  sysfutex2_d \
+                  sysfutex3_d \
+
+rv64samt_ps_tests = $(addprefix rv64samt-ps-, $(rv64sa_mt_tests))
+
+spike_tests += $(rv64samt_ps_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysclone_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysclone_d.S
new file mode 100644
index 0000000..f178476
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysclone_d.S
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// sysclone_d tests basic functionalities of clone system call:
+//    - create a new thread
+//    - assign a new per-thread stack frame to the child thread
+//    - assign a new per-thread TLS to the child thread
+//
+// In addition to testing clone(), sysclone_d partially checks
+// functionalities of futex and exit system calls that are used to
+// facilitate thread exit and synchronization.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt_ecall.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define MAX_NUM_THREADS 20
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  li      a0, MAX_NUM_THREADS
+  call    _create_threads
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  beqz    a0, _fail                   // exit if there's no worker thread
+  call    _join
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _check
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _delete_threads
+
+  li      a0, SUCCESS
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed by child threads
+//------------------------------------------------------------------------
+_mt_test:
+  // get this thread's TID
+  li      a7, SYSCALL_GETTID
+  ecall
+
+  // store the TID to both stack and TLS of this thread
+  addi    sp, sp, -8
+  sd      a0, (sp)
+  sd      a0, (tp)
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// _check:
+//    The master thread looks into the stack and TLS of each child thread
+//    and check if the child thread's TID was written in both places.
+//
+//    This function assumes the following structure in the calling thread's
+//    stack frame
+//
+//    | child_stack_ptr_0       |  << fp: frame pointer
+//    | child_tls_ptr_0         |
+//    | child_thread_id_0       |
+//    | saved_child_thread_id_0 |
+//    | child_stack_ptr_1       |
+//    | child_tls_ptr_1         |
+//    | child_thread_id_1       |
+//    | saved_child_thread_id_1 |
+//    | ...                     |  << sp: stack pointer
+//
+//    This function takes a number of threads to check in a0
+//------------------------------------------------------------------------
+
+_check:
+  mv      t0, a0          // get the number of threads
+  mv      s0, ra          // save return register
+  mv      s1, sp          // save stack pointer
+1:
+  ld      t1, (sp)        // get child_thread_saved_id
+
+  addi    sp, sp, 8
+  ld      t2, (sp)        // get child_thread_id
+  bnez    t2, _fail       // this child_thread_id should have been cleared
+
+  addi    sp, sp, 8
+  ld      t3, (sp)        // get child_tls_ptr
+  ld      t3, (t3)        // get the first value stored in child's TLS
+  bne     t1, t3, _fail   // child_tid should have been saved in the TLS
+
+  addi    sp, sp, 8
+  ld      t4, (sp)        // get child_stack_ptr
+  li      t5, MEM_SIZE
+  add     t4, t4, t5      // get the high address of child's stack
+  ld      t4, -8(t4)      // get the first value stored in child's stack
+  bne     t1, t4, _fail   // child_tid should have been saved in the stack
+
+  addi    sp, sp, 8
+
+  // decrement the number of threads to wait for
+  addi    t0, t0, -1
+  bnez    t0, 1b
+
+  // finish checking all threads
+  mv      ra, s0                  // restore return register
+  mv      sp, s1                  // restore stack pointer
+  ret
+
+_fail:
+  li        a0, FAILURE
+  RVTEST_CODE_END
+
+  .data
+
+MT_DATA
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex1_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex1_d.S
new file mode 100644
index 0000000..418eb03
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex1_d.S
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// sysfutex1_d tests basic functionalities of futex system call:
+//    - make some threads wait on a variable
+//    - wake up all threads waiting on a variable
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt_ecall.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define MAX_NUM_THREADS 20
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, call _master function, waits for all
+// threads to complete, deallocates threads and checks result
+//------------------------------------------------------------------------
+  li      a0, MAX_NUM_THREADS
+  call    _create_threads
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  beqz    a0, _fail                   // exit if there's no worker thread
+
+  call    _master_work
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _join
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _check
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _delete_threads
+
+  li      a0, SUCCESS
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// master_work function executed by the parent/master thread
+//
+//    - wake up all threads waiting on futex_X
+//------------------------------------------------------------------------
+_master_work:
+  mv    s0, ra                  // save return address
+  li    t0, 0                   // number of threads that have been waken
+  la    t1, n_worker_threads
+  ld    t1, (t1)
+
+1:
+  // futex(futex_X, FUTEX_WAKE_PRIVATE, n_worker_threads)
+  la    a0, futex_X
+  li    a1, FUTEX_WAKE_PRIVATE
+  li    a2, 1                   // wake up at most 1 thread
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  add   t0, t0, a0              // track the number of waken threads so far
+
+  // keep waking up until all threads are waken up
+  blt   t0, t1, 1b
+
+  // restore return address and return
+  mv    ra, s0
+  ret
+
+//------------------------------------------------------------------------
+// mt_test function executed by child threads
+//
+//    Wait on futex_X
+//------------------------------------------------------------------------
+_mt_test:
+  // futex(futex_X, FUTEX_WAIT_PRIVATE, 1)
+  la    a0, futex_X
+  li    a1, FUTEX_WAIT_PRIVATE
+  li    a2, 0                   // expected val of futex_X
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// _check:
+//    Each thread should do LOOP_COUNT iterations
+//------------------------------------------------------------------------
+
+_check:
+  ret
+
+_fail:
+  li        a0, FAILURE
+  RVTEST_CODE_END
+
+  .data
+
+futex_X:  .dword  0
+futex_Y:  .dword  0
+
+count_master:   .dword  0
+count_child:    .dword  0
+
+MT_DATA
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex2_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex2_d.S
new file mode 100644
index 0000000..cfb36b5
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex2_d.S
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta, Moyang
+ */
+
+//------------------------------------------------------------------------
+// sysfutex_d tests FUTEX_WAKE_OP functionalities of futex system call:
+//    - make a thread wait on a variable
+//    - atomically wake up a thread waiting on a variable and perform
+//      a operation on a value
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt_ecall.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define NUM_THREADS 1
+#define LOOP_COUNT  1000
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, call _master function, waits for all
+// threads to complete, deallocates threads and checks result
+//------------------------------------------------------------------------
+  li      a0, NUM_THREADS
+  call    _create_threads
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  beqz    a0, _fail        // exit if there's no worker thread
+
+  call    _master_work
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _join
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _check
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _delete_threads
+
+  li      a0, SUCCESS
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// master_work function executed by the parent/master thread
+//
+//    Wake up thread(s) waiting on futex_X and then wait on futex_Y in a
+//    loop. Also atomically modify futex_Z during the wake-up.
+//------------------------------------------------------------------------
+_master_work:
+  mv    s0, ra                  // save return address
+  li    t0, LOOP_COUNT
+  la    t1, count_master
+  la    t3, count_Z
+
+1:
+  // futex(futex_X, FUTEX_WAKE_OP, 1, val2, futex_Z, val3 )
+  la    a0, futex_X
+  li    a1, FUTEX_WAKE_OP
+  li    a2, 1                   // wake up at most 1 thread
+  li    a3, 0                   // should not perform the second wake up
+  la    a4, futex_Z             // add 1 to futex_Z each time
+  li    a5, FUTEX_OP(FUTEX_OP_ADD, 1, FUTEX_OP_CMP_LT, 0)
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  // increment count_Z (should equals to futex_Z)
+  ld    t4, (t3)
+  addi  t4, t4, 1
+  sd    t4, (t3)
+
+  // keep waking up until at least one thread is waken up
+  beqz  a0, 1b
+
+  // increment count_master
+  ld    t2, (t1)
+  addi  t2, t2, 1
+  sd    t2, (t1)
+
+  // futex(futex_Y, FUTEX_WAIT_PRIVATE, 0)
+  la    a0, futex_Y
+  li    a1, FUTEX_WAIT_PRIVATE
+  li    a2, 0                   // expected val of futex_Y
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  // decrement t0
+  addi  t0, t0, -1
+  bnez  t0, 1b
+
+  // restore return address and return
+  mv    ra, s0
+  ret
+
+//------------------------------------------------------------------------
+// mt_test function executed by child threads
+//
+//    Wait on futex_X and then wake up threads waiting on futex_Y in a loop
+//------------------------------------------------------------------------
+_mt_test:
+  li    t0, LOOP_COUNT
+  la    t1, count_child
+
+1:
+  // futex(futex_X, FUTEX_WAIT_PRIVATE, 1)
+  la    a0, futex_X
+  li    a1, FUTEX_WAIT_PRIVATE
+  li    a2, 0                   // expected val of futex_X
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  // increment count_child
+  ld    t2, (t1)
+  addi  t2, t2, 1
+  sd    t2, (t1)
+
+2:
+  // futex(futex_Y, FUTEX_WAKE_PRIVATE, 0)
+  la    a0, futex_Y
+  li    a1, FUTEX_WAKE_PRIVATE
+  li    a2, 1                   // wake up at most 1 thread
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  // keep waking up until at least one thread is waken up
+  beqz  a0, 2b
+
+  // decrement t0
+  addi  t0, t0, -1
+  bnez  t0, 1b
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// _check:
+//    Each thread should do LOOP_COUNT iterations
+//------------------------------------------------------------------------
+
+_check:
+  la    t0, count_master
+  la    t1, count_child
+  li    t2, LOOP_COUNT
+  la    t3, count_Z
+  la    t4, futex_Z
+
+  ld    t0, (t0)
+  bne   t0, t2, _fail
+
+  ld    t1, (t1)
+  bne   t1, t2, _fail
+
+  ld    t3, (t3)
+  ld    t4, (t4)
+  bne   t3, t4, _fail
+
+  ret
+
+_fail:
+  li        a0, FAILURE
+  RVTEST_CODE_END
+
+  .data
+
+futex_X:  .dword  0
+futex_Y:  .dword  0
+futex_Z:  .dword  0
+
+count_master:   .dword  0
+count_child:    .dword  0
+count_Z:        .dword  0
+
+MT_DATA
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex3_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex3_d.S
new file mode 100644
index 0000000..4616de8
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex3_d.S
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta, Moyang Wang
+ */
+
+//------------------------------------------------------------------------
+// sysfutex3_d tests FUTEX_CMP_REQUEUE functionalities of futex system
+// call:
+//    - make worker threads waiting on futex 1
+//    - wake up 1 thread, requeue the rest of the threads to futex 2
+//    - wake all threads waiting on futex 1 and futex 2
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt_ecall.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define NUM_THREADS 20
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, call _master function, waits for all
+// threads to complete, deallocates threads and checks result
+//------------------------------------------------------------------------
+  li      a0, NUM_THREADS
+  call    _create_threads
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  beqz    a0, _fail        // exit if there's no worker thread
+
+  call    _master_work
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _join
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _check
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _delete_threads
+
+  li      a0, SUCCESS
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// master_work function executed by the parent/master thread
+//------------------------------------------------------------------------
+_master_work:
+  mv    s0, ra                  // save return address
+  li    t0, 0                   // number of threads that have been waken
+  la    t1, n_worker_threads
+  ld    t1, (t1)
+
+1:
+  // futex(futex_X, FUTEX_CMP_REQUEUE, 1, INT_MAX, futex_Y, *futex_X)
+  la    a0, futex_X
+  li    a1, FUTEX_CMP_REQUEUE
+  li    a2, 1                   // wake up at most 1 thread
+  li    a3, 1000                // practically is INT_MAX
+  la    a4, futex_Y             // move all other waiter to futex_Y
+  li    a5, 0
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  // loop until wake up one thread, all other waiter are requeued to
+  // futex_Y
+  beqz  a0, 1b
+
+  addi  t0, t0, 1
+
+2:
+  // alternating between futex_X and futex_Y
+  // because there could be new threads added to futex_X's queue
+  // after our futex_requeue
+
+  // futex(futex_Y, FUTEX_WAKE_PRIVATE, 0)
+  la    a0, futex_Y
+  li    a1, FUTEX_WAKE
+  li    a2, 1                   // wake up at most 1 thread
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  add   t0, t0, a0              // track the number of waken threads so far
+
+  // futex(futex_X, FUTEX_WAKE_PRIVATE, 0)
+  la    a0, futex_X
+  li    a1, FUTEX_WAKE
+  li    a2, 1                   // wake up at most 1 thread
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  add   t0, t0, a0              // track the number of waken threads so far
+
+  // keep waking up until all threads are waken up
+  blt   t0, t1, 2b
+
+  // restore return address and return
+  mv    ra, s0
+  ret
+
+//------------------------------------------------------------------------
+// mt_test function executed by child threads
+//
+//    Wait on futex_X
+//------------------------------------------------------------------------
+_mt_test:
+  // futex(futex_X, FUTEX_WAIT_PRIVATE, 1)
+  la    a0, futex_X
+  li    a1, FUTEX_WAIT
+  li    a2, 0                   // expected val of futex_X
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// _check:
+//    counter should equals to number of child threads
+//------------------------------------------------------------------------
+
+_check:
+  ret
+
+_fail:
+  li        a0, FAILURE
+  RVTEST_CODE_END
+
+  .data
+
+futex_X:  .dword  0
+futex_Y:  .dword  0
+
+MT_DATA
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex_d.S
new file mode 100644
index 0000000..707bdfa
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64samt/sysfutex_d.S
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// sysfutex_d tests basic functionalities of futex system call:
+//    - make a thread wait on a variable
+//    - wake up a thread waiting on a variable
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt_ecall.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define NUM_THREADS 1
+#define LOOP_COUNT  1000
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, call _master function, waits for all
+// threads to complete, deallocates threads and checks result
+//------------------------------------------------------------------------
+  li      a0, NUM_THREADS
+  call    _create_threads
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  beqz    a0, _fail        // exit if there's no worker thread
+  call    _master_work
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _join
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _check
+
+  la      t6, n_worker_threads
+  ld      a0, (t6)
+  call    _delete_threads
+
+  li      a0, SUCCESS
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// master_work function executed by the parent/master thread
+//
+//    Wake up thread(s) waiting on futex_X and then wait on futex_Y in a
+//    loop.
+//------------------------------------------------------------------------
+_master_work:
+  mv    s0, ra                  // save return address
+  li    t0, LOOP_COUNT
+  la    t1, count_master
+
+1:
+  // futex(futex_X, FUTEX_WAKE_PRIVATE, 1)
+  la    a0, futex_X
+  li    a1, FUTEX_WAKE_PRIVATE
+  li    a2, 1                   // wake up at most 1 thread
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  // keep waking up until at least one thread is waken up
+  beqz  a0, 1b
+
+  // increment count_master
+  ld    t2, (t1)
+  addi  t2, t2, 1
+  sd    t2, (t1)
+
+  // futex(futex_Y, FUTEX_WAIT_PRIVATE, 0)
+  la    a0, futex_Y
+  li    a1, FUTEX_WAIT_PRIVATE
+  li    a2, 0                   // expected val of futex_Y
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  // decrement t0
+  addi  t0, t0, -1
+  bnez  t0, 1b
+
+  // restore return address and return
+  mv    ra, s0
+  ret
+
+//------------------------------------------------------------------------
+// mt_test function executed by child threads
+//
+//    Wait on futex_X and then wake up threads waiting on futex_Y in a loop
+//------------------------------------------------------------------------
+_mt_test:
+  li    t0, LOOP_COUNT
+  la    t1, count_child
+
+1:
+  // futex(futex_X, FUTEX_WAIT_PRIVATE, 1)
+  la    a0, futex_X
+  li    a1, FUTEX_WAIT_PRIVATE
+  li    a2, 0                   // expected val of futex_X
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  // increment count_child
+  ld    t2, (t1)
+  addi  t2, t2, 1
+  sd    t2, (t1)
+
+2:
+  // futex(futex_Y, FUTEX_WAKE_PRIVATE, 0)
+  la    a0, futex_Y
+  li    a1, FUTEX_WAKE_PRIVATE
+  li    a2, 1                   // wake up at most 1 thread
+  li    a7, SYSCALL_FUTEX
+  ecall
+
+  // keep waking up until at least one thread is waken up
+  beqz  a0, 2b
+
+  // decrement t0
+  addi  t0, t0, -1
+  bnez  t0, 1b
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// _check:
+//    Each thread should do LOOP_COUNT iterations
+//------------------------------------------------------------------------
+
+_check:
+  la    t0, count_master
+  la    t1, count_child
+  li    t2, LOOP_COUNT
+
+  ld    t0, (t0)
+  bne   t0, t2, _fail
+
+  ld    t1, (t1)
+  bne   t1, t2, _fail
+
+  ret
+
+_fail:
+  li        a0, FAILURE
+  RVTEST_CODE_END
+
+  .data
+
+futex_X:  .dword  0
+futex_Y:  .dword  0
+
+count_master:   .dword  0
+count_child:    .dword  0
+
+MT_DATA
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64si/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64si/Makefrag
new file mode 100644
index 0000000..f9ca5e8
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64si/Makefrag
@@ -0,0 +1,16 @@
+#=======================================================================
+# Makefrag for rv64si tests
+#-----------------------------------------------------------------------
+
+rv64si_sc_tests = \
+	csr \
+	dirty \
+	ma_fetch \
+	scall \
+	wfi \
+	sbreak \
+
+rv64si_p_tests = $(addprefix rv64si-p-, $(rv64si_sc_tests))
+#rv64si_ps_tests = $(addprefix rv64si-ps-, $(rv64si_sc_tests))
+
+spike_tests += $(rv64si_p_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64si/csr.S b/tests/test-progs/asmtest/src/riscv/isa/rv64si/csr.S
new file mode 100644
index 0000000..dbe1c05
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64si/csr.S
@@ -0,0 +1,148 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# csr.S
+#-----------------------------------------------------------------------------
+#
+# Test CSRRx and CSRRxI instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64S
+RVTEST_CODE_BEGIN
+
+#ifdef __MACHINE_MODE
+  #define sscratch mscratch
+  #define sstatus mstatus
+  #define scause mcause
+  #define sepc mepc
+  #define sret mret
+  #define stvec_handler mtvec_handler
+  #undef SSTATUS_SPP
+  #define SSTATUS_SPP MSTATUS_MPP
+#endif
+
+  # For RV64, make sure UXL encodes RV64.  (UXL does not exist for RV32.)
+#if __riscv_xlen == 64
+  # If running in M mode, use mstatus.MPP to check existence of U mode.
+  # Otherwise, if in S mode, then U mode must exist and we don't need to check.
+#ifdef __MACHINE_MODE
+  li t0, MSTATUS_MPP
+  csrc mstatus, t0
+  csrr t1, mstatus
+  and t0, t0, t1
+  bnez t0, 1f
+#endif
+  # If U mode is present, UXL should be 2 (XLEN = 64-bit)
+  TEST_CASE(13, a0, SSTATUS_UXL & (SSTATUS_UXL << 1), csrr a0, sstatus; li a1, SSTATUS_UXL; and a0, a0, a1)
+#ifdef __MACHINE_MODE
+  j 2f
+1:
+  # If U mode is not present, UXL should be 0
+  TEST_CASE(14, a0, 0, csrr a0, sstatus; li a1, SSTATUS_UXL; and a0, a0, a1)
+2:
+#endif
+#endif
+
+  csrwi sscratch, 3
+  TEST_CASE( 2, a0,         3, csrr a0, sscratch);
+  TEST_CASE( 3, a1,         3, csrrci a1, sscratch, 1);
+  TEST_CASE( 4, a2,         2, csrrsi a2, sscratch, 4);
+  TEST_CASE( 5, a3,         6, csrrwi a3, sscratch, 2);
+  TEST_CASE( 6, a1,         2, li a0, 0xbad1dea; csrrw a1, sscratch, a0);
+  TEST_CASE( 7, a0, 0xbad1dea, li a0, 0x0001dea; csrrc a0, sscratch, a0);
+  TEST_CASE( 8, a0, 0xbad0000, li a0, 0x000beef; csrrs a0, sscratch, a0);
+  TEST_CASE( 9, a0, 0xbadbeef, csrr a0, sscratch);
+
+#ifdef __MACHINE_MODE
+  # Is F extension present?
+  csrr a0, misa
+  andi a0, a0, (1 << ('F' - 'A'))
+  beqz a0, 1f
+  # If so, make sure FP stores have no effect when mstatus.FS is off.
+  li a1, MSTATUS_FS
+  csrs mstatus, a1
+#ifdef __riscv_flen
+  fmv.s.x f0, x0
+  csrc mstatus, a1
+  la a1, fsw_data
+  TEST_CASE(10, a0, 1, fsw f0, (a1); lw a0, (a1));
+#else
+  # Fail if this test is compiled without F but executed on a core with F.
+  TEST_CASE(10, zero, 1)
+#endif
+1:
+
+  # Figure out if 'U' is set in misa
+  csrr a0, misa   # a0 = csr(misa)
+  srli a0, a0, 20 # a0 = a0 >> 20
+  andi a0, a0, 1  # a0 = a0 & 1
+  beqz a0, finish # if no user mode, skip the rest of these checks
+#endif /* __MACHINE_MODE */
+
+  # jump to user land
+  li t0, SSTATUS_SPP
+  csrc sstatus, t0
+  la t0, 1f
+  csrw sepc, t0
+  sret
+  1:
+
+  # Make sure writing the cycle counter causes an exception.
+  # Don't run in supervisor, as we don't delegate illegal instruction traps.
+#ifdef __MACHINE_MODE
+  TEST_CASE(11, a0, 255, li a0, 255; csrrw a0, cycle, x0);
+#endif
+
+  # Make sure reading status in user mode causes an exception.
+  # Don't run in supervisor, as we don't delegate illegal instruction traps.
+#ifdef __MACHINE_MODE
+  TEST_CASE(12, a0, 255, li a0, 255; csrr a0, sstatus)
+#else
+  TEST_CASE(12, x0, 0, nop)
+#endif
+
+finish:
+  RVTEST_PASS
+
+  # We should only fall through to this if scall failed.
+  TEST_PASSFAIL
+
+  .align 2
+  .global stvec_handler
+stvec_handler:
+  # Trapping on tests 10-12 is good news.
+  # Note that since the test didn't complete, TESTNUM is smaller by 1.
+  li t0, 9
+  bltu TESTNUM, t0, 1f
+  li t0, 11
+  bleu TESTNUM, t0, privileged
+1:
+
+  # catch RVTEST_PASS and kick it up to M-mode
+  csrr t0, scause
+  li t1, CAUSE_USER_ECALL
+  bne t0, t1, fail
+  RVTEST_PASS
+
+privileged:
+  # Make sure scause indicates a lack of privilege.
+  csrr t0, scause
+  li t1, CAUSE_ILLEGAL_INSTRUCTION
+  bne t0, t1, fail
+  # Return to user mode, but skip the trapping instruction.
+  csrr t0, sepc
+  addi t0, t0, 4
+  csrw sepc, t0
+  sret
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+fsw_data: .word 1
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64si/dirty.S b/tests/test-progs/asmtest/src/riscv/isa/rv64si/dirty.S
new file mode 100644
index 0000000..8444196
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64si/dirty.S
@@ -0,0 +1,129 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# dirty.S
+#-----------------------------------------------------------------------------
+#
+# Test VM referenced and dirty bits.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64M
+RVTEST_CODE_BEGIN
+
+  # Turn on VM
+  li a0, (SATP_MODE & ~(SATP_MODE<<1)) * SATP_MODE_SV39
+  la a1, page_table_1
+  srl a1, a1, RISCV_PGSHIFT
+  or a1, a1, a0
+  csrw sptbr, a1
+  sfence.vma
+
+  # Set up MPRV with MPP=S, so loads and stores use S-mode
+  li a1, ((MSTATUS_MPP & ~(MSTATUS_MPP<<1)) * PRV_S) | MSTATUS_MPRV
+  csrs mstatus, a1
+
+  # Try a faulting store to make sure dirty bit is not set
+  li TESTNUM, 2
+  li t2, 1
+  sw t2, dummy - DRAM_BASE, a0
+
+  # Set SUM=1 so user memory access is permitted
+  li TESTNUM, 3
+  li a1, ((MSTATUS_MPP & ~(MSTATUS_MPP<<1)) * PRV_S) | MSTATUS_SUM
+  csrs mstatus, a1
+
+  # Make sure SUM=1 works
+  lw t0, dummy - DRAM_BASE
+  bnez t0, die
+
+  # Try a non-faulting store to make sure dirty bit is set
+  sw t2, dummy - DRAM_BASE, a0
+
+  # Make sure it succeeded
+  lw t0, dummy - DRAM_BASE
+  bne t0, t2, die
+
+  # Leave MPRV
+  li t0, MSTATUS_MPRV
+  csrc mstatus, t0
+
+  # Make sure D bit is set
+  lw t0, page_table_1
+  li a0, PTE_A | PTE_D
+  and t0, t0, a0
+  bne t0, a0, die
+
+  # Enter MPRV again
+  li t0, MSTATUS_MPRV
+  csrs mstatus, t0
+
+  # Make sure that superpage entries trap when PPN LSBs are set.
+  li TESTNUM, 4
+  lw a0, page_table_1 - DRAM_BASE
+  or a0, a0, 1 << PTE_PPN_SHIFT
+  sw a0, page_table_1 - DRAM_BASE, t0
+  sfence.vma
+  sw a0, page_table_1 - DRAM_BASE, t0
+  j die
+  
+  RVTEST_PASS
+
+  TEST_PASSFAIL
+
+  .align 2
+  .global mtvec_handler
+mtvec_handler:
+  csrr t0, mcause
+  add t0, t0, -CAUSE_STORE_PAGE_FAULT
+  bnez t0, die
+
+  li t1, 2
+  bne TESTNUM, t1, 1f
+  # Make sure D bit is clear
+  lw t0, page_table_1
+  and t1, t0, PTE_D
+  bnez t1, die
+skip:
+  csrr t0, mepc
+  add t0, t0, 4
+  csrw mepc, t0
+  mret
+
+1:
+  li t1, 3
+  bne TESTNUM, t1, 1f
+  # The implementation doesn't appear to set D bits in HW.
+  # Make sure the D bit really is clear.
+  lw t0, page_table_1
+  and t1, t0, PTE_D
+  bnez t1, die
+  # Set the D bit.
+  or t0, t0, PTE_D
+  sw t0, page_table_1, t1
+  sfence.vma
+  mret
+
+1:
+  li t1, 4
+  bne TESTNUM, t1, 1f
+  j pass
+
+1:
+die:
+  RVTEST_FAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+.align 12
+page_table_1: .dword (DRAM_BASE/RISCV_PGSIZE << PTE_PPN_SHIFT) | PTE_V | PTE_U | PTE_R | PTE_W | PTE_X | PTE_A
+dummy: .dword 0
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64si/ma_fetch.S b/tests/test-progs/asmtest/src/riscv/isa/rv64si/ma_fetch.S
new file mode 100644
index 0000000..cd5a22d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64si/ma_fetch.S
@@ -0,0 +1,159 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# ma_fetch.S
+#-----------------------------------------------------------------------------
+#
+# Test misaligned fetch trap.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64S
+RVTEST_CODE_BEGIN
+
+#ifdef __MACHINE_MODE
+  #define sscratch mscratch
+  #define sstatus mstatus
+  #define scause mcause
+  #define sbadaddr mbadaddr
+  #define sepc mepc
+  #define sret mret
+  #define stvec_handler mtvec_handler
+#endif
+
+  .align 2
+  .option norvc
+
+  # Without RVC, the jalr should trap, and the handler will skip ahead.
+  # With RVC, the jalr should not trap, and "j fail" should get skipped.
+  li TESTNUM, 2
+  li t1, 0
+  la t0, 1f
+  jalr t1, t0, 2
+1:
+  .option rvc
+  c.j 1f
+  c.j 2f
+  .option norvc
+1:
+  j fail
+2:
+
+  // This test should pass, since JALR ignores the target LSB
+  li TESTNUM, 3
+  la t0, 1f
+  jalr t1, t0, 1
+1:
+  j 1f
+  j fail
+1:
+
+  li TESTNUM, 4
+  li t1, 0
+  la t0, 1f
+  jalr t1, t0, 3
+1:
+  .option rvc
+  c.j 1f
+  c.j 2f
+  .option norvc
+1:
+  j fail
+2:
+
+  # Like test 2, but with jal instead of jalr.
+  li TESTNUM, 5
+  li t1, 0
+  la t0, 1f
+  jal t1, 2f
+1:
+  .option rvc
+  c.j 1f
+2:
+  c.j 2f
+  .option norvc
+1:
+  j fail
+2:
+
+  # Like test 2, but with a taken branch instead of jalr.
+  li TESTNUM, 6
+  li t1, 0
+  la t0, 1f
+  beqz x0, 2f
+1:
+  .option rvc
+  c.j 1f
+2:
+  c.j 2f
+  .option norvc
+1:
+  j fail
+2:
+
+  # Not-taken branches should not trap, even without RVC.
+  li TESTNUM, 7
+  bnez x0, 1f
+  j 2f
+  .option rvc
+  c.j 1f
+1:
+  c.j 1f
+  .option norvc
+1:
+  j fail
+2:
+
+  j pass
+
+  TEST_PASSFAIL
+
+  .align 2
+  .global stvec_handler
+stvec_handler:
+  # tests 2, 4, 5, and 6 should trap
+  li a0, 2
+  beq TESTNUM, a0, 1f
+  li a0, 4
+  beq TESTNUM, a0, 1f
+  li a0, 5
+  beq TESTNUM, a0, 1f
+  li a0, 6
+  beq TESTNUM, a0, 1f
+  j fail
+1:
+
+  # verify that return address was not written
+  bnez t1, fail
+
+  # verify trap cause
+  li a1, CAUSE_MISALIGNED_FETCH
+  csrr a0, scause
+  bne a0, a1, fail
+
+  # verify that epc == &jalr (== t0 - 4)
+  csrr a1, sepc
+  addi a1, a1, 4
+  bne t0, a1, fail
+
+  # verify that badaddr == 0 or badaddr == t0+2.
+  csrr a0, sbadaddr
+  beqz a0, 1f
+  addi a0, a0, -2
+  bne a0, t0, fail
+1:
+
+  addi a1, a1, 12
+  csrw sepc, a1
+  sret
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64si/sbreak.S b/tests/test-progs/asmtest/src/riscv/isa/rv64si/sbreak.S
new file mode 100644
index 0000000..31efff8
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64si/sbreak.S
@@ -0,0 +1,51 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# scall.S
+#-----------------------------------------------------------------------------
+#
+# Test syscall trap.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64S
+RVTEST_CODE_BEGIN
+
+#ifdef __MACHINE_MODE
+  #define sscratch mscratch
+  #define sstatus mstatus
+  #define scause mcause
+  #define sepc mepc
+  #define sret mret
+  #define stvec_handler mtvec_handler
+#endif
+
+  li TESTNUM, 2
+
+do_break:
+  sbreak
+  j fail
+
+  TEST_PASSFAIL
+
+  .align 2
+  .global stvec_handler
+stvec_handler:
+  li t1, CAUSE_BREAKPOINT
+  csrr t0, scause
+  bne t0, t1, fail
+  la t1, do_break
+  csrr t0, sepc
+  bne t0, t1, fail
+  j pass
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64si/scall.S b/tests/test-progs/asmtest/src/riscv/isa/rv64si/scall.S
new file mode 100644
index 0000000..0579806
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64si/scall.S
@@ -0,0 +1,77 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# scall.S
+#-----------------------------------------------------------------------------
+#
+# Test syscall trap.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64S
+RVTEST_CODE_BEGIN
+
+#ifdef __MACHINE_MODE
+  #define sscratch mscratch
+  #define sstatus mstatus
+  #define scause mcause
+  #define sepc mepc
+  #define sret mret
+  #define stvec_handler mtvec_handler
+  #undef SSTATUS_SPP
+  #define SSTATUS_SPP MSTATUS_MPP
+#endif
+
+  li TESTNUM, 2
+
+  # This is the expected trap code.
+  li t1, CAUSE_USER_ECALL
+
+#ifdef __MACHINE_MODE
+  # If running in M mode, use mstatus.MPP to check existence of U mode.
+  # Otherwise, if in S mode, then U mode must exist and we don't need to check.
+  li t0, MSTATUS_MPP
+  csrc mstatus, t0
+  csrr t1, mstatus
+  and t0, t0, t1
+  beqz t0, 1f
+
+  # If U mode doesn't exist, mcause should indicate ECALL from M mode.
+  li t1, CAUSE_MACHINE_ECALL
+#endif
+
+1:
+  li t0, SSTATUS_SPP
+  csrc sstatus, t0
+  la t0, 1f
+  csrw sepc, t0
+  sret
+1:
+
+  li TESTNUM, 1
+do_scall:
+  scall
+  j fail
+
+  TEST_PASSFAIL
+
+  .align 2
+  .global stvec_handler
+stvec_handler:
+  csrr t0, scause
+  bne t0, t1, fail
+  la t2, do_scall
+  csrr t0, sepc
+  bne t0, t2, fail
+  j pass
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64si/wfi.S b/tests/test-progs/asmtest/src/riscv/isa/rv64si/wfi.S
new file mode 100644
index 0000000..0302034
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64si/wfi.S
@@ -0,0 +1,33 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# wfi.S
+#-----------------------------------------------------------------------------
+#
+# Test wait-for-interrupt instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64S
+RVTEST_CODE_BEGIN
+
+  # Make sure wfi doesn't halt the hart, even if interrupts are disabled
+  csrc sstatus, SSTATUS_SIE
+  csrs sie, SIP_SSIP
+  csrs sip, SIP_SSIP
+  wfi
+
+  RVTEST_PASS
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/Makefrag
new file mode 100644
index 0000000..5019226
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/Makefrag
@@ -0,0 +1,14 @@
+#=======================================================================
+# Makefrag for rv64ua tests
+#-----------------------------------------------------------------------
+
+rv64ua_sc_tests = \
+	amoadd_d amoand_d amomax_d amomaxu_d amomin_d amominu_d amoor_d amoxor_d amoswap_d \
+	amoadd_w amoand_w amomax_w amomaxu_w amomin_w amominu_w amoor_w amoxor_w amoswap_w \
+	lrsc \
+
+rv64ua_p_tests = $(addprefix rv64ua-p-, $(rv64ua_sc_tests))
+rv64ua_v_tests = $(addprefix rv64ua-v-, $(rv64ua_sc_tests))
+rv64ua_ps_tests = $(addprefix rv64ua-ps-, $(rv64ua_sc_tests))
+
+spike_tests += $(rv64ua_p_tests) $(rv64ua_v_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoadd_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoadd_d.S
new file mode 100644
index 0000000..05b2f38
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoadd_d.S
@@ -0,0 +1,47 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoadd_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amoadd.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sd a0, 0(a3); \
+    amoadd.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xffffffff7ffff800, ld a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0xffffffff7ffff800, \
+    amoadd.d a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xffffffff7ffff000, ld a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoadd_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoadd_w.S
new file mode 100644
index 0000000..d076d45
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoadd_w.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoadd_w.S
+#-----------------------------------------------------------------------------
+#
+# Test amoadd.w instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sw a0, 0(a3); \
+    amoadd.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0x000000007ffff800, lw a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0x000000007ffff800, \
+    li  a1, 0xffffffff80000000; \
+    amoadd.w a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xfffffffffffff800, lw a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+    .bss
+    .align 3
+amo_operand:
+    .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoand_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoand_d.S
new file mode 100644
index 0000000..c1148c0
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoand_d.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoand_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amoand.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sd a0, 0(a3); \
+    amoand.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xffffffff80000000, ld a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0xffffffff80000000, \
+    li  a1, 0x0000000080000000; \
+    amoand.d a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0x0000000080000000, ld a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoand_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoand_w.S
new file mode 100644
index 0000000..7fe3bd0
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoand_w.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoand.w.S
+#-----------------------------------------------------------------------------
+#
+# Test amoand.w instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sw a0, 0(a3); \
+    amoand.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xffffffff80000000, lw a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0xffffffff80000000, \
+    li  a1, 0x0000000080000000; \
+    amoand.w a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xffffffff80000000, lw a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomax_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomax_d.S
new file mode 100644
index 0000000..b7f8703
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomax_d.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amomax_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amomax.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sd a0, 0(a3); \
+    amomax.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xfffffffffffff800, ld a5, 0(a3))
+
+  TEST_CASE(4, a4, 0, \
+    li a1, 1; \
+    sd x0, 0(a3); \
+    amomax.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 1, ld a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomax_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomax_w.S
new file mode 100644
index 0000000..f986205
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomax_w.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amomax_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amomax.w instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sw a0, 0(a3); \
+    amomax.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xfffffffffffff800, lw a5, 0(a3))
+
+  TEST_CASE(4, a4, 0, \
+    li a1, 1; \
+    sw x0, 0(a3); \
+    amomax.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 1, lw a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomaxu_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomaxu_d.S
new file mode 100644
index 0000000..227ac4c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomaxu_d.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amomaxu_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amomaxu.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sd a0, 0(a3); \
+    amomaxu.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xfffffffffffff800, ld a5, 0(a3))
+
+  TEST_CASE(4, a4, 0, \
+    li a1, 0xffffffffffffffff; \
+    sd x0, 0(a3); \
+    amomaxu.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xffffffffffffffff, ld a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomaxu_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomaxu_w.S
new file mode 100644
index 0000000..eb27d07
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomaxu_w.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amomaxu_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amomaxu.w instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sw a0, 0(a3); \
+    amomaxu.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xfffffffffffff800, lw a5, 0(a3))
+
+  TEST_CASE(4, a4, 0, \
+    li a1, 0xffffffffffffffff; \
+    sw x0, 0(a3); \
+    amomaxu.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xffffffffffffffff, lw a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomin_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomin_d.S
new file mode 100644
index 0000000..ee6bbf3
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomin_d.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amomin_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amomin.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sd a0, 0(a3); \
+    amomin.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xffffffff80000000, ld a5, 0(a3))
+
+  TEST_CASE(4, a4, 0, \
+    li a1, 0xffffffffffffffff; \
+    sd x0, 0(a3); \
+    amomin.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xffffffffffffffff, ld a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomin_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomin_w.S
new file mode 100644
index 0000000..1337d2c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amomin_w.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amomin_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amomin.w instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sw a0, 0(a3); \
+    amomin.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xffffffff80000000, lw a5, 0(a3))
+
+  TEST_CASE(4, a4, 0, \
+    li a1, 0xffffffffffffffff; \
+    sw x0, 0(a3); \
+    amomin.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xffffffffffffffff, lw a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amominu_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amominu_d.S
new file mode 100644
index 0000000..08bfb5b
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amominu_d.S
@@ -0,0 +1,49 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amominu_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amominu.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sd a0, 0(a3); \
+    amominu.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xffffffff80000000, ld a5, 0(a3))
+
+  TEST_CASE(4, a4, 0, \
+    li a1, 0xffffffffffffffff; \
+    sd x0, 0(a3); \
+    amominu.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0, ld a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
+  
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amominu_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amominu_w.S
new file mode 100644
index 0000000..f45f856
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amominu_w.S
@@ -0,0 +1,49 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amominu_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amominu.w instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sw a0, 0(a3); \
+    amominu.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xffffffff80000000, lw a5, 0(a3))
+
+  TEST_CASE(4, a4, 0, \
+    li a1, 0xffffffffffffffff; \
+    sw x0, 0(a3); \
+    amominu.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0, lw a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
+  
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoor_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoor_d.S
new file mode 100644
index 0000000..6f71495
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoor_d.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoor_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amoor.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sd a0, 0(a3); \
+    amoor.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xfffffffffffff800, ld a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0xfffffffffffff800, \
+    li  a1, 1; \
+    amoor.d a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xfffffffffffff801, ld a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoor_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoor_w.S
new file mode 100644
index 0000000..e64b8c2
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoor_w.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoor.w.S
+#-----------------------------------------------------------------------------
+#
+# Test amoor.w instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sw a0, 0(a3); \
+    amoor.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xfffffffffffff800, lw a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0xfffffffffffff800, \
+    li  a1, 1; \
+    amoor.w a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xfffffffffffff801, lw a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoswap_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoswap_d.S
new file mode 100644
index 0000000..6b07d74
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoswap_d.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoswap.d.S
+#-----------------------------------------------------------------------------
+#
+# Test amoswap.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sd a0, 0(a3); \
+    amoswap.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xfffffffffffff800, ld a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0xfffffffffffff800, \
+    li  a1, 0x0000000080000000; \
+    amoswap.d a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0x0000000080000000, ld a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoswap_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoswap_w.S
new file mode 100644
index 0000000..c4276dc
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoswap_w.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoswap_w.S
+#-----------------------------------------------------------------------------
+#
+# Test amoswap.w instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sw a0, 0(a3); \
+    amoswap.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0xfffffffffffff800, lw a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0xfffffffffffff800, \
+    li  a1, 0x0000000080000000; \
+    amoswap.w a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xffffffff80000000, lw a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoxor_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoxor_d.S
new file mode 100644
index 0000000..8305434
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoxor_d.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoxor_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amoxor.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sd a0, 0(a3); \
+    amoxor.d	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0x000000007ffff800, ld a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0x000000007ffff800, \
+    li  a1, 1; \
+    amoxor.d a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0x000000007ffff801, ld a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoxor_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoxor_w.S
new file mode 100644
index 0000000..1b6fc48
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/amoxor_w.S
@@ -0,0 +1,48 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoxor_w.S
+#-----------------------------------------------------------------------------
+#
+# Test amoxor.w instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a4, 0xffffffff80000000, \
+    li a0, 0xffffffff80000000; \
+    li a1, 0xfffffffffffff800; \
+    la a3, amo_operand; \
+    sw a0, 0(a3); \
+    amoxor.w	a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(3, a5, 0x7ffff800, lw a5, 0(a3))
+
+  # try again after a cache miss
+  TEST_CASE(4, a4, 0x7ffff800, \
+    li  a1, 0xc0000001; \
+    amoxor.w a4, a1, 0(a3); \
+  )
+
+  TEST_CASE(5, a5, 0xffffffffbffff801, lw a5, 0(a3))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
+
+  .bss
+  .align 3
+amo_operand:
+  .dword 0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/lrsc.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/lrsc.S
new file mode 100644
index 0000000..11eb7de
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/lrsc.S
@@ -0,0 +1,85 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# lrsr.S
+#-----------------------------------------------------------------------------
+#
+# Test LR/SC instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+# get a unique core id
+la a0, coreid
+li a1, 1
+amoadd.w a2, a1, (a0)
+
+# for now, only run this on core 0
+1:li a3, 1
+bgeu a2, a3, 1b
+
+1: lw a1, (a0)
+bltu a1, a3, 1b
+
+# make sure that sc without a reservation fails.
+TEST_CASE( 2, a4, 1, \
+  la a0, foo; \
+  sc.w a4, x0, (a0); \
+)
+
+# make sure that sc with the wrong reservation fails.
+# TODO is this actually mandatory behavior?
+TEST_CASE( 3, a4, 1, \
+  la a0, foo; \
+  add a1, a0, 1024; \
+  lr.w a1, (a1); \
+  sc.w a4, a1, (a0); \
+)
+
+#define LOG_ITERATIONS 10
+
+# have each core add its coreid+1 to foo 1024 times
+la a0, foo
+li a1, 1<<LOG_ITERATIONS
+addi a2, a2, 1
+1: lr.w a4, (a0)
+add a4, a4, a2
+sc.w a4, a4, (a0)
+bnez a4, 1b
+add a1, a1, -1
+bnez a1, 1b
+
+# wait for all cores to finish
+la a0, barrier
+li a1, 1
+amoadd.w x0, a1, (a0)
+1: lw a1, (a0)
+blt a1, a3, 1b
+fence
+
+# expected result is 512*ncores*(ncores+1)
+TEST_CASE( 4, a0, 0, \
+  lw a0, foo; \
+  slli a1, a3, LOG_ITERATIONS-1; \
+1:sub a0, a0, a1; \
+  addi a3, a3, -1; \
+  bgez a3, 1b
+)
+
+TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+coreid: .word 0
+barrier: .word 0
+foo: .word 0
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ua/test.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/test.S
new file mode 100644
index 0000000..9e6ab68
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ua/test.S
@@ -0,0 +1,25 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# amoadd_d.S
+#-----------------------------------------------------------------------------
+#
+# Test amoadd.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+la        a0, shared_var
+amoadd.w  t0, t1, 0(a0)
+lr.w      t2, 0(a0)
+//sc.w      t0, t1, 0(a0)
+
+RVTEST_CODE_END
+
+  .data
+shared_var:     .dword    0
+non_shared_var: .dword    0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/Makefrag
new file mode 100644
index 0000000..56a189f
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/Makefrag
@@ -0,0 +1,10 @@
+#=======================================================================
+# Makefrag for rv64ua_mt tests
+#-----------------------------------------------------------------------
+
+rv64ua_mt_tests = amoadd_d amoswap_d amoxor_d amoand_d \
+                  amoor_d amomin_d amomax_d amominu_d amomaxu_d lrsc_d \
+
+rv64uamt_ps_tests = $(addprefix rv64uamt-ps-, $(rv64ua_mt_tests))
+
+spike_tests += $(rv64uamt_ps_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoadd_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoadd_d.S
new file mode 100644
index 0000000..cf744c4
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoadd_d.S
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests amoadd_d instruction in multi-threading system.
+// Each thread increments a globally shared variable LOOP_COUNT times.
+// Once a thread completes, it signals its completition by atomically
+// incrementing a barrier variable.
+// Master thread (i.e., thread 0) waits for all threads to complete by
+// spinning on the barrier variable until all threads update the variable.
+// Then, the master thread checks the shared variable's value.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define LOOP_COUNT  1000
+#define RESULT      LOOP_COUNT * NUM_THREADS
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  li        t0, 1               // one operand of amoadd_w
+  li        t1, LOOP_COUNT      // loop count
+  la        a0, shared_var
+1:
+  amoadd.d  zero, t0, (a0)
+  addi      t1, t1, -1
+  bnez      t1, 1b
+
+  la        a0, barrier
+  amoadd.d  zero, t0, (a0)
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, shared_var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoand_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoand_d.S
new file mode 100644
index 0000000..668e4c3
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoand_d.S
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests amoand_w instruction in multi-threading system.
+// All threads execute an amoxor_w instruction.
+// Master thread (i.e., thread 0) waits for all threads to complete by
+// spinning on the barrier variable until all threads update the variable.
+// Then, the master thread checks the shared variable's value.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define RESULT      0x000000008E003441
+
+//------------------------------------------------------------------------
+// Reinitialize shared_var to 0xffffffffffffffff
+//------------------------------------------------------------------------
+  la  a0, shared_var
+  li  t0, 0xffffffffffffffff
+  sd  t0, (a0)
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  la        a0, shared_var
+  la        t0, array_index
+  li        t1, 8
+  amoadd.d  t1, t1, (t0)        // get my array_index
+
+  la        t0, array
+  add       t0, t0, t1
+  ld        t0, (t0)            // get array[array_index]
+
+  amoand.d  zero, t0, (a0)
+
+  li        t0, 1
+  la        a0, barrier
+  amoadd.d  zero, t0, (a0)
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, shared_var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
+array_index:    .dword    0;
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amomax_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amomax_d.S
new file mode 100644
index 0000000..54bc321
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amomax_d.S
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests amomax_d instruction in multi-threading system.
+// All threads execute an amomax_w instruction.
+// Master thread (i.e., thread 0) waits for all threads to complete by
+// spinning on the barrier variable until all threads update the variable.
+// Then, the master thread checks the shared variable's value.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define RESULT      0x12343eeaaf423451
+
+//------------------------------------------------------------------------
+// Reinitialize shared_var to 0x8000000000000000
+//------------------------------------------------------------------------
+  la  a0, shared_var
+  li  t0, 0x8000000000000000
+  sd  t0, (a0)
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  la        a0, shared_var
+  la        t0, array_index
+  li        t1, 8
+  amoadd.d  t1, t1, (t0)        // get my array_index
+
+  la        t0, array
+  add       t0, t0, t1
+  ld        t0, (t0)            // get array[array_index]
+
+  amomax.d  zero, t0, (a0)
+
+  li        t0, 1
+  la        a0, barrier
+  amoadd.d  zero, t0, (a0)
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, shared_var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
+array_index:    .dword    0;
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amomaxu_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amomaxu_d.S
new file mode 100644
index 0000000..e5db058
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amomaxu_d.S
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests amomax_d instruction in multi-threading system.
+// All threads execute an amomax_w instruction.
+// Master thread (i.e., thread 0) waits for all threads to complete by
+// spinning on the barrier variable until all threads update the variable.
+// Then, the master thread checks the shared variable's value.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define RESULT      0xdeadbeefdeadbeef
+
+//------------------------------------------------------------------------
+// Reinitialize shared_var to 0x0000000000000000
+//------------------------------------------------------------------------
+  la  a0, shared_var
+  li  t0, 0x0000000000000000
+  sd  t0, (a0)
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  la        a0, shared_var
+  la        t0, array_index
+  li        t1, 8
+  amoadd.d  t1, t1, (t0)        // get my array_index
+
+  la        t0, array
+  add       t0, t0, t1
+  ld        t0, (t0)            // get array[array_index]
+
+  amomaxu.d zero, t0, (a0)
+
+  li        t0, 1
+  la        a0, barrier
+  amoadd.d  zero, t0, (a0)
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, shared_var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
+array_index:    .dword    0;
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amomin_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amomin_d.S
new file mode 100644
index 0000000..684e9ed
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amomin_d.S
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests amomin_d instruction in multi-threading system.
+// All threads execute an amomin_d instruction.
+// Master thread (i.e., thread 0) waits for all threads to complete by
+// spinning on the barrier variable until all threads update the variable.
+// Then, the master thread checks the shared variable's value.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define RESULT      0xDEADBEEFDEADBEEF
+
+//------------------------------------------------------------------------
+// Reinitialize shared_var to 0x7fffffffffffffff
+//------------------------------------------------------------------------
+  la  a0, shared_var
+  li  t0, 0x7fffffffffffffff
+  sd  t0, (a0)
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  la        a0, shared_var
+  la        t0, array_index
+  li        t1, 8
+  amoadd.d  t1, t1, (t0)        // get my array_index
+
+  la        t0, array
+  add       t0, t0, t1
+  ld        t0, (t0)            // get array[array_index]
+
+  amomin.d  zero, t0, (a0)
+
+  li        t0, 1
+  la        a0, barrier
+  amoadd.d  zero, t0, (a0)
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, shared_var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
+array_index:    .dword    0;
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amominu_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amominu_d.S
new file mode 100644
index 0000000..a12443e
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amominu_d.S
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests amominu_d instruction in multi-threading system.
+// All threads execute an amominu_d instruction.
+// Master thread (i.e., thread 0) waits for all threads to complete by
+// spinning on the barrier variable until all threads update the variable.
+// Then, the master thread checks the shared variable's value.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define RESULT      0x00000000deadbeef
+
+//------------------------------------------------------------------------
+// Reinitialize shared_var to 0xffffffffffffffff
+//------------------------------------------------------------------------
+  la  a0, shared_var
+  li  t0, 0xffffffffffffffff
+  sd  t0, (a0)
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  la        a0, shared_var
+  la        t0, array_index
+  li        t1, 8
+  amoadd.d  t1, t1, (t0)        // get my array_index
+
+  la        t0, array
+  add       t0, t0, t1
+  ld        t0, (t0)            // get array[array_index]
+
+  amominu.d zero, t0, (a0)
+
+  li        t0, 1
+  la        a0, barrier
+  amoadd.d  zero, t0, (a0)
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, shared_var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
+array_index:    .dword    0;
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoor_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoor_d.S
new file mode 100644
index 0000000..1bcc371
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoor_d.S
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests amoor_d instruction in multi-threading system.
+// All threads execute an amoor_w instruction.
+// Master thread (i.e., thread 0) waits for all threads to complete by
+// spinning on the barrier variable until all threads update the variable.
+// Then, the master thread checks the shared variable's value.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define RESULT      0xDEBDBEEFFFEFBEFF
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  la        a0, shared_var
+  la        t0, array_index
+  li        t1, 8
+  amoadd.d  t1, t1, (t0)        // get my array_index
+
+  la        t0, array
+  add       t0, t0, t1
+  ld        t0, (t0)            // get array[array_index]
+
+  amoor.d   zero, t0, (a0)
+
+  li        t0, 1
+  la        a0, barrier
+  amoadd.d  zero, t0, (a0)
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, shared_var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
+array_index:    .dword    0;
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoswap_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoswap_d.S
new file mode 100644
index 0000000..5733de9
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoswap_d.S
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests amoswap.d instruction in multi-threading system.
+// All threads execute a critical section LOOP_COUNT times. A thread
+// gets into a critical section by acquiring a lock variable (i.e.,
+// shared_var) and checking return value.
+// 0 means the lock is not being locked. Each thread increments
+// a variable (i.e., var) inside the critical section and releases the
+// lock by swapping back 0 to the lock variable.
+// The master thread (i.e., thread 0) waits for all threads to complete
+// and compare the var's value to the expected result.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define LOOP_COUNT  1000
+#define RESULT      NUM_THREADS * LOOP_COUNT
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  li        t0, 1               // initialize the swap value (1-locked)
+  li        t1, LOOP_COUNT
+  la        t2, var             // load the var's address
+  la        a0, shared_var
+
+1:
+  amoswap.d.aq  s2, t0, (a0)    // try to swap t0 with the lock
+  bnez          s2, 1b          // retry if the lock is being held
+
+  lw            t3, (t2)        // load the var's value
+  addi          t3, t3, 1       // add 1 to the value
+  sw            t3, (t2)        // store the new value to var
+
+  amoswap.d.rl  zero, zero, (a0)// release the lock by swapping back 0
+
+  addi          t1, t1, -1      // decrement the loop_count
+  bnez          t1, 1b          // repeat if not done yet
+
+  la            a0, barrier
+  amoadd.d      zero, t0, (a0)  // signal this thread's completion
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
+var: .dword   0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoxor_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoxor_d.S
new file mode 100644
index 0000000..6650e45
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/amoxor_d.S
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests amoxor_d instruction in multi-threading system.
+// All threads execute an amoxor_w instruction.
+// Master thread (i.e., thread 0) waits for all threads to complete by
+// spinning on the barrier variable until all threads update the variable.
+// Then, the master thread checks the shared variable's value.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define RESULT      0xCC998005AF423451
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  la        a0, shared_var
+  la        t0, array_index
+  li        t1, 8
+  amoadd.d  t1, t1, (t0)        // get my array_index
+
+  la        t0, array
+  add       t0, t0, t1
+  ld        t0, (t0)            // get array[array_index]
+
+  amoxor.d  zero, t0, (a0)
+
+  li        t0, 1
+  la        a0, barrier
+  amoadd.d  zero, t0, (a0)
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, shared_var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
+array_index:    .dword    0;
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/lrsc_d.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/lrsc_d.S
new file mode 100644
index 0000000..fc07783
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uamt/lrsc_d.S
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018, Cornell University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * Authors: Tuan Ta
+ */
+
+//------------------------------------------------------------------------
+// This code tests lr.d and sc.d instructions in multi-threading system.
+// All threads execute a critical section LOOP_COUNT times. A thread
+// gets into a critical section by acquiring a lock variable (i.e.,
+// shared_var) and checking return value.
+// 0 means the lock is not being locked. Each thread increments
+// a variable (i.e., var) inside the critical section and releases the
+// lock by swapping back 0 to the lock variable.
+// The master thread (i.e., thread 0) waits for all threads to complete
+// and compare the var's value to the expected result.
+//------------------------------------------------------------------------
+
+#include "riscv_test.h"
+#include "test_macros.h"
+#include "test_macros_mt.h"
+
+  RVTEST_RV64U
+  RVTEST_CODE_BEGIN
+
+#define LOOP_COUNT  1000
+#define RESULT      NUM_THREADS * LOOP_COUNT
+
+//------------------------------------------------------------------------
+// Master thread creates new threads, waits for all threads to complete,
+// deallocates threads and checks result
+//------------------------------------------------------------------------
+  call _create_threads
+  call _join
+  call _delete_threads
+  call _check
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// mt_test function executed in child threads
+// A child thread signals its completion by atomicaly adding 1 to barrier
+//------------------------------------------------------------------------
+_mt_test:
+  li        t0, 1               // initialize the swap value (1-locked)
+  li        t1, LOOP_COUNT
+  la        t2, var             // load the var's address
+  la        a0, shared_var
+
+1:
+  lr.d.aq       s2, (a0)        // load and reserve a0
+  bnez          s2, 1b          // retry lr if the lock is being held
+  sc.d.rl       s2, t0, (a0)    // try to lock a0
+  bnez          s2, 1b          // retry if sc failed
+
+  lw            t3, (t2)        // load the var's value
+  addi          t3, t3, 1       // add 1 to the value
+  sw            t3, (t2)        // store the new value to var
+
+  sd            zero, (a0)      // release the lock by storing 0 to a0
+
+  addi          t1, t1, -1      // decrement the loop_count
+  bnez          t1, 1b          // repeat if not done yet
+
+  la            a0, barrier
+  amoadd.d      zero, t0, (a0)  // signal this thread's completion
+
+  RVTEST_CODE_END
+
+//------------------------------------------------------------------------
+// Master thread checks result
+//------------------------------------------------------------------------
+_check:
+  la        a0, var
+  li        a1, RESULT
+  ld        a0, (a0)
+  bne       a0, a1, _fail
+  li        a0, SUCCESS
+  ret
+
+_fail:
+  li        a0, FAILURE
+  ret
+
+  .data
+
+MT_DATA
+var: .dword   0
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uc/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64uc/Makefrag
new file mode 100644
index 0000000..90aeb63
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uc/Makefrag
@@ -0,0 +1,12 @@
+#=======================================================================
+# Makefrag for rv64uc tests
+#-----------------------------------------------------------------------
+
+rv64uc_sc_tests = \
+	rvc \
+
+rv64ua_p_tests = $(addprefix rv64ua-p-, $(rv64ua_sc_tests))
+rv64uc_v_tests = $(addprefix rv64uc-v-, $(rv64uc_sc_tests))
+rv64ua_ps_tests = $(addprefix rv64ua-ps-, $(rv64ua_sc_tests))
+
+spike_tests += $(rv64uc_p_tests) $(rv64uc_v_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uc/rvc.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uc/rvc.S
new file mode 100644
index 0000000..3629d1d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uc/rvc.S
@@ -0,0 +1,154 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# rvc.S
+#-----------------------------------------------------------------------------
+#
+# Test RVC corner cases.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  .align 2
+  .option push
+  .option norvc
+
+  #define RVC_TEST_CASE(n, r, v, code...) \
+    TEST_CASE (n, r, v, .option push; .option rvc; code; .align 2; .option pop)
+
+  // Make sure fetching a 4-byte instruction across a page boundary works.
+  li TESTNUM, 2
+  li a1, 666
+  TEST_CASE (2, a1, 667, \
+        j 1f; \
+        .align 3; \
+        data: \
+          .dword 0xfedcba9876543210; \
+          .dword 0xfedcba9876543210; \
+        .align 12; \
+        .skip 4094; \
+      1: addi a1, a1, 1)
+
+  li sp, 0x1234
+  RVC_TEST_CASE (3, a0, 0x1234 + 1020, c.addi4spn a0, sp, 1020)
+  RVC_TEST_CASE (4, sp, 0x1234 + 496, c.addi16sp sp, 496)
+  RVC_TEST_CASE (5, sp, 0x1234 + 496 - 512, c.addi16sp sp, -512)
+
+  la a1, data
+  RVC_TEST_CASE (6, a2, 0xfffffffffedcba99, c.lw a0, 4(a1); addi a0, a0, 1; c.sw a0, 4(a1); c.lw a2, 4(a1))
+#if __riscv_xlen == 64
+  RVC_TEST_CASE (7, a2, 0xfedcba9976543211, c.ld a0, 0(a1); addi a0, a0, 1; c.sd a0, 0(a1); c.ld a2, 0(a1))
+#endif
+
+  RVC_TEST_CASE (8, a0, -15, ori a0, x0, 1; c.addi a0, -16)
+  RVC_TEST_CASE (9, a5, -16, ori a5, x0, 1; c.li a5, -16)
+#if __riscv_xlen == 64
+  RVC_TEST_CASE (10, a0, 0x76543210, ld a0, (a1); c.addiw a0, -1)
+#endif
+
+  RVC_TEST_CASE (11, s0, 0xffffffffffffffe1, c.lui s0, 0xfffe1; c.srai s0, 12)
+#if __riscv_xlen == 64
+  RVC_TEST_CASE (12, s0, 0x000fffffffffffe1, c.lui s0, 0xfffe1; c.srli s0, 12)
+#else
+  RVC_TEST_CASE (12, s0, 0x000fffe1, c.lui s0, 0xfffe1; c.srli s0, 12)
+#endif
+  RVC_TEST_CASE (14, s0, ~0x11, c.li s0, -2; c.andi s0, ~0x10)
+  RVC_TEST_CASE (15, s1, 14, li s1, 20; li a0, 6; c.sub s1, a0)
+  RVC_TEST_CASE (16, s1, 18, li s1, 20; li a0, 6; c.xor s1, a0)
+  RVC_TEST_CASE (17, s1, 22, li s1, 20; li a0, 6; c.or s1, a0)
+  RVC_TEST_CASE (18, s1,  4, li s1, 20; li a0, 6; c.and s1, a0)
+#if __riscv_xlen == 64
+  RVC_TEST_CASE (19, s1, 0xffffffff80000000, li s1, 0x7fffffff; li a0, -1; c.subw s1, a0)
+  RVC_TEST_CASE (20, s1, 0xffffffff80000000, li s1, 0x7fffffff; li a0, 1; c.addw s1, a0)
+#endif
+  RVC_TEST_CASE (21, s0, 0x12340, li s0, 0x1234; c.slli s0, 4)
+
+  RVC_TEST_CASE (30, ra, 0, \
+        li ra, 0; \
+        c.j 1f; \
+        c.j 2f; \
+      1:c.j 1f; \
+      2:j fail; \
+      1:)
+
+  RVC_TEST_CASE (31, x0, 0, \
+        li a0, 0; \
+        c.beqz a0, 1f; \
+        c.j 2f; \
+      1:c.j 1f; \
+      2:j fail; \
+      1:)
+
+  RVC_TEST_CASE (32, x0, 0, \
+        li a0, 1; \
+        c.bnez a0, 1f; \
+        c.j 2f; \
+      1:c.j 1f; \
+      2:j fail; \
+      1:)
+
+  RVC_TEST_CASE (33, x0, 0, \
+        li a0, 1; \
+        c.beqz a0, 1f; \
+        c.j 2f; \
+      1:c.j fail; \
+      2:)
+
+  RVC_TEST_CASE (34, x0, 0, \
+        li a0, 0; \
+        c.bnez a0, 1f; \
+        c.j 2f; \
+      1:c.j fail; \
+      2:)
+
+  RVC_TEST_CASE (35, ra, 0, \
+        la t0, 1f; \
+        li ra, 0; \
+        c.jr t0; \
+        c.j 2f; \
+      1:c.j 1f; \
+      2:j fail; \
+      1:)
+
+  RVC_TEST_CASE (36, ra, -2, \
+        la t0, 1f; \
+        li ra, 0; \
+        c.jalr t0; \
+        c.j 2f; \
+      1:c.j 1f; \
+      2:j fail; \
+      1:sub ra, ra, t0)
+
+#if __riscv_xlen == 32
+  RVC_TEST_CASE (37, ra, -2, \
+        la t0, 1f; \
+        li ra, 0; \
+        c.jal 1f; \
+        c.j 2f; \
+      1:c.j 1f; \
+      2:j fail; \
+      1:sub ra, ra, t0)
+#endif
+
+  la sp, data
+  RVC_TEST_CASE (40, a2, 0xfffffffffedcba99, c.lwsp a0, 12(sp); addi a0, a0, 1; c.swsp a0, 12(sp); c.lwsp a2, 12(sp))
+#if __riscv_xlen == 64
+  RVC_TEST_CASE (41, a2, 0xfedcba9976543211, c.ldsp a0, 8(sp); addi a0, a0, 1; c.sdsp a0, 8(sp); c.ldsp a2, 8(sp))
+#endif
+
+  RVC_TEST_CASE (42, t0, 0x246, li a0, 0x123; c.mv t0, a0; c.add t0, a0)
+
+  .option pop
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/Makefrag
new file mode 100644
index 0000000..7828481
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/Makefrag
@@ -0,0 +1,13 @@
+#=======================================================================
+# Makefrag for rv64ud tests
+#-----------------------------------------------------------------------
+
+rv64ud_sc_tests = \
+	fadd fdiv fclass fcmp fcvt fcvt_w fmadd fmin \
+	ldst move structural recoding \
+
+rv64ud_p_tests = $(addprefix rv64ud-p-, $(rv64ud_sc_tests))
+rv64ud_v_tests = $(addprefix rv64ud-v-, $(rv64ud_sc_tests))
+rv64ud_ps_tests = $(addprefix rv64ud-ps-, $(rv64ud_sc_tests))
+
+spike_tests += $(rv64ud_p_tests) $(rv64ud_v_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fadd.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fadd.S
new file mode 100644
index 0000000..51ca82d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fadd.S
@@ -0,0 +1,50 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fadd.S
+#-----------------------------------------------------------------------------
+#
+# Test f{add|sub|mul}.d instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+#if __riscv_xlen == 32
+    # Replace the function with the 32-bit variant defined in test_macros.h
+    #undef TEST_FP_OP2_D
+    #define TEST_FP_OP2_D TEST_FP_OP2_D32
+#endif
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_OP2_D( 2,  fadd.d, 0,                3.5,        2.5,        1.0 );
+  TEST_FP_OP2_D( 3,  fadd.d, 1,              -1234,    -1235.1,        1.1 );
+  TEST_FP_OP2_D( 4,  fadd.d, 1,         3.14159266, 3.14159265, 0.00000001 );
+
+  TEST_FP_OP2_D( 5,  fsub.d, 0,                1.5,        2.5,        1.0 );
+  TEST_FP_OP2_D( 6,  fsub.d, 1,              -1234,    -1235.1,       -1.1 );
+  TEST_FP_OP2_D( 7,  fsub.d, 1, 3.1415926400000001, 3.14159265, 0.00000001 );
+
+  TEST_FP_OP2_D( 8,  fmul.d, 0,                2.5,        2.5,        1.0 );
+  TEST_FP_OP2_D( 9,  fmul.d, 1,            1358.61,    -1235.1,       -1.1 );
+  TEST_FP_OP2_D(10,  fmul.d, 1,      3.14159265e-8, 3.14159265, 0.00000001 );
+
+  # Is the canonical NaN generated for Inf - Inf?
+  TEST_FP_OP2_D(11,  fsub.d, 0x10, qNaN, Inf, Inf);
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fclass.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fclass.S
new file mode 100644
index 0000000..04a8947
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fclass.S
@@ -0,0 +1,46 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fclass.S
+#-----------------------------------------------------------------------------
+#
+# Test fclass.d instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+#if __riscv_xlen == 32
+    # Replace the function with the 32-bit variant defined in test_macros.h
+    #undef TEST_FCLASS_D
+    #define TEST_FCLASS_D TEST_FCLASS_D32
+#endif
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FCLASS_D( 2, 1 << 0, 0xfff0000000000000 )
+  TEST_FCLASS_D( 3, 1 << 1, 0xbff0000000000000 )
+  TEST_FCLASS_D( 4, 1 << 2, 0x800fffffffffffff )
+  TEST_FCLASS_D( 5, 1 << 3, 0x8000000000000000 )
+  TEST_FCLASS_D( 6, 1 << 4, 0x0000000000000000 )
+  TEST_FCLASS_D( 7, 1 << 5, 0x000fffffffffffff )
+  TEST_FCLASS_D( 8, 1 << 6, 0x3ff0000000000000 )
+  TEST_FCLASS_D( 9, 1 << 7, 0x7ff0000000000000 )
+  TEST_FCLASS_D(10, 1 << 8, 0x7ff0000000000001 )
+  TEST_FCLASS_D(11, 1 << 9, 0x7ff8000000000000 )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fcmp.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fcmp.S
new file mode 100644
index 0000000..7727a28
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fcmp.S
@@ -0,0 +1,56 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fcmp.S
+#-----------------------------------------------------------------------------
+#
+# Test f{eq|lt|le}.d instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+#if __riscv_xlen == 32
+    # Replace the function with the 32-bit variant defined in test_macros.h
+    #undef TEST_FP_CMP_OP_D
+    #define TEST_FP_CMP_OP_D TEST_FP_CMP_OP_D32
+#endif
+
+  TEST_FP_CMP_OP_D( 2, feq.d, 0x00, 1, -1.36, -1.36)
+  TEST_FP_CMP_OP_D( 3, fle.d, 0x00, 1, -1.36, -1.36)
+  TEST_FP_CMP_OP_D( 4, flt.d, 0x00, 0, -1.36, -1.36)
+
+  TEST_FP_CMP_OP_D( 5, feq.d, 0x00, 0, -1.37, -1.36)
+  TEST_FP_CMP_OP_D( 6, fle.d, 0x00, 1, -1.37, -1.36)
+  TEST_FP_CMP_OP_D( 7, flt.d, 0x00, 1, -1.37, -1.36)
+
+  # Only sNaN should signal invalid for feq.
+  TEST_FP_CMP_OP_D( 8, feq.d, 0x00, 0, NaN, 0)
+  TEST_FP_CMP_OP_D( 9, feq.d, 0x00, 0, NaN, NaN)
+  TEST_FP_CMP_OP_D(10, feq.d, 0x10, 0, sNaN, 0)
+
+  # qNaN should signal invalid for fle/flt.
+  TEST_FP_CMP_OP_D(11, flt.d, 0x10, 0, NaN, 0)
+  TEST_FP_CMP_OP_D(12, flt.d, 0x10, 0, NaN, NaN)
+  TEST_FP_CMP_OP_D(13, flt.d, 0x10, 0, sNaN, 0)
+  TEST_FP_CMP_OP_D(14, fle.d, 0x10, 0, NaN, 0)
+  TEST_FP_CMP_OP_D(15, fle.d, 0x10, 0, NaN, NaN)
+  TEST_FP_CMP_OP_D(16, fle.d, 0x10, 0, sNaN, 0)
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fcvt.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fcvt.S
new file mode 100644
index 0000000..98916b1
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fcvt.S
@@ -0,0 +1,79 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fcvt.S
+#-----------------------------------------------------------------------------
+#
+# Test fcvt.d.{wu|w|lu|l}, fcvt.s.d, and fcvt.d.s instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+#if __riscv_xlen == 32
+    # Replace the function with the 32-bit variant defined in test_macros.h
+    #undef TEST_INT_FP_OP_D
+    #define TEST_INT_FP_OP_D TEST_INT_FP_OP_D32
+
+    #undef TEST_FCVT_S_D
+    #define TEST_FCVT_S_D TEST_FCVT_S_D32
+#endif
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_INT_FP_OP_D(2,  fcvt.d.w,                   2.0,  2);
+  TEST_INT_FP_OP_D(3,  fcvt.d.w,                  -2.0, -2);
+
+  TEST_INT_FP_OP_D(4, fcvt.d.wu,                   2.0,  2);
+  TEST_INT_FP_OP_D(5, fcvt.d.wu,            4294967294, -2);
+
+#if __riscv_xlen >= 64
+  TEST_INT_FP_OP_D(6,  fcvt.d.l,                   2.0,  2);
+  TEST_INT_FP_OP_D(7,  fcvt.d.l,                  -2.0, -2);
+
+  TEST_INT_FP_OP_D(8, fcvt.d.lu,                   2.0,  2);
+  TEST_INT_FP_OP_D(9, fcvt.d.lu, 1.8446744073709552e19, -2);
+#endif
+
+  TEST_FCVT_S_D(10, -1.5, -1.5)
+  TEST_FCVT_D_S(11, -1.5, -1.5)
+
+#if __riscv_xlen >= 64
+  TEST_CASE(12, a0, 0x7ff8000000000000,
+    la a1, test_data_22;
+    ld a2, 0(a1);
+    fmv.d.x f2, a2;
+    fcvt.s.d f2, f2;
+    fcvt.d.s f2, f2;
+    fmv.x.d a0, f2;
+  )
+#else
+  TEST_CASE_D32(12, a0, a1, 0x7ff8000000000000,
+    la a1, test_data_22;
+    fld f2, 0(a1);
+    fcvt.s.d f2, f2;
+    fcvt.d.s f2, f2;
+    fsd f2, 0(a1);
+    lw a0, 0(a1);
+    lw a1, 4(a1)
+  )
+#endif
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+test_data_22:
+  .dword 0x7ffcffffffff8004
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fcvt_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fcvt_w.S
new file mode 100644
index 0000000..56cc29d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fcvt_w.S
@@ -0,0 +1,114 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fcvt_w.S
+#-----------------------------------------------------------------------------
+#
+# Test fcvt{wu|w|lu|l}.d instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_INT_OP_D( 2,  fcvt.w.d, 0x01,         -1, -1.1, rtz);
+  TEST_FP_INT_OP_D( 3,  fcvt.w.d, 0x00,         -1, -1.0, rtz);
+  TEST_FP_INT_OP_D( 4,  fcvt.w.d, 0x01,          0, -0.9, rtz);
+  TEST_FP_INT_OP_D( 5,  fcvt.w.d, 0x01,          0,  0.9, rtz);
+  TEST_FP_INT_OP_D( 6,  fcvt.w.d, 0x00,          1,  1.0, rtz);
+  TEST_FP_INT_OP_D( 7,  fcvt.w.d, 0x01,          1,  1.1, rtz);
+  TEST_FP_INT_OP_D( 8,  fcvt.w.d, 0x10,     -1<<31, -3e9, rtz);
+  TEST_FP_INT_OP_D( 9,  fcvt.w.d, 0x10,  (1<<31)-1,  3e9, rtz);
+
+  TEST_FP_INT_OP_D(12, fcvt.wu.d, 0x10,          0, -3.0, rtz);
+  TEST_FP_INT_OP_D(13, fcvt.wu.d, 0x10,          0, -1.0, rtz);
+  TEST_FP_INT_OP_D(14, fcvt.wu.d, 0x01,          0, -0.9, rtz);
+  TEST_FP_INT_OP_D(15, fcvt.wu.d, 0x01,          0,  0.9, rtz);
+  TEST_FP_INT_OP_D(16, fcvt.wu.d, 0x00,          1,  1.0, rtz);
+  TEST_FP_INT_OP_D(17, fcvt.wu.d, 0x01,          1,  1.1, rtz);
+  TEST_FP_INT_OP_D(18, fcvt.wu.d, 0x10,          0, -3e9, rtz);
+  TEST_FP_INT_OP_D(19, fcvt.wu.d, 0x00, 0xffffffffb2d05e00, 3e9, rtz);
+
+#if __riscv_xlen >= 64
+  TEST_FP_INT_OP_D(22,  fcvt.l.d, 0x01,         -1, -1.1, rtz);
+  TEST_FP_INT_OP_D(23,  fcvt.l.d, 0x00,         -1, -1.0, rtz);
+  TEST_FP_INT_OP_D(24,  fcvt.l.d, 0x01,          0, -0.9, rtz);
+  TEST_FP_INT_OP_D(25,  fcvt.l.d, 0x01,          0,  0.9, rtz);
+  TEST_FP_INT_OP_D(26,  fcvt.l.d, 0x00,          1,  1.0, rtz);
+  TEST_FP_INT_OP_D(27,  fcvt.l.d, 0x01,          1,  1.1, rtz);
+  TEST_FP_INT_OP_D(28,  fcvt.l.d, 0x00,-3000000000, -3e9, rtz);
+  TEST_FP_INT_OP_D(29,  fcvt.l.d, 0x00, 3000000000,  3e9, rtz);
+  TEST_FP_INT_OP_D(20,  fcvt.l.d, 0x10,     -1<<63,-3e19, rtz);
+  TEST_FP_INT_OP_D(21,  fcvt.l.d, 0x10,  (1<<63)-1, 3e19, rtz);
+
+  TEST_FP_INT_OP_D(32, fcvt.lu.d, 0x10,          0, -3.0, rtz);
+  TEST_FP_INT_OP_D(33, fcvt.lu.d, 0x10,          0, -1.0, rtz);
+  TEST_FP_INT_OP_D(34, fcvt.lu.d, 0x01,          0, -0.9, rtz);
+  TEST_FP_INT_OP_D(35, fcvt.lu.d, 0x01,          0,  0.9, rtz);
+  TEST_FP_INT_OP_D(36, fcvt.lu.d, 0x00,          1,  1.0, rtz);
+  TEST_FP_INT_OP_D(37, fcvt.lu.d, 0x01,          1,  1.1, rtz);
+  TEST_FP_INT_OP_D(38, fcvt.lu.d, 0x10,          0, -3e9, rtz);
+  TEST_FP_INT_OP_D(39, fcvt.lu.d, 0x00, 3000000000,  3e9, rtz);
+#endif
+
+  # test negative NaN, negative infinity conversion
+  TEST_CASE(42, x1, 0x000000007fffffff, la x1, tdat_d; fld f1,  0(x1); fcvt.w.d x1, f1)
+#if __riscv_xlen >= 64
+  TEST_CASE(43, x1, 0x7fffffffffffffff, la x1, tdat_d; fld f1,  0(x1); fcvt.l.d x1, f1)
+#endif
+  TEST_CASE(44, x1, 0xffffffff80000000, la x1, tdat_d; fld f1, 16(x1); fcvt.w.d x1, f1)
+#if __riscv_xlen >= 64
+  TEST_CASE(45, x1, 0x8000000000000000, la x1, tdat_d; fld f1, 16(x1); fcvt.l.d x1, f1)
+#endif
+
+  # test positive NaN, positive infinity conversion
+  TEST_CASE(52, x1, 0x000000007fffffff, la x1, tdat_d; fld f1,  8(x1); fcvt.w.d x1, f1)
+#if __riscv_xlen >= 64
+  TEST_CASE(53, x1, 0x7fffffffffffffff, la x1, tdat_d; fld f1,  8(x1); fcvt.l.d x1, f1)
+#endif
+  TEST_CASE(54, x1, 0x000000007fffffff, la x1, tdat_d; fld f1, 24(x1); fcvt.w.d x1, f1)
+#if __riscv_xlen >= 64
+  TEST_CASE(55, x1, 0x7fffffffffffffff, la x1, tdat_d; fld f1, 24(x1); fcvt.l.d x1, f1)
+#endif
+
+  # test NaN, infinity conversions to unsigned integer
+  TEST_CASE(62, x1, 0xffffffffffffffff, la x1, tdat_d; fld f1,  0(x1); fcvt.wu.d x1, f1)
+  TEST_CASE(63, x1, 0xffffffffffffffff, la x1, tdat_d; fld f1,  8(x1); fcvt.wu.d x1, f1)
+  TEST_CASE(64, x1,                  0, la x1, tdat_d; fld f1, 16(x1); fcvt.wu.d x1, f1)
+  TEST_CASE(65, x1, 0xffffffffffffffff, la x1, tdat_d; fld f1, 24(x1); fcvt.wu.d x1, f1)
+#if __riscv_xlen >= 64
+  TEST_CASE(66, x1, 0xffffffffffffffff, la x1, tdat_d; fld f1,  0(x1); fcvt.lu.d x1, f1)
+  TEST_CASE(67, x1, 0xffffffffffffffff, la x1, tdat_d; fld f1,  8(x1); fcvt.lu.d x1, f1)
+  TEST_CASE(68, x1,                  0, la x1, tdat_d; fld f1, 16(x1); fcvt.lu.d x1, f1)
+  TEST_CASE(69, x1, 0xffffffffffffffff, la x1, tdat_d; fld f1, 24(x1); fcvt.lu.d x1, f1)
+#endif
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+# -NaN, NaN, -inf, +inf
+tdat:
+.word 0xffffffff
+.word 0x7fffffff
+.word 0xff800000
+.word 0x7f800000
+
+tdat_d:
+.dword 0xffffffffffffffff
+.dword 0x7fffffffffffffff
+.dword 0xfff0000000000000
+.dword 0x7ff0000000000000
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fdiv.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fdiv.S
new file mode 100644
index 0000000..f985fa1
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fdiv.S
@@ -0,0 +1,54 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fdiv.S
+#-----------------------------------------------------------------------------
+#
+# Test f{div|sqrt}.d instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+#if __riscv_xlen == 32
+    # Replace the functions with the 32-bit variants defined in test_macros.h
+    #undef TEST_FP_OP2_D
+    #define TEST_FP_OP2_D TEST_FP_OP2_D32
+
+    #undef TEST_FP_OP1_D
+    #define TEST_FP_OP1_D TEST_FP_OP1_D32
+
+    #undef TEST_FP_OP1_D_DWORD_RESULT
+    #define TEST_FP_OP1_D_DWORD_RESULT TEST_FP_OP1_D32_DWORD_RESULT
+#endif
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_OP2_D( 2,  fdiv.d, 1, 1.1557273520668288, 3.14159265, 2.71828182 );
+  TEST_FP_OP2_D( 3,  fdiv.d, 1,-0.9991093838555584,      -1234,     1235.1 );
+  TEST_FP_OP2_D( 4,  fdiv.d, 0,         3.14159265, 3.14159265,        1.0 );
+
+  TEST_FP_OP1_D( 5,  fsqrt.d, 1, 1.7724538498928541, 3.14159265 );
+  TEST_FP_OP1_D( 6,  fsqrt.d, 0,                100,      10000 );
+
+  TEST_FP_OP1_D_DWORD_RESULT(16,  fsqrt.d, 0x10,      0x7FF8000000000000,      -1.0 );
+
+  TEST_FP_OP1_D( 7,  fsqrt.d, 1, 13.076696830622021, 171.0);
+
+  TEST_FP_OP1_D( 8,  fsqrt.d, 1,0.00040099251863345283320230749702, 1.60795e-7);
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fmadd.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fmadd.S
new file mode 100644
index 0000000..1e3ba66
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fmadd.S
@@ -0,0 +1,51 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fmadd.S
+#-----------------------------------------------------------------------------
+#
+# Test f[n]m{add|sub}.s and f[n]m{add|sub}.d instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+#if __riscv_xlen == 32
+    # Replace the function with the 32-bit variant defined in test_macros.h
+    #undef TEST_FP_OP3_D
+    #define TEST_FP_OP3_D TEST_FP_OP3_D32
+#endif
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_OP3_D( 2,  fmadd.d, 0,                 3.5,  1.0,        2.5,        1.0 );
+  TEST_FP_OP3_D( 3,  fmadd.d, 1,  1236.1999999999999, -1.0,    -1235.1,        1.1 );
+  TEST_FP_OP3_D( 4,  fmadd.d, 0,               -12.0,  2.0,       -5.0,       -2.0 );
+
+  TEST_FP_OP3_D( 5, fnmadd.d, 0,                -3.5,  1.0,        2.5,        1.0 );
+  TEST_FP_OP3_D( 6, fnmadd.d, 1, -1236.1999999999999, -1.0,    -1235.1,        1.1 );
+  TEST_FP_OP3_D( 7, fnmadd.d, 0,                12.0,  2.0,       -5.0,       -2.0 );
+
+  TEST_FP_OP3_D( 8,  fmsub.d, 0,                 1.5,  1.0,        2.5,        1.0 );
+  TEST_FP_OP3_D( 9,  fmsub.d, 1,                1234, -1.0,    -1235.1,        1.1 );
+  TEST_FP_OP3_D(10,  fmsub.d, 0,                -8.0,  2.0,       -5.0,       -2.0 );
+
+  TEST_FP_OP3_D(11, fnmsub.d, 0,                -1.5,  1.0,        2.5,        1.0 );
+  TEST_FP_OP3_D(12, fnmsub.d, 1,               -1234, -1.0,    -1235.1,        1.1 );
+  TEST_FP_OP3_D(13, fnmsub.d, 0,                 8.0,  2.0,       -5.0,       -2.0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fmin.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fmin.S
new file mode 100644
index 0000000..10ff8e6
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/fmin.S
@@ -0,0 +1,60 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fmin.S
+#-----------------------------------------------------------------------------
+#
+# Test f{min|max}.d instructinos.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+#if __riscv_xlen == 32
+    # Replace the function with the 32-bit variant defined in test_macros.h
+    #undef TEST_FP_OP2_D
+    #define TEST_FP_OP2_D TEST_FP_OP2_D32
+#endif
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_OP2_D( 2,  fmin.d, 0,        1.0,        2.5,        1.0 );
+  TEST_FP_OP2_D( 3,  fmin.d, 0,    -1235.1,    -1235.1,        1.1 );
+  TEST_FP_OP2_D( 4,  fmin.d, 0,    -1235.1,        1.1,    -1235.1 );
+  TEST_FP_OP2_D( 5,  fmin.d, 0,    -1235.1,        NaN,    -1235.1 );
+  TEST_FP_OP2_D( 6,  fmin.d, 0, 0.00000001, 3.14159265, 0.00000001 );
+  TEST_FP_OP2_D( 7,  fmin.d, 0,       -2.0,       -1.0,       -2.0 );
+
+  TEST_FP_OP2_D(12,  fmax.d, 0,        2.5,        2.5,        1.0 );
+  TEST_FP_OP2_D(13,  fmax.d, 0,        1.1,    -1235.1,        1.1 );
+  TEST_FP_OP2_D(14,  fmax.d, 0,        1.1,        1.1,    -1235.1 );
+  TEST_FP_OP2_D(15,  fmax.d, 0,    -1235.1,        NaN,    -1235.1 );
+  TEST_FP_OP2_D(16,  fmax.d, 0, 3.14159265, 3.14159265, 0.00000001 );
+  TEST_FP_OP2_D(17,  fmax.d, 0,       -1.0,       -1.0,       -2.0 );
+
+  # FMIN(sNaN, x) = x
+  TEST_FP_OP2_D(20,  fmax.d, 0x10, 1.0, sNaN, 1.0);
+  # FMIN(qNaN, qNaN) = canonical NaN
+  TEST_FP_OP2_D(21,  fmax.d, 0x00, qNaN, NaN, NaN);
+
+  # -0.0 < +0.0
+  TEST_FP_OP2_D(30,  fmin.d, 0,       -0.0,       -0.0,        0.0 );
+  TEST_FP_OP2_D(31,  fmin.d, 0,       -0.0,        0.0,       -0.0 );
+  TEST_FP_OP2_D(32,  fmax.d, 0,        0.0,       -0.0,        0.0 );
+  TEST_FP_OP2_D(33,  fmax.d, 0,        0.0,        0.0,       -0.0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/ldst.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/ldst.S
new file mode 100644
index 0000000..9629341
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/ldst.S
@@ -0,0 +1,42 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# ldst.S
+#-----------------------------------------------------------------------------
+#
+# This test verifies that flw, fld, fsw, and fsd work properly.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  la s0, tdat
+  TEST_CASE(2, a0, 0x40000000bf800000, fld f2, 0(s0); fsd f2, 16(s0); ld a0, 16(s0))
+  TEST_CASE(3, a0, 0x40000000bf800000, fld f2, 0(s0); fsw f2, 16(s0); ld a0, 16(s0))
+  TEST_CASE(4, a0, 0x40000000bf800000, flw f2, 0(s0); fsw f2, 16(s0); ld a0, 16(s0))
+  TEST_CASE(5, a0, 0xc080000040400000, fld f2, 8(s0); fsd f2, 16(s0); ld a0, 16(s0))
+  TEST_CASE(6, a0, 0xffffffff40400000, flw f2, 8(s0); fsd f2, 16(s0); ld a0, 16(s0))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+.word 0xbf800000
+.word 0x40000000
+.word 0x40400000
+.word 0xc0800000
+.word 0xdeadbeef
+.word 0xcafebabe
+.word 0xabad1dea
+.word 0x1337d00d
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/move.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/move.S
new file mode 100644
index 0000000..8911d95
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/move.S
@@ -0,0 +1,113 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# move.S
+#-----------------------------------------------------------------------------
+#
+# This test verifies that fmv.d.x, fmv.x.d, and fsgnj[x|n].d work properly.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+#TODO: make 32-bit compatible version
+#define TEST_FSGNJD(n, insn, new_sign, rs1_sign, rs2_sign) \
+  TEST_CASE(n, a0, 0x123456789abcdef0 | (-(new_sign) << 63), \
+    li a1, ((rs1_sign) << 63) | 0x123456789abcdef0; \
+    li a2, -(rs2_sign); \
+    fmv.d.x f1, a1; \
+    fmv.d.x f2, a2; \
+    insn f0, f1, f2; \
+    fmv.x.d a0, f0)
+
+  TEST_FSGNJD(10, fsgnj.d, 0, 0, 0)
+  TEST_FSGNJD(11, fsgnj.d, 1, 0, 1)
+  TEST_FSGNJD(12, fsgnj.d, 0, 1, 0)
+  TEST_FSGNJD(13, fsgnj.d, 1, 1, 1)
+
+  TEST_FSGNJD(20, fsgnjn.d, 1, 0, 0)
+  TEST_FSGNJD(21, fsgnjn.d, 0, 0, 1)
+  TEST_FSGNJD(22, fsgnjn.d, 1, 1, 0)
+  TEST_FSGNJD(23, fsgnjn.d, 0, 1, 1)
+
+  TEST_FSGNJD(30, fsgnjx.d, 0, 0, 0)
+  TEST_FSGNJD(31, fsgnjx.d, 1, 0, 1)
+  TEST_FSGNJD(32, fsgnjx.d, 1, 1, 0)
+  TEST_FSGNJD(33, fsgnjx.d, 0, 1, 1)
+
+// Test fsgnj.s in conjunction with double-precision moves
+#define TEST_FSGNJS(n, rd, rs1, rs2) \
+  TEST_CASE(n, a0, (rd) | (-((rd) >> 31) << 32), \
+    li a1, rs1; \
+    li a2, rs2; \
+    fmv.d.x f1, a1; \
+    fmv.d.x f2, a2; \
+    fsgnj.s f0, f1, f2; \
+    fmv.x.s a0, f0); \
+  TEST_CASE(1##n, a0, (rd) | 0xffffffff00000000, \
+    li a1, rs1; \
+    li a2, rs2; \
+    fmv.d.x f1, a1; \
+    fmv.d.x f2, a2; \
+    fsgnj.s f0, f1, f2; \
+    fmv.x.d a0, f0)
+
+  TEST_FSGNJS(40, 0x7fc00000, 0x7ffffffe12345678, 0)
+  TEST_FSGNJS(41, 0x7fc00000, 0xfffffffe12345678, 0)
+  TEST_FSGNJS(42, 0x7fc00000, 0x7fffffff12345678, 0)
+  TEST_FSGNJS(43, 0x12345678, 0xffffffff12345678, 0)
+
+  TEST_FSGNJS(50, 0x7fc00000, 0x7ffffffe12345678, 0x80000000)
+  TEST_FSGNJS(51, 0x7fc00000, 0xfffffffe12345678, 0x80000000)
+  TEST_FSGNJS(52, 0x7fc00000, 0x7fffffff12345678, 0x80000000)
+  TEST_FSGNJS(53, 0x12345678, 0xffffffff12345678, 0x80000000)
+
+  TEST_FSGNJS(60, 0xffc00000, 0x7ffffffe12345678, 0xffffffff80000000)
+  TEST_FSGNJS(61, 0xffc00000, 0xfffffffe12345678, 0xffffffff80000000)
+  TEST_FSGNJS(62, 0x92345678, 0xffffffff12345678, 0xffffffff80000000)
+  TEST_FSGNJS(63, 0x12345678, 0xffffffff12345678, 0x7fffffff80000000)
+
+// Test fsgnj.d in conjunction with single-precision moves
+#define TEST_FSGNJD_SP(n, isnan, rd, rs1, rs2) \
+  TEST_CASE(n, a0, ((rd) & 0xffffffff) | (-(((rd) >> 31) & 1) << 32), \
+    li a1, rs1; \
+    li a2, rs2; \
+    fmv.d.x f1, a1; \
+    fmv.d.x f2, a2; \
+    fsgnj.d f0, f1, f2; \
+    feq.s a0, f0, f0; \
+    addi a0, a0, -!(isnan); \
+    bnez a0, 1f; \
+    fmv.x.s a0, f0; \
+    1:); \
+  TEST_CASE(1##n, a0, rd, \
+    li a1, rs1; \
+    li a2, rs2; \
+    fmv.d.x f1, a1; \
+    fmv.d.x f2, a2; \
+    fsgnj.d f0, f1, f2; \
+    fmv.x.d a0, f0; \
+    1:)
+
+  TEST_FSGNJD_SP(70, 0, 0xffffffff11111111, 0xffffffff11111111, 0xffffffff11111111)
+  TEST_FSGNJD_SP(71, 1, 0x7fffffff11111111, 0xffffffff11111111, 0x7fffffff11111111)
+  TEST_FSGNJD_SP(72, 0, 0xffffffff11111111, 0xffffffff11111111, 0xffffffff91111111)
+  TEST_FSGNJD_SP(73, 0, 0xffffffff11111111, 0xffffffff11111111, 0x8000000000000000)
+  TEST_FSGNJD_SP(74, 0, 0xffffffff11111111, 0x7fffffff11111111, 0xffffffff11111111)
+  TEST_FSGNJD_SP(75, 1, 0x7fffffff11111111, 0x7fffffff11111111, 0x7fffffff11111111)
+  TEST_FSGNJD_SP(76, 0, 0xffffffff11111111, 0x7fffffff11111111, 0xffffffff91111111)
+  TEST_FSGNJD_SP(77, 0, 0xffffffff11111111, 0x7fffffff11111111, 0x8000000000000000)
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/recoding.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/recoding.S
new file mode 100644
index 0000000..69ad665
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/recoding.S
@@ -0,0 +1,67 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# recoding.S
+#-----------------------------------------------------------------------------
+#
+# Test corner cases of John Hauser's microarchitectural recoding scheme.
+# There are twice as many recoded values as IEEE-754 values; some of these
+# extras are redundant (e.g. Inf) and others are illegal (subnormals with
+# too many bits set).
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  # Make sure infinities with different mantissas compare as equal.
+  fld f0, minf, a0
+  fld f1, three, a0
+  fmul.d f1, f1, f0
+  TEST_CASE( 2, a0, 1, feq.d a0, f0, f1)
+  TEST_CASE( 3, a0, 1, fle.d a0, f0, f1)
+  TEST_CASE( 4, a0, 0, flt.d a0, f0, f1)
+
+  # Likewise, but for zeroes.
+  fcvt.d.w f0, x0
+  li a0, 1
+  fcvt.d.w f1, a0
+  fmul.d f1, f1, f0
+  TEST_CASE(5, a0, 1, feq.d a0, f0, f1)
+  TEST_CASE(6, a0, 1, fle.d a0, f0, f1)
+  TEST_CASE(7, a0, 0, flt.d a0, f0, f1)
+
+  # When converting small doubles to single-precision subnormals,
+  # ensure that the extra precision is discarded.
+  flw f0, big, a0
+  fld f1, tiny, a0
+  fcvt.s.d f1, f1
+  fmul.s f0, f0, f1
+  fmv.x.s a0, f0
+  lw a1, small
+  TEST_CASE(10, a0, 0, sub a0, a0, a1)
+
+  # Make sure FSD+FLD correctly saves and restores a single-precision value.
+  flw f0, three, a0
+  fadd.s f1, f0, f0
+  fadd.s f0, f0, f0
+  fsd f0, tiny, a0
+  fld f0, tiny, a0
+  TEST_CASE(20, a0, 1, feq.s a0, f0, f1)
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+minf: .double -Inf
+three: .double 3.0
+big: .float 1221
+small: .float 2.9133121e-37
+tiny: .double 2.3860049081905093e-40
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ud/structural.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/structural.S
new file mode 100644
index 0000000..5ecbb96
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ud/structural.S
@@ -0,0 +1,58 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# structural.S
+#-----------------------------------------------------------------------------
+#
+# This test verifies that the FPU correctly obviates structural hazards on its
+# writeback port (e.g. fadd followed by fsgnj)
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+li x25, 1
+
+li x2, 0x3FF0000000000000
+li x1, 0x3F800000
+
+#define TEST(nops, errcode)     \
+  fmv.d.x  f4, x0    ;\
+  fmv.s.x  f3, x0    ;\
+  fmv.d.x  f2, x2    ;\
+  fmv.s.x  f1, x1    ;\
+  j 1f ;\
+  .align 5        ;\
+1:fmul.d  f4, f2, f2  ;\
+  nops          ;\
+  fsgnj.s f3, f1, f1 ;\
+  fmv.x.d  x4, f4    ;\
+  fmv.x.s  x5, f3    ;\
+  beq     x1, x5, 2f  ;\
+  RVTEST_FAIL ;\
+2:beq     x2, x4, 2f  ;\
+  RVTEST_FAIL; \
+2:fmv.d.x  f2, zero    ;\
+  fmv.s.x  f1, zero    ;\
+
+TEST(;,2)
+TEST(nop,4)
+TEST(nop;nop,6)
+TEST(nop;nop;nop,8)
+TEST(nop;nop;nop;nop,10)
+TEST(nop;nop;nop;nop;nop,12)
+TEST(nop;nop;nop;nop;nop;nop,14)
+
+RVTEST_PASS
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/Makefrag
new file mode 100644
index 0000000..26c63af
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/Makefrag
@@ -0,0 +1,13 @@
+#=======================================================================
+# Makefrag for rv64uf tests
+#-----------------------------------------------------------------------
+
+rv64uf_sc_tests = \
+	fadd fdiv fclass fcmp fcvt fcvt_w fmadd fmin \
+	ldst move recoding \
+
+rv64uf_p_tests = $(addprefix rv64uf-p-, $(rv64uf_sc_tests))
+rv64uf_v_tests = $(addprefix rv64uf-v-, $(rv64uf_sc_tests))
+rv64uf_ps_tests = $(addprefix rv64uf-ps-, $(rv64uf_sc_tests))
+
+spike_tests += $(rv64uf_p_tests) $(rv64uf_v_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fadd.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fadd.S
new file mode 100644
index 0000000..b6259df
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fadd.S
@@ -0,0 +1,44 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fadd.S
+#-----------------------------------------------------------------------------
+#
+# Test f{add|sub|mul}.s instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_OP2_S( 2,  fadd.s, 0,                3.5,        2.5,        1.0 );
+  TEST_FP_OP2_S( 3,  fadd.s, 1,              -1234,    -1235.1,        1.1 );
+  TEST_FP_OP2_S( 4,  fadd.s, 1,         3.14159265, 3.14159265, 0.00000001 );
+
+  TEST_FP_OP2_S( 5,  fsub.s, 0,                1.5,        2.5,        1.0 );
+  TEST_FP_OP2_S( 6,  fsub.s, 1,              -1234,    -1235.1,       -1.1 );
+  TEST_FP_OP2_S( 7,  fsub.s, 1,         3.14159265, 3.14159265, 0.00000001 );
+
+  TEST_FP_OP2_S( 8,  fmul.s, 0,                2.5,        2.5,        1.0 );
+  TEST_FP_OP2_S( 9,  fmul.s, 1,            1358.61,    -1235.1,       -1.1 );
+  TEST_FP_OP2_S(10,  fmul.s, 1,      3.14159265e-8, 3.14159265, 0.00000001 );
+
+  # Is the canonical NaN generated for Inf - Inf?
+  TEST_FP_OP2_S(11,  fsub.s, 0x10, qNaNf, Inf, Inf);
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fclass.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fclass.S
new file mode 100644
index 0000000..9bb86b1
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fclass.S
@@ -0,0 +1,40 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fclass.S
+#-----------------------------------------------------------------------------
+#
+# Test fclass.s instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FCLASS_S( 2, 1 << 0, 0xff800000 )
+  TEST_FCLASS_S( 3, 1 << 1, 0xbf800000 )
+  TEST_FCLASS_S( 4, 1 << 2, 0x807fffff )
+  TEST_FCLASS_S( 5, 1 << 3, 0x80000000 )
+  TEST_FCLASS_S( 6, 1 << 4, 0x00000000 )
+  TEST_FCLASS_S( 7, 1 << 5, 0x007fffff )
+  TEST_FCLASS_S( 8, 1 << 6, 0x3f800000 )
+  TEST_FCLASS_S( 9, 1 << 7, 0x7f800000 )
+  TEST_FCLASS_S(10, 1 << 8, 0x7f800001 )
+  TEST_FCLASS_S(11, 1 << 9, 0x7fc00000 )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fcmp.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fcmp.S
new file mode 100644
index 0000000..2d7fcc2
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fcmp.S
@@ -0,0 +1,50 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fcmp.S
+#-----------------------------------------------------------------------------
+#
+# Test f{eq|lt|le}.s instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_CMP_OP_S( 2, feq.s, 0x00, 1, -1.36, -1.36)
+  TEST_FP_CMP_OP_S( 3, fle.s, 0x00, 1, -1.36, -1.36)
+  TEST_FP_CMP_OP_S( 4, flt.s, 0x00, 0, -1.36, -1.36)
+
+  TEST_FP_CMP_OP_S( 5, feq.s, 0x00, 0, -1.37, -1.36)
+  TEST_FP_CMP_OP_S( 6, fle.s, 0x00, 1, -1.37, -1.36)
+  TEST_FP_CMP_OP_S( 7, flt.s, 0x00, 1, -1.37, -1.36)
+
+  # Only sNaN should signal invalid for feq.
+  TEST_FP_CMP_OP_S( 8, feq.s, 0x00, 0, NaN, 0)
+  TEST_FP_CMP_OP_S( 9, feq.s, 0x00, 0, NaN, NaN)
+  TEST_FP_CMP_OP_S(10, feq.s, 0x10, 0, sNaNf, 0)
+
+  # qNaN should signal invalid for fle/flt.
+  TEST_FP_CMP_OP_S(11, flt.s, 0x10, 0, NaN, 0)
+  TEST_FP_CMP_OP_S(12, flt.s, 0x10, 0, NaN, NaN)
+  TEST_FP_CMP_OP_S(13, flt.s, 0x10, 0, sNaNf, 0)
+  TEST_FP_CMP_OP_S(14, fle.s, 0x10, 0, NaN, 0)
+  TEST_FP_CMP_OP_S(15, fle.s, 0x10, 0, NaN, NaN)
+  TEST_FP_CMP_OP_S(16, fle.s, 0x10, 0, sNaNf, 0)
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fcvt.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fcvt.S
new file mode 100644
index 0000000..a41686e
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fcvt.S
@@ -0,0 +1,43 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fcvt.S
+#-----------------------------------------------------------------------------
+#
+# Test fcvt.s.{wu|w|lu|l}, fcvt.s.d, and fcvt.d.s instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_INT_FP_OP_S( 2,  fcvt.s.w,                   2.0,  2);
+  TEST_INT_FP_OP_S( 3,  fcvt.s.w,                  -2.0, -2);
+
+  TEST_INT_FP_OP_S( 4, fcvt.s.wu,                   2.0,  2);
+  TEST_INT_FP_OP_S( 5, fcvt.s.wu,           4.2949673e9, -2);
+
+#if __riscv_xlen >= 64
+  TEST_INT_FP_OP_S( 6,  fcvt.s.l,                   2.0,  2);
+  TEST_INT_FP_OP_S( 7,  fcvt.s.l,                  -2.0, -2);
+
+  TEST_INT_FP_OP_S( 8, fcvt.s.lu,                   2.0,  2);
+  TEST_INT_FP_OP_S( 9, fcvt.s.lu,          1.8446744e19, -2);
+#endif
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fcvt_w.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fcvt_w.S
new file mode 100644
index 0000000..cad5cba
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fcvt_w.S
@@ -0,0 +1,105 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fcvt_w.S
+#-----------------------------------------------------------------------------
+#
+# Test fcvt{wu|w|lu|l}.s instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_INT_OP_S( 2,  fcvt.w.s, 0x01,         -1, -1.1, rtz);
+  TEST_FP_INT_OP_S( 3,  fcvt.w.s, 0x00,         -1, -1.0, rtz);
+  TEST_FP_INT_OP_S( 4,  fcvt.w.s, 0x01,          0, -0.9, rtz);
+  TEST_FP_INT_OP_S( 5,  fcvt.w.s, 0x01,          0,  0.9, rtz);
+  TEST_FP_INT_OP_S( 6,  fcvt.w.s, 0x00,          1,  1.0, rtz);
+  TEST_FP_INT_OP_S( 7,  fcvt.w.s, 0x01,          1,  1.1, rtz);
+  TEST_FP_INT_OP_S( 8,  fcvt.w.s, 0x10,     -1<<31, -3e9, rtz);
+  TEST_FP_INT_OP_S( 9,  fcvt.w.s, 0x10,  (1<<31)-1,  3e9, rtz);
+
+  TEST_FP_INT_OP_S(12, fcvt.wu.s, 0x10,          0, -3.0, rtz);
+  TEST_FP_INT_OP_S(13, fcvt.wu.s, 0x10,          0, -1.0, rtz);
+  TEST_FP_INT_OP_S(14, fcvt.wu.s, 0x01,          0, -0.9, rtz);
+  TEST_FP_INT_OP_S(15, fcvt.wu.s, 0x01,          0,  0.9, rtz);
+  TEST_FP_INT_OP_S(16, fcvt.wu.s, 0x00,          1,  1.0, rtz);
+  TEST_FP_INT_OP_S(17, fcvt.wu.s, 0x01,          1,  1.1, rtz);
+  TEST_FP_INT_OP_S(18, fcvt.wu.s, 0x10,          0, -3e9, rtz);
+  TEST_FP_INT_OP_S(19, fcvt.wu.s, 0x00, 3000000000,  3e9, rtz);
+
+#if __riscv_xlen >= 64
+  TEST_FP_INT_OP_S(22,  fcvt.l.s, 0x01,         -1, -1.1, rtz);
+  TEST_FP_INT_OP_S(23,  fcvt.l.s, 0x00,         -1, -1.0, rtz);
+  TEST_FP_INT_OP_S(24,  fcvt.l.s, 0x01,          0, -0.9, rtz);
+  TEST_FP_INT_OP_S(25,  fcvt.l.s, 0x01,          0,  0.9, rtz);
+  TEST_FP_INT_OP_S(26,  fcvt.l.s, 0x00,          1,  1.0, rtz);
+  TEST_FP_INT_OP_S(27,  fcvt.l.s, 0x01,          1,  1.1, rtz);
+
+  TEST_FP_INT_OP_S(32, fcvt.lu.s, 0x10,          0, -3.0, rtz);
+  TEST_FP_INT_OP_S(33, fcvt.lu.s, 0x10,          0, -1.0, rtz);
+  TEST_FP_INT_OP_S(34, fcvt.lu.s, 0x01,          0, -0.9, rtz);
+  TEST_FP_INT_OP_S(35, fcvt.lu.s, 0x01,          0,  0.9, rtz);
+  TEST_FP_INT_OP_S(36, fcvt.lu.s, 0x00,          1,  1.0, rtz);
+  TEST_FP_INT_OP_S(37, fcvt.lu.s, 0x01,          1,  1.1, rtz);
+  TEST_FP_INT_OP_S(38, fcvt.lu.s, 0x10,          0, -3e9, rtz);
+#endif
+
+  # test negative NaN, negative infinity conversion
+  TEST_CASE( 42, x1, 0x000000007fffffff, la x1, tdat  ; flw f1,  0(x1); fcvt.w.s x1, f1)
+  TEST_CASE( 44, x1, 0xffffffff80000000, la x1, tdat  ; flw f1,  8(x1); fcvt.w.s x1, f1)
+#if __riscv_xlen >= 64
+  TEST_CASE( 43, x1, 0x7fffffffffffffff, la x1, tdat  ; flw f1,  0(x1); fcvt.l.s x1, f1)
+  TEST_CASE( 45, x1, 0x8000000000000000, la x1, tdat  ; flw f1,  8(x1); fcvt.l.s x1, f1)
+#endif
+
+  # test positive NaN, positive infinity conversion
+  TEST_CASE( 52, x1, 0x000000007fffffff, la x1, tdat  ; flw f1,  4(x1); fcvt.w.s x1, f1)
+  TEST_CASE( 54, x1, 0x000000007fffffff, la x1, tdat  ; flw f1, 12(x1); fcvt.w.s x1, f1)
+#if __riscv_xlen >= 64
+  TEST_CASE( 53, x1, 0x7fffffffffffffff, la x1, tdat  ; flw f1,  4(x1); fcvt.l.s x1, f1)
+  TEST_CASE( 55, x1, 0x7fffffffffffffff, la x1, tdat  ; flw f1, 12(x1); fcvt.l.s x1, f1)
+#endif
+
+  # test NaN, infinity conversions to unsigned integer
+  TEST_CASE( 62, x1, 0xffffffffffffffff, la x1, tdat  ; flw f1,  0(x1); fcvt.wu.s x1, f1)
+  TEST_CASE( 63, x1, 0xffffffffffffffff, la x1, tdat  ; flw f1,  4(x1); fcvt.wu.s x1, f1)
+  TEST_CASE( 64, x1,                  0, la x1, tdat  ; flw f1,  8(x1); fcvt.wu.s x1, f1)
+  TEST_CASE( 65, x1, 0xffffffffffffffff, la x1, tdat  ; flw f1, 12(x1); fcvt.wu.s x1, f1)
+#if __riscv_xlen >= 64
+  TEST_CASE( 66, x1, 0xffffffffffffffff, la x1, tdat  ; flw f1,  0(x1); fcvt.lu.s x1, f1)
+  TEST_CASE( 67, x1, 0xffffffffffffffff, la x1, tdat  ; flw f1,  4(x1); fcvt.lu.s x1, f1)
+  TEST_CASE( 68, x1,                  0, la x1, tdat  ; flw f1,  8(x1); fcvt.lu.s x1, f1)
+  TEST_CASE( 69, x1, 0xffffffffffffffff, la x1, tdat  ; flw f1, 12(x1); fcvt.lu.s x1, f1)
+#endif
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+# -NaN, NaN, -inf, +inf
+tdat:
+.word 0xffffffff
+.word 0x7fffffff
+.word 0xff800000
+.word 0x7f800000
+
+tdat_d:
+.dword 0xffffffffffffffff
+.dword 0x7fffffffffffffff
+.dword 0xfff0000000000000
+.dword 0x7ff0000000000000
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fdiv.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fdiv.S
new file mode 100644
index 0000000..a75a23d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fdiv.S
@@ -0,0 +1,40 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fdiv.S
+#-----------------------------------------------------------------------------
+#
+# Test f{div|sqrt}.s instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_OP2_S(2,  fdiv.s, 1, 1.1557273520668288, 3.14159265, 2.71828182 );
+  TEST_FP_OP2_S(3,  fdiv.s, 1,-0.9991093838555584,      -1234,     1235.1 );
+  TEST_FP_OP2_S(4,  fdiv.s, 0,         3.14159265, 3.14159265,        1.0 );
+
+  TEST_FP_OP1_S(5,  fsqrt.s, 1, 1.7724538498928541, 3.14159265 );
+  TEST_FP_OP1_S(6,  fsqrt.s, 0,                100,      10000 );
+
+  TEST_FP_OP1_S_DWORD_RESULT(7,  fsqrt.s, 0x10, 0x7FC00000, -1.0 );
+
+  TEST_FP_OP1_S(8,  fsqrt.s, 1, 13.076696, 171.0);
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fmadd.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fmadd.S
new file mode 100644
index 0000000..241bead
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fmadd.S
@@ -0,0 +1,45 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fmadd.S
+#-----------------------------------------------------------------------------
+#
+# Test f[n]m{add|sub}.s and f[n]m{add|sub}.d instructions.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_OP3_S( 2,  fmadd.s, 0,                 3.5,  1.0,        2.5,        1.0 );
+  TEST_FP_OP3_S( 3,  fmadd.s, 1,              1236.2, -1.0,    -1235.1,        1.1 );
+  TEST_FP_OP3_S( 4,  fmadd.s, 0,               -12.0,  2.0,       -5.0,       -2.0 );
+
+  TEST_FP_OP3_S( 5, fnmadd.s, 0,                -3.5,  1.0,        2.5,        1.0 );
+  TEST_FP_OP3_S( 6, fnmadd.s, 1,             -1236.2, -1.0,    -1235.1,        1.1 );
+  TEST_FP_OP3_S( 7, fnmadd.s, 0,                12.0,  2.0,       -5.0,       -2.0 );
+
+  TEST_FP_OP3_S( 8,  fmsub.s, 0,                 1.5,  1.0,        2.5,        1.0 );
+  TEST_FP_OP3_S( 9,  fmsub.s, 1,                1234, -1.0,    -1235.1,        1.1 );
+  TEST_FP_OP3_S(10,  fmsub.s, 0,                -8.0,  2.0,       -5.0,       -2.0 );
+
+  TEST_FP_OP3_S(11, fnmsub.s, 0,                -1.5,  1.0,        2.5,        1.0 );
+  TEST_FP_OP3_S(12, fnmsub.s, 1,               -1234, -1.0,    -1235.1,        1.1 );
+  TEST_FP_OP3_S(13, fnmsub.s, 0,                 8.0,  2.0,       -5.0,       -2.0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fmin.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fmin.S
new file mode 100644
index 0000000..8c721aa
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/fmin.S
@@ -0,0 +1,54 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fmin.S
+#-----------------------------------------------------------------------------
+#
+# Test f{min|max}.s instructinos.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_FP_OP2_S( 2,  fmin.s, 0,        1.0,        2.5,        1.0 );
+  TEST_FP_OP2_S( 3,  fmin.s, 0,    -1235.1,    -1235.1,        1.1 );
+  TEST_FP_OP2_S( 4,  fmin.s, 0,    -1235.1,        1.1,    -1235.1 );
+  TEST_FP_OP2_S( 5,  fmin.s, 0,    -1235.1,        NaN,    -1235.1 );
+  TEST_FP_OP2_S( 6,  fmin.s, 0, 0.00000001, 3.14159265, 0.00000001 );
+  TEST_FP_OP2_S( 7,  fmin.s, 0,       -2.0,       -1.0,       -2.0 );
+
+  TEST_FP_OP2_S(12,  fmax.s, 0,        2.5,        2.5,        1.0 );
+  TEST_FP_OP2_S(13,  fmax.s, 0,        1.1,    -1235.1,        1.1 );
+  TEST_FP_OP2_S(14,  fmax.s, 0,        1.1,        1.1,    -1235.1 );
+  TEST_FP_OP2_S(15,  fmax.s, 0,    -1235.1,        NaN,    -1235.1 );
+  TEST_FP_OP2_S(16,  fmax.s, 0, 3.14159265, 3.14159265, 0.00000001 );
+  TEST_FP_OP2_S(17,  fmax.s, 0,       -1.0,       -1.0,       -2.0 );
+
+  # FMIN(sNaN, x) = x
+  TEST_FP_OP2_S(20,  fmax.s, 0x10, 1.0, sNaNf, 1.0);
+  # FMIN(qNaN, qNaN) = canonical NaN
+  TEST_FP_OP2_S(21,  fmax.s, 0x00, qNaNf, NaN, NaN);
+
+  # -0.0 < +0.0
+  TEST_FP_OP2_S(30,  fmin.s, 0,       -0.0,       -0.0,        0.0 );
+  TEST_FP_OP2_S(31,  fmin.s, 0,       -0.0,        0.0,       -0.0 );
+  TEST_FP_OP2_S(32,  fmax.s, 0,        0.0,       -0.0,        0.0 );
+  TEST_FP_OP2_S(33,  fmax.s, 0,        0.0,        0.0,       -0.0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/ldst.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/ldst.S
new file mode 100644
index 0000000..c35dd8d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/ldst.S
@@ -0,0 +1,38 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# ldst.S
+#-----------------------------------------------------------------------------
+#
+# This test verifies that flw, fld, fsw, and fsd work properly.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a0, 0x40000000deadbeef, la a1, tdat; flw f1, 4(a1); fsw f1, 20(a1); ld a0, 16(a1))
+  TEST_CASE(3, a0, 0x1337d00dbf800000, la a1, tdat; flw f1, 0(a1); fsw f1, 24(a1); ld a0, 24(a1))
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+.word 0xbf800000
+.word 0x40000000
+.word 0x40400000
+.word 0xc0800000
+.word 0xdeadbeef
+.word 0xcafebabe
+.word 0xabad1dea
+.word 0x1337d00d
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/move.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/move.S
new file mode 100644
index 0000000..60f7cf3
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/move.S
@@ -0,0 +1,58 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# move.S
+#-----------------------------------------------------------------------------
+#
+# This test verifies that the fmv.s.x, fmv.x.s, and fsgnj[x|n].d instructions
+# and the fcsr work properly.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a1, 1, csrwi fcsr, 1; li a0, 0x1234; fssr a1, a0)
+  TEST_CASE(3, a0, 0x34, frsr a0)
+  TEST_CASE(4, a0, 0x14, frflags a0)
+  TEST_CASE(5, a0, 0x01, csrrwi a0, frm, 2)
+  TEST_CASE(6, a0, 0x54, frsr a0)
+  TEST_CASE(7, a0, 0x14, csrrci a0, fflags, 4)
+  TEST_CASE(8, a0, 0x50, frsr a0)
+
+#define TEST_FSGNJS(n, insn, new_sign, rs1_sign, rs2_sign) \
+  TEST_CASE(n, a0, 0x12345678 | (-(new_sign) << 31), \
+    li a1, ((rs1_sign) << 31) | 0x12345678; \
+    li a2, -(rs2_sign); \
+    fmv.s.x f1, a1; \
+    fmv.s.x f2, a2; \
+    insn f0, f1, f2; \
+    fmv.x.s a0, f0)
+
+  TEST_FSGNJS(10, fsgnj.s, 0, 0, 0)
+  TEST_FSGNJS(11, fsgnj.s, 1, 0, 1)
+  TEST_FSGNJS(12, fsgnj.s, 0, 1, 0)
+  TEST_FSGNJS(13, fsgnj.s, 1, 1, 1)
+
+  TEST_FSGNJS(20, fsgnjn.s, 1, 0, 0)
+  TEST_FSGNJS(21, fsgnjn.s, 0, 0, 1)
+  TEST_FSGNJS(22, fsgnjn.s, 1, 1, 0)
+  TEST_FSGNJS(23, fsgnjn.s, 0, 1, 1)
+
+  TEST_FSGNJS(30, fsgnjx.s, 0, 0, 0)
+  TEST_FSGNJS(31, fsgnjx.s, 1, 0, 1)
+  TEST_FSGNJS(32, fsgnjx.s, 1, 1, 0)
+  TEST_FSGNJS(33, fsgnjx.s, 0, 1, 1)
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64uf/recoding.S b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/recoding.S
new file mode 100644
index 0000000..802be66
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64uf/recoding.S
@@ -0,0 +1,46 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# recoding.S
+#-----------------------------------------------------------------------------
+#
+# Test corner cases of John Hauser's microarchitectural recoding scheme.
+# There are twice as many recoded values as IEEE-754 values; some of these
+# extras are redundant (e.g. Inf) and others are illegal (subnormals with
+# too many bits set).
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64UF
+RVTEST_CODE_BEGIN
+
+  # Make sure infinities with different mantissas compare as equal.
+  flw f0, minf, a0
+  flw f1, three, a0
+  fmul.s f1, f1, f0
+  TEST_CASE( 2, a0, 1, feq.s a0, f0, f1)
+  TEST_CASE( 3, a0, 1, fle.s a0, f0, f1)
+  TEST_CASE( 4, a0, 0, flt.s a0, f0, f1)
+
+  # Likewise, but for zeroes.
+  fcvt.s.w f0, x0
+  li a0, 1
+  fcvt.s.w f1, a0
+  fmul.s f1, f1, f0
+  TEST_CASE(5, a0, 1, feq.s a0, f0, f1)
+  TEST_CASE(6, a0, 1, fle.s a0, f0, f1)
+  TEST_CASE(7, a0, 0, flt.s a0, f0, f1)
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+minf: .float -Inf
+three: .float 3.0
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/Makefrag
new file mode 100644
index 0000000..24ba30c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/Makefrag
@@ -0,0 +1,28 @@
+#=======================================================================
+# Makefrag for rv64ui tests
+#-----------------------------------------------------------------------
+
+rv64ui_sc_tests = \
+	add addi addiw addw \
+	and andi \
+	auipc \
+	beq bge bgeu blt bltu bne \
+	simple \
+	fence_i \
+	jal jalr \
+	lb lbu lh lhu lw lwu ld \
+	lui \
+	or ori \
+	sb sh sw sd \
+	sll slli slliw sllw \
+	slt slti sltiu sltu \
+	sra srai sraiw sraw \
+	srl srli srliw srlw \
+	sub subw \
+	xor xori \
+
+rv64ui_p_tests = $(addprefix rv64ui-p-, $(rv64ui_sc_tests))
+rv64ui_v_tests = $(addprefix rv64ui-v-, $(rv64ui_sc_tests))
+rv64ui_ps_tests = $(addprefix rv64ui-ps-, $(rv64ui_sc_tests))
+
+spike_tests += $(rv64ui_p_tests) $(rv64ui_v_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/add.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/add.S
new file mode 100644
index 0000000..0696428
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/add.S
@@ -0,0 +1,85 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# add.S
+#-----------------------------------------------------------------------------
+#
+# Test add instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  add, 0x00000000, 0x00000000, 0x00000000 );
+  TEST_RR_OP( 3,  add, 0x00000002, 0x00000001, 0x00000001 );
+  TEST_RR_OP( 4,  add, 0x0000000a, 0x00000003, 0x00000007 );
+
+  TEST_RR_OP( 5,  add, 0xffffffffffff8000, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 6,  add, 0xffffffff80000000, 0xffffffff80000000, 0x00000000 );
+  TEST_RR_OP( 7,  add, 0xffffffff7fff8000, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 8,  add, 0x0000000000007fff, 0x0000000000000000, 0x0000000000007fff );
+  TEST_RR_OP( 9,  add, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 );
+  TEST_RR_OP( 10, add, 0x0000000080007ffe, 0x000000007fffffff, 0x0000000000007fff );
+
+  TEST_RR_OP( 11, add, 0xffffffff80007fff, 0xffffffff80000000, 0x0000000000007fff );
+  TEST_RR_OP( 12, add, 0x000000007fff7fff, 0x000000007fffffff, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 13, add, 0xffffffffffffffff, 0x0000000000000000, 0xffffffffffffffff );
+  TEST_RR_OP( 14, add, 0x0000000000000000, 0xffffffffffffffff, 0x0000000000000001 );
+  TEST_RR_OP( 15, add, 0xfffffffffffffffe, 0xffffffffffffffff, 0xffffffffffffffff );
+
+  TEST_RR_OP( 16, add, 0x0000000080000000, 0x0000000000000001, 0x000000007fffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 17, add, 24, 13, 11 );
+  TEST_RR_SRC2_EQ_DEST( 18, add, 25, 14, 11 );
+  TEST_RR_SRC12_EQ_DEST( 19, add, 26, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 20, 0, add, 24, 13, 11 );
+  TEST_RR_DEST_BYPASS( 21, 1, add, 25, 14, 11 );
+  TEST_RR_DEST_BYPASS( 22, 2, add, 26, 15, 11 );
+
+  TEST_RR_SRC12_BYPASS( 23, 0, 0, add, 24, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 24, 0, 1, add, 25, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 25, 0, 2, add, 26, 15, 11 );
+  TEST_RR_SRC12_BYPASS( 26, 1, 0, add, 24, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 27, 1, 1, add, 25, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 28, 2, 0, add, 26, 15, 11 );
+
+  TEST_RR_SRC21_BYPASS( 29, 0, 0, add, 24, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 30, 0, 1, add, 25, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 31, 0, 2, add, 26, 15, 11 );
+  TEST_RR_SRC21_BYPASS( 32, 1, 0, add, 24, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 33, 1, 1, add, 25, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 34, 2, 0, add, 26, 15, 11 );
+
+  TEST_RR_ZEROSRC1( 35, add, 15, 15 );
+  TEST_RR_ZEROSRC2( 36, add, 32, 32 );
+  TEST_RR_ZEROSRC12( 37, add, 0 );
+  TEST_RR_ZERODEST( 38, add, 16, 30 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/addi.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/addi.S
new file mode 100644
index 0000000..e6b67ca
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/addi.S
@@ -0,0 +1,71 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# addi.S
+#-----------------------------------------------------------------------------
+#
+# Test addi instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2,  addi, 0x00000000, 0x00000000, 0x000 );
+  TEST_IMM_OP( 3,  addi, 0x00000002, 0x00000001, 0x001 );
+  TEST_IMM_OP( 4,  addi, 0x0000000a, 0x00000003, 0x007 );
+
+  TEST_IMM_OP( 5,  addi, 0xfffffffffffff800, 0x0000000000000000, 0x800 );
+  TEST_IMM_OP( 6,  addi, 0xffffffff80000000, 0xffffffff80000000, 0x000 );
+  TEST_IMM_OP( 7,  addi, 0xffffffff7ffff800, 0xffffffff80000000, 0x800 );
+
+  TEST_IMM_OP( 8,  addi, 0x00000000000007ff, 0x00000000, 0x7ff );
+  TEST_IMM_OP( 9,  addi, 0x000000007fffffff, 0x7fffffff, 0x000 );
+  TEST_IMM_OP( 10, addi, 0x00000000800007fe, 0x7fffffff, 0x7ff );
+
+  TEST_IMM_OP( 11, addi, 0xffffffff800007ff, 0xffffffff80000000, 0x7ff );
+  TEST_IMM_OP( 12, addi, 0x000000007ffff7ff, 0x000000007fffffff, 0x800 );
+
+  TEST_IMM_OP( 13, addi, 0xffffffffffffffff, 0x0000000000000000, 0xfff );
+  TEST_IMM_OP( 14, addi, 0x0000000000000000, 0xffffffffffffffff, 0x001 );
+  TEST_IMM_OP( 15, addi, 0xfffffffffffffffe, 0xffffffffffffffff, 0xfff );
+
+  TEST_IMM_OP( 16, addi, 0x0000000080000000, 0x7fffffff, 0x001 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, addi, 24, 13, 11 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, addi, 24, 13, 11 );
+  TEST_IMM_DEST_BYPASS( 19, 1, addi, 23, 13, 10 );
+  TEST_IMM_DEST_BYPASS( 20, 2, addi, 22, 13,  9 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, addi, 24, 13, 11 );
+  TEST_IMM_SRC1_BYPASS( 22, 1, addi, 23, 13, 10 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, addi, 22, 13,  9 );
+
+  TEST_IMM_ZEROSRC1( 24, addi, 32, 32 );
+  TEST_IMM_ZERODEST( 25, addi, 33, 50 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/addiw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/addiw.S
new file mode 100644
index 0000000..c0f9a61
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/addiw.S
@@ -0,0 +1,71 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# addiw.S
+#-----------------------------------------------------------------------------
+#
+# Test addiw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2,  addiw, 0x00000000, 0x00000000, 0x000 );
+  TEST_IMM_OP( 3,  addiw, 0x00000002, 0x00000001, 0x001 );
+  TEST_IMM_OP( 4,  addiw, 0x0000000a, 0x00000003, 0x007 );
+
+  TEST_IMM_OP( 5,  addiw, 0xfffffffffffff800, 0x0000000000000000, 0x800 );
+  TEST_IMM_OP( 6,  addiw, 0xffffffff80000000, 0xffffffff80000000, 0x000 );
+  TEST_IMM_OP( 7,  addiw, 0x000000007ffff800, 0xffffffff80000000, 0x800 );
+
+  TEST_IMM_OP( 8,  addiw, 0x00000000000007ff, 0x00000000, 0x7ff );
+  TEST_IMM_OP( 9,  addiw, 0x000000007fffffff, 0x7fffffff, 0x000 );
+  TEST_IMM_OP( 10, addiw, 0xffffffff800007fe, 0x7fffffff, 0x7ff );
+
+  TEST_IMM_OP( 11, addiw, 0xffffffff800007ff, 0xffffffff80000000, 0x7ff );
+  TEST_IMM_OP( 12, addiw, 0x000000007ffff7ff, 0x000000007fffffff, 0x800 );
+
+  TEST_IMM_OP( 13, addiw, 0xffffffffffffffff, 0x0000000000000000, 0xfff );
+  TEST_IMM_OP( 14, addiw, 0x0000000000000000, 0xffffffffffffffff, 0x001 );
+  TEST_IMM_OP( 15, addiw, 0xfffffffffffffffe, 0xffffffffffffffff, 0xfff );
+
+  TEST_IMM_OP( 16, addiw, 0xffffffff80000000, 0x7fffffff, 0x001 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, addiw, 24, 13, 11 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, addiw, 24, 13, 11 );
+  TEST_IMM_DEST_BYPASS( 19, 1, addiw, 23, 13, 10 );
+  TEST_IMM_DEST_BYPASS( 20, 2, addiw, 22, 13,  9 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, addiw, 24, 13, 11 );
+  TEST_IMM_SRC1_BYPASS( 22, 1, addiw, 23, 13, 10 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, addiw, 22, 13,  9 );
+
+  TEST_IMM_ZEROSRC1( 24, addiw, 32, 32 );
+  TEST_IMM_ZERODEST( 25, addiw, 33, 50 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/addw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/addw.S
new file mode 100644
index 0000000..ad7fe0b
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/addw.S
@@ -0,0 +1,85 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# addw.S
+#-----------------------------------------------------------------------------
+#
+# Test addw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  addw, 0x00000000, 0x00000000, 0x00000000 );
+  TEST_RR_OP( 3,  addw, 0x00000002, 0x00000001, 0x00000001 );
+  TEST_RR_OP( 4,  addw, 0x0000000a, 0x00000003, 0x00000007 );
+
+  TEST_RR_OP( 5,  addw, 0xffffffffffff8000, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 6,  addw, 0xffffffff80000000, 0xffffffff80000000, 0x00000000 );
+  TEST_RR_OP( 7,  addw, 0x000000007fff8000, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 8,  addw, 0x0000000000007fff, 0x0000000000000000, 0x0000000000007fff );
+  TEST_RR_OP( 9,  addw, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 );
+  TEST_RR_OP( 10, addw, 0xffffffff80007ffe, 0x000000007fffffff, 0x0000000000007fff );
+
+  TEST_RR_OP( 11, addw, 0xffffffff80007fff, 0xffffffff80000000, 0x0000000000007fff );
+  TEST_RR_OP( 12, addw, 0x000000007fff7fff, 0x000000007fffffff, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 13, addw, 0xffffffffffffffff, 0x0000000000000000, 0xffffffffffffffff );
+  TEST_RR_OP( 14, addw, 0x0000000000000000, 0xffffffffffffffff, 0x0000000000000001 );
+  TEST_RR_OP( 15, addw, 0xfffffffffffffffe, 0xffffffffffffffff, 0xffffffffffffffff );
+
+  TEST_RR_OP( 16, addw, 0xffffffff80000000, 0x0000000000000001, 0x000000007fffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 17, addw, 24, 13, 11 );
+  TEST_RR_SRC2_EQ_DEST( 18, addw, 25, 14, 11 );
+  TEST_RR_SRC12_EQ_DEST( 19, addw, 26, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 20, 0, addw, 24, 13, 11 );
+  TEST_RR_DEST_BYPASS( 21, 1, addw, 25, 14, 11 );
+  TEST_RR_DEST_BYPASS( 22, 2, addw, 26, 15, 11 );
+
+  TEST_RR_SRC12_BYPASS( 23, 0, 0, addw, 24, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 24, 0, 1, addw, 25, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 25, 0, 2, addw, 26, 15, 11 );
+  TEST_RR_SRC12_BYPASS( 26, 1, 0, addw, 24, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 27, 1, 1, addw, 25, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 28, 2, 0, addw, 26, 15, 11 );
+
+  TEST_RR_SRC21_BYPASS( 29, 0, 0, addw, 24, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 30, 0, 1, addw, 25, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 31, 0, 2, addw, 26, 15, 11 );
+  TEST_RR_SRC21_BYPASS( 32, 1, 0, addw, 24, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 33, 1, 1, addw, 25, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 34, 2, 0, addw, 26, 15, 11 );
+
+  TEST_RR_ZEROSRC1( 35, addw, 15, 15 );
+  TEST_RR_ZEROSRC2( 36, addw, 32, 32 );
+  TEST_RR_ZEROSRC12( 37, addw, 0 );
+  TEST_RR_ZERODEST( 38, addw, 16, 30 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/and.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/and.S
new file mode 100644
index 0000000..3f63790
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/and.S
@@ -0,0 +1,69 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# and.S
+#-----------------------------------------------------------------------------
+#
+# Test and instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Logical tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_OP( 3, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_OP( 4, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
+  TEST_RR_OP( 5, and, 0xf000f000, 0xf00ff00f, 0xf0f0f0f0 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 6, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC2_EQ_DEST( 7, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC12_EQ_DEST( 8, and, 0xff00ff00, 0xff00ff00 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 9,  0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_DEST_BYPASS( 10, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_DEST_BYPASS( 11, 2, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
+
+  TEST_RR_SRC12_BYPASS( 12, 0, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC12_BYPASS( 13, 0, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC12_BYPASS( 14, 0, 2, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
+  TEST_RR_SRC12_BYPASS( 15, 1, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC12_BYPASS( 16, 1, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC12_BYPASS( 17, 2, 0, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
+
+  TEST_RR_SRC21_BYPASS( 18, 0, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC21_BYPASS( 19, 0, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC21_BYPASS( 20, 0, 2, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
+  TEST_RR_SRC21_BYPASS( 21, 1, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC21_BYPASS( 22, 1, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC21_BYPASS( 23, 2, 0, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
+
+  TEST_RR_ZEROSRC1( 24, and, 0, 0xff00ff00 );
+  TEST_RR_ZEROSRC2( 25, and, 0, 0x00ff00ff );
+  TEST_RR_ZEROSRC12( 26, and, 0 );
+  TEST_RR_ZERODEST( 27, and, 0x11111111, 0x22222222 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/andi.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/andi.S
new file mode 100644
index 0000000..913af9d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/andi.S
@@ -0,0 +1,55 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# andi.S
+#-----------------------------------------------------------------------------
+#
+# Test andi instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Logical tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2, andi, 0xff00ff00, 0xff00ff00, 0xf0f );
+  TEST_IMM_OP( 3, andi, 0x000000f0, 0x0ff00ff0, 0x0f0 );
+  TEST_IMM_OP( 4, andi, 0x0000000f, 0x00ff00ff, 0x70f );
+  TEST_IMM_OP( 5, andi, 0x00000000, 0xf00ff00f, 0x0f0 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 6, andi, 0x00000000, 0xff00ff00, 0x0f0 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 7,  0, andi, 0x00000700, 0x0ff00ff0, 0x70f );
+  TEST_IMM_DEST_BYPASS( 8,  1, andi, 0x000000f0, 0x00ff00ff, 0x0f0 );
+  TEST_IMM_DEST_BYPASS( 9,  2, andi, 0xf00ff00f, 0xf00ff00f, 0xf0f );
+
+  TEST_IMM_SRC1_BYPASS( 10, 0, andi, 0x00000700, 0x0ff00ff0, 0x70f );
+  TEST_IMM_SRC1_BYPASS( 11, 1, andi, 0x000000f0, 0x00ff00ff, 0x0f0 );
+  TEST_IMM_SRC1_BYPASS( 12, 2, andi, 0x0000000f, 0xf00ff00f, 0x70f );
+
+  TEST_IMM_ZEROSRC1( 13, andi, 0, 0x0f0 );
+  TEST_IMM_ZERODEST( 14, andi, 0x00ff00ff, 0x70f );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/auipc.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/auipc.S
new file mode 100644
index 0000000..6fe5962
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/auipc.S
@@ -0,0 +1,39 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# auipc.S
+#-----------------------------------------------------------------------------
+#
+# Test auipc instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  TEST_CASE(2, a0, 10000, \
+    .align 3; \
+    lla a0, 1f + 10000; \
+    jal a1, 1f; \
+    1: sub a0, a0, a1; \
+  )
+
+  TEST_CASE(3, a0, -10000, \
+    .align 3; \
+    lla a0, 1f - 10000; \
+    jal a1, 1f; \
+    1: sub a0, a0, a1; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/beq.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/beq.S
new file mode 100644
index 0000000..436db8c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/beq.S
@@ -0,0 +1,73 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# beq.S
+#-----------------------------------------------------------------------------
+#
+# Test beq instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Branch tests
+  #-------------------------------------------------------------
+
+  # Each test checks both forward and backward branches
+
+  TEST_BR2_OP_TAKEN( 2, beq,  0,  0 );
+  TEST_BR2_OP_TAKEN( 3, beq,  1,  1 );
+  TEST_BR2_OP_TAKEN( 4, beq, -1, -1 );
+
+  TEST_BR2_OP_NOTTAKEN( 5, beq,  0,  1 );
+  TEST_BR2_OP_NOTTAKEN( 6, beq,  1,  0 );
+  TEST_BR2_OP_NOTTAKEN( 7, beq, -1,  1 );
+  TEST_BR2_OP_NOTTAKEN( 8, beq,  1, -1 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_BR2_SRC12_BYPASS( 9,  0, 0, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 10, 0, 1, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 11, 0, 2, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 12, 1, 0, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 13, 1, 1, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 14, 2, 0, beq, 0, -1 );
+
+  TEST_BR2_SRC12_BYPASS( 15, 0, 0, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 16, 0, 1, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 17, 0, 2, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 18, 1, 0, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 19, 1, 1, beq, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 20, 2, 0, beq, 0, -1 );
+
+  #-------------------------------------------------------------
+  # Test delay slot instructions not executed nor bypassed
+  #-------------------------------------------------------------
+
+  TEST_CASE( 21, x1, 3, \
+    li  x1, 1; \
+    beq x0, x0, 1f; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+1:  addi x1, x1, 1; \
+    addi x1, x1, 1; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bge.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bge.S
new file mode 100644
index 0000000..04aebbc
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bge.S
@@ -0,0 +1,76 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# bge.S
+#-----------------------------------------------------------------------------
+#
+# Test bge instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Branch tests
+  #-------------------------------------------------------------
+
+  # Each test checks both forward and backward branches
+
+  TEST_BR2_OP_TAKEN( 2, bge,  0,  0 );
+  TEST_BR2_OP_TAKEN( 3, bge,  1,  1 );
+  TEST_BR2_OP_TAKEN( 4, bge, -1, -1 );
+  TEST_BR2_OP_TAKEN( 5, bge,  1,  0 );
+  TEST_BR2_OP_TAKEN( 6, bge,  1, -1 );
+  TEST_BR2_OP_TAKEN( 7, bge, -1, -2 );
+
+  TEST_BR2_OP_NOTTAKEN(  8, bge,  0,  1 );
+  TEST_BR2_OP_NOTTAKEN(  9, bge, -1,  1 );
+  TEST_BR2_OP_NOTTAKEN( 10, bge, -2, -1 );
+  TEST_BR2_OP_NOTTAKEN( 11, bge, -2,  1 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_BR2_SRC12_BYPASS( 12, 0, 0, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 13, 0, 1, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 14, 0, 2, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 15, 1, 0, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 16, 1, 1, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 17, 2, 0, bge, -1, 0 );
+
+  TEST_BR2_SRC12_BYPASS( 18, 0, 0, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 19, 0, 1, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 20, 0, 2, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 21, 1, 0, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 22, 1, 1, bge, -1, 0 );
+  TEST_BR2_SRC12_BYPASS( 23, 2, 0, bge, -1, 0 );
+
+  #-------------------------------------------------------------
+  # Test delay slot instructions not executed nor bypassed
+  #-------------------------------------------------------------
+
+  TEST_CASE( 24, x1, 3, \
+    li  x1, 1; \
+    bge x1, x0, 1f; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+1:  addi x1, x1, 1; \
+    addi x1, x1, 1; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bgeu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bgeu.S
new file mode 100644
index 0000000..36b6b3a
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bgeu.S
@@ -0,0 +1,76 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# bgeu.S
+#-----------------------------------------------------------------------------
+#
+# Test bgeu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Branch tests
+  #-------------------------------------------------------------
+
+  # Each test checks both forward and backward branches
+
+  TEST_BR2_OP_TAKEN( 2, bgeu, 0x00000000, 0x00000000 );
+  TEST_BR2_OP_TAKEN( 3, bgeu, 0x00000001, 0x00000001 );
+  TEST_BR2_OP_TAKEN( 4, bgeu, 0xffffffff, 0xffffffff );
+  TEST_BR2_OP_TAKEN( 5, bgeu, 0x00000001, 0x00000000 );
+  TEST_BR2_OP_TAKEN( 6, bgeu, 0xffffffff, 0xfffffffe );
+  TEST_BR2_OP_TAKEN( 7, bgeu, 0xffffffff, 0x00000000 );
+
+  TEST_BR2_OP_NOTTAKEN(  8, bgeu, 0x00000000, 0x00000001 );
+  TEST_BR2_OP_NOTTAKEN(  9, bgeu, 0xfffffffe, 0xffffffff );
+  TEST_BR2_OP_NOTTAKEN( 10, bgeu, 0x00000000, 0xffffffff );
+  TEST_BR2_OP_NOTTAKEN( 11, bgeu, 0x7fffffff, 0x80000000 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_BR2_SRC12_BYPASS( 12, 0, 0, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 13, 0, 1, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 14, 0, 2, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 15, 1, 0, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 16, 1, 1, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 17, 2, 0, bgeu, 0xefffffff, 0xf0000000 );
+
+  TEST_BR2_SRC12_BYPASS( 18, 0, 0, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 19, 0, 1, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 20, 0, 2, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 21, 1, 0, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 22, 1, 1, bgeu, 0xefffffff, 0xf0000000 );
+  TEST_BR2_SRC12_BYPASS( 23, 2, 0, bgeu, 0xefffffff, 0xf0000000 );
+
+  #-------------------------------------------------------------
+  # Test delay slot instructions not executed nor bypassed
+  #-------------------------------------------------------------
+
+  TEST_CASE( 24, x1, 3, \
+    li  x1, 1; \
+    bgeu x1, x0, 1f; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+1:  addi x1, x1, 1; \
+    addi x1, x1, 1; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/blt.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/blt.S
new file mode 100644
index 0000000..1c0ca69
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/blt.S
@@ -0,0 +1,73 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# blt.S
+#-----------------------------------------------------------------------------
+#
+# Test blt instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Branch tests
+  #-------------------------------------------------------------
+
+  # Each test checks both forward and backward branches
+
+  TEST_BR2_OP_TAKEN( 2, blt,  0,  1 );
+  TEST_BR2_OP_TAKEN( 3, blt, -1,  1 );
+  TEST_BR2_OP_TAKEN( 4, blt, -2, -1 );
+
+  TEST_BR2_OP_NOTTAKEN( 5, blt,  1,  0 );
+  TEST_BR2_OP_NOTTAKEN( 6, blt,  1, -1 );
+  TEST_BR2_OP_NOTTAKEN( 7, blt, -1, -2 );
+  TEST_BR2_OP_NOTTAKEN( 8, blt,  1, -2 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_BR2_SRC12_BYPASS( 9,  0, 0, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 10, 0, 1, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 11, 0, 2, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 12, 1, 0, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 13, 1, 1, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 14, 2, 0, blt, 0, -1 );
+
+  TEST_BR2_SRC12_BYPASS( 15, 0, 0, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 16, 0, 1, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 17, 0, 2, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 18, 1, 0, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 19, 1, 1, blt, 0, -1 );
+  TEST_BR2_SRC12_BYPASS( 20, 2, 0, blt, 0, -1 );
+
+  #-------------------------------------------------------------
+  # Test delay slot instructions not executed nor bypassed
+  #-------------------------------------------------------------
+
+  TEST_CASE( 21, x1, 3, \
+    li  x1, 1; \
+    blt x0, x1, 1f; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+1:  addi x1, x1, 1; \
+    addi x1, x1, 1; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bltu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bltu.S
new file mode 100644
index 0000000..4e880d6
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bltu.S
@@ -0,0 +1,73 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# bltu.S
+#-----------------------------------------------------------------------------
+#
+# Test bltu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Branch tests
+  #-------------------------------------------------------------
+
+  # Each test checks both forward and backward branches
+
+  TEST_BR2_OP_TAKEN( 2, bltu, 0x00000000, 0x00000001 );
+  TEST_BR2_OP_TAKEN( 3, bltu, 0xfffffffe, 0xffffffff );
+  TEST_BR2_OP_TAKEN( 4, bltu, 0x00000000, 0xffffffff );
+
+  TEST_BR2_OP_NOTTAKEN( 5, bltu, 0x00000001, 0x00000000 );
+  TEST_BR2_OP_NOTTAKEN( 6, bltu, 0xffffffff, 0xfffffffe );
+  TEST_BR2_OP_NOTTAKEN( 7, bltu, 0xffffffff, 0x00000000 );
+  TEST_BR2_OP_NOTTAKEN( 8, bltu, 0x80000000, 0x7fffffff );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_BR2_SRC12_BYPASS( 9,  0, 0, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 10, 0, 1, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 11, 0, 2, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 12, 1, 0, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 13, 1, 1, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 14, 2, 0, bltu, 0xf0000000, 0xefffffff );
+
+  TEST_BR2_SRC12_BYPASS( 15, 0, 0, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 16, 0, 1, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 17, 0, 2, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 18, 1, 0, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 19, 1, 1, bltu, 0xf0000000, 0xefffffff );
+  TEST_BR2_SRC12_BYPASS( 20, 2, 0, bltu, 0xf0000000, 0xefffffff );
+
+  #-------------------------------------------------------------
+  # Test delay slot instructions not executed nor bypassed
+  #-------------------------------------------------------------
+
+  TEST_CASE( 21, x1, 3, \
+    li  x1, 1; \
+    bltu x0, x1, 1f; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+1:  addi x1, x1, 1; \
+    addi x1, x1, 1; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bne.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bne.S
new file mode 100644
index 0000000..3ca4e6c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/bne.S
@@ -0,0 +1,73 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# bne.S
+#-----------------------------------------------------------------------------
+#
+# Test bne instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Branch tests
+  #-------------------------------------------------------------
+
+  # Each test checks both forward and backward branches
+
+  TEST_BR2_OP_TAKEN( 2, bne,  0,  1 );
+  TEST_BR2_OP_TAKEN( 3, bne,  1,  0 );
+  TEST_BR2_OP_TAKEN( 4, bne, -1,  1 );
+  TEST_BR2_OP_TAKEN( 5, bne,  1, -1 );
+
+  TEST_BR2_OP_NOTTAKEN( 6, bne,  0,  0 );
+  TEST_BR2_OP_NOTTAKEN( 7, bne,  1,  1 );
+  TEST_BR2_OP_NOTTAKEN( 8, bne, -1, -1 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_BR2_SRC12_BYPASS( 9,  0, 0, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 10, 0, 1, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 11, 0, 2, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 12, 1, 0, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 13, 1, 1, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 14, 2, 0, bne, 0, 0 );
+
+  TEST_BR2_SRC12_BYPASS( 15, 0, 0, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 16, 0, 1, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 17, 0, 2, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 18, 1, 0, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 19, 1, 1, bne, 0, 0 );
+  TEST_BR2_SRC12_BYPASS( 20, 2, 0, bne, 0, 0 );
+
+  #-------------------------------------------------------------
+  # Test delay slot instructions not executed nor bypassed
+  #-------------------------------------------------------------
+
+  TEST_CASE( 21, x1, 3, \
+    li  x1, 1; \
+    bne x1, x0, 1f; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+    addi x1, x1, 1; \
+1:  addi x1, x1, 1; \
+    addi x1, x1, 1; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/fence_i.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/fence_i.S
new file mode 100644
index 0000000..cd0fe56
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/fence_i.S
@@ -0,0 +1,54 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# fence_i.S
+#-----------------------------------------------------------------------------
+#
+# Test self-modifying code and the fence.i instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+li a3, 111
+lh a0, insn
+lh a1, insn+2
+
+# test I$ hit
+.align 6
+sh a0, 1f, t0
+sh a1, 1f+2, t0
+fence.i
+
+1: addi a3, a3, 222
+TEST_CASE( 2, a3, 444, nop )
+
+# test prefetcher hit
+li a4, 100
+1: addi a4, a4, -1
+bnez a4, 1b
+
+sh a0, 1f, t0
+sh a1, 1f+2, t0
+fence.i
+
+.align 6
+1: addi a3, a3, 555
+TEST_CASE( 3, a3, 777, nop )
+
+TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+insn:
+  addi a3, a3, 333
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/jal.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/jal.S
new file mode 100644
index 0000000..00c65d8
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/jal.S
@@ -0,0 +1,59 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# jal.S
+#-----------------------------------------------------------------------------
+#
+# Test jal instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Test 2: Basic test
+  #-------------------------------------------------------------
+
+test_2:
+  li  TESTNUM, 2
+  li  ra, 0
+
+  jal x4, target_2
+linkaddr_2:
+  nop
+  nop
+
+  j fail
+
+target_2:
+  la  x2, linkaddr_2
+  bne x2, x4, fail
+
+  #-------------------------------------------------------------
+  # Test delay slot instructions not executed nor bypassed
+  #-------------------------------------------------------------
+
+  TEST_CASE( 3, ra, 3, \
+    li  ra, 1; \
+    jal x0, 1f; \
+    addi ra, ra, 1; \
+    addi ra, ra, 1; \
+    addi ra, ra, 1; \
+    addi ra, ra, 1; \
+1:  addi ra, ra, 1; \
+    addi ra, ra, 1; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/jalr.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/jalr.S
new file mode 100644
index 0000000..f27005a
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/jalr.S
@@ -0,0 +1,70 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# jalr.S
+#-----------------------------------------------------------------------------
+#
+# Test jalr instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Test 2: Basic test
+  #-------------------------------------------------------------
+
+test_2:
+  li  TESTNUM, 2
+  li  t0, 0
+  la  t1, target_2
+
+  jalr t0, t1, 0
+linkaddr_2:
+  j fail
+
+target_2:
+  la  t1, linkaddr_2
+  bne t0, t1, fail
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_JALR_SRC1_BYPASS( 4, 0, jalr );
+  TEST_JALR_SRC1_BYPASS( 5, 1, jalr );
+  TEST_JALR_SRC1_BYPASS( 6, 2, jalr );
+
+  #-------------------------------------------------------------
+  # Test delay slot instructions not executed nor bypassed
+  #-------------------------------------------------------------
+
+  .option push
+  .align 2
+  .option norvc
+  TEST_CASE( 7, t0, 4, \
+    li  t0, 1; \
+    la  t1, 1f; \
+    jr  t1, -4; \
+    addi t0, t0, 1; \
+    addi t0, t0, 1; \
+    addi t0, t0, 1; \
+    addi t0, t0, 1; \
+1:  addi t0, t0, 1; \
+    addi t0, t0, 1; \
+  )
+  .option pop
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lb.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lb.S
new file mode 100644
index 0000000..856dfe9
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lb.S
@@ -0,0 +1,92 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# lb.S
+#-----------------------------------------------------------------------------
+#
+# Test lb instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_LD_OP( 2, lb, 0xffffffffffffffff, 0,  tdat );
+  TEST_LD_OP( 3, lb, 0x0000000000000000, 1,  tdat );
+  TEST_LD_OP( 4, lb, 0xfffffffffffffff0, 2,  tdat );
+  TEST_LD_OP( 5, lb, 0x000000000000000f, 3, tdat );
+
+  # Test with negative offset
+
+  TEST_LD_OP( 6, lb, 0xffffffffffffffff, -3, tdat4 );
+  TEST_LD_OP( 7, lb, 0x0000000000000000, -2,  tdat4 );
+  TEST_LD_OP( 8, lb, 0xfffffffffffffff0, -1,  tdat4 );
+  TEST_LD_OP( 9, lb, 0x000000000000000f, 0,   tdat4 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0xffffffffffffffff, \
+    la  x1, tdat; \
+    addi x1, x1, -32; \
+    lb x5, 32(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0x0000000000000000, \
+    la  x1, tdat; \
+    addi x1, x1, -6; \
+    lb x5, 7(x1); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_LD_DEST_BYPASS( 12, 0, lb, 0xfffffffffffffff0, 1, tdat2 );
+  TEST_LD_DEST_BYPASS( 13, 1, lb, 0x000000000000000f, 1, tdat3 );
+  TEST_LD_DEST_BYPASS( 14, 2, lb, 0x0000000000000000, 1, tdat1 );
+
+  TEST_LD_SRC1_BYPASS( 15, 0, lb, 0xfffffffffffffff0, 1, tdat2 );
+  TEST_LD_SRC1_BYPASS( 16, 1, lb, 0x000000000000000f, 1, tdat3 );
+  TEST_LD_SRC1_BYPASS( 17, 2, lb, 0x0000000000000000, 1, tdat1 );
+
+  #-------------------------------------------------------------
+  # Test write-after-write hazard
+  #-------------------------------------------------------------
+
+  TEST_CASE( 18, x2, 2, \
+    la  x5, tdat; \
+    lb  x2, 0(x5); \
+    li  x2, 2; \
+  )
+
+  TEST_CASE( 19, x2, 2, \
+    la  x5, tdat; \
+    lb  x2, 0(x5); \
+    nop; \
+    li  x2, 2; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .byte 0xff
+tdat2:  .byte 0x00
+tdat3:  .byte 0xf0
+tdat4:  .byte 0x0f
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lbu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lbu.S
new file mode 100644
index 0000000..adc3a05
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lbu.S
@@ -0,0 +1,92 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# lbu.S
+#-----------------------------------------------------------------------------
+#
+# Test lbu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_LD_OP( 2, lbu, 0x00000000000000ff, 0,  tdat );
+  TEST_LD_OP( 3, lbu, 0x0000000000000000, 1,  tdat );
+  TEST_LD_OP( 4, lbu, 0x00000000000000f0, 2,  tdat );
+  TEST_LD_OP( 5, lbu, 0x000000000000000f, 3, tdat );
+
+  # Test with negative offset
+
+  TEST_LD_OP( 6, lbu, 0x00000000000000ff, -3, tdat4 );
+  TEST_LD_OP( 7, lbu, 0x0000000000000000, -2,  tdat4 );
+  TEST_LD_OP( 8, lbu, 0x00000000000000f0, -1,  tdat4 );
+  TEST_LD_OP( 9, lbu, 0x000000000000000f, 0,   tdat4 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x00000000000000ff, \
+    la  x1, tdat; \
+    addi x1, x1, -32; \
+    lbu x5, 32(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0x0000000000000000, \
+    la  x1, tdat; \
+    addi x1, x1, -6; \
+    lbu x5, 7(x1); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_LD_DEST_BYPASS( 12, 0, lbu, 0x00000000000000f0, 1, tdat2 );
+  TEST_LD_DEST_BYPASS( 13, 1, lbu, 0x000000000000000f, 1, tdat3 );
+  TEST_LD_DEST_BYPASS( 14, 2, lbu, 0x0000000000000000, 1, tdat1 );
+
+  TEST_LD_SRC1_BYPASS( 15, 0, lbu, 0x00000000000000f0, 1, tdat2 );
+  TEST_LD_SRC1_BYPASS( 16, 1, lbu, 0x000000000000000f, 1, tdat3 );
+  TEST_LD_SRC1_BYPASS( 17, 2, lbu, 0x0000000000000000, 1, tdat1 );
+
+  #-------------------------------------------------------------
+  # Test write-after-write hazard
+  #-------------------------------------------------------------
+
+  TEST_CASE( 18, x2, 2, \
+    la  x5, tdat; \
+    lbu  x2, 0(x5); \
+    li  x2, 2; \
+  )
+
+  TEST_CASE( 19, x2, 2, \
+    la  x5, tdat; \
+    lbu  x2, 0(x5); \
+    nop; \
+    li  x2, 2; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .byte 0xff
+tdat2:  .byte 0x00
+tdat3:  .byte 0xf0
+tdat4:  .byte 0x0f
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/ld.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/ld.S
new file mode 100644
index 0000000..948c34b
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/ld.S
@@ -0,0 +1,92 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# ld.S
+#-----------------------------------------------------------------------------
+#
+# Test ld instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_LD_OP( 2, ld, 0x00ff00ff00ff00ff, 0,  tdat );
+  TEST_LD_OP( 3, ld, 0xff00ff00ff00ff00, 8,  tdat );
+  TEST_LD_OP( 4, ld, 0x0ff00ff00ff00ff0, 16, tdat );
+  TEST_LD_OP( 5, ld, 0xf00ff00ff00ff00f, 24, tdat );
+
+  # Test with negative offset
+
+  TEST_LD_OP( 6, ld, 0x00ff00ff00ff00ff, -24, tdat4 );
+  TEST_LD_OP( 7, ld, 0xff00ff00ff00ff00, -16, tdat4 );
+  TEST_LD_OP( 8, ld, 0x0ff00ff00ff00ff0, -8,  tdat4 );
+  TEST_LD_OP( 9, ld, 0xf00ff00ff00ff00f, 0,   tdat4 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x00ff00ff00ff00ff, \
+    la  x1, tdat; \
+    addi x1, x1, -32; \
+    ld x5, 32(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0xff00ff00ff00ff00, \
+    la  x1, tdat; \
+    addi x1, x1, -3; \
+    ld x5, 11(x1); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_LD_DEST_BYPASS( 12, 0, ld, 0x0ff00ff00ff00ff0, 8, tdat2 );
+  TEST_LD_DEST_BYPASS( 13, 1, ld, 0xf00ff00ff00ff00f, 8, tdat3 );
+  TEST_LD_DEST_BYPASS( 14, 2, ld, 0xff00ff00ff00ff00, 8, tdat1 );
+
+  TEST_LD_SRC1_BYPASS( 15, 0, ld, 0x0ff00ff00ff00ff0, 8, tdat2 );
+  TEST_LD_SRC1_BYPASS( 16, 1, ld, 0xf00ff00ff00ff00f, 8, tdat3 );
+  TEST_LD_SRC1_BYPASS( 17, 2, ld, 0xff00ff00ff00ff00, 8, tdat1 );
+
+  #-------------------------------------------------------------
+  # Test write-after-write hazard
+  #-------------------------------------------------------------
+
+  TEST_CASE( 18, x2, 2, \
+    la  x5, tdat; \
+    ld  x2, 0(x5); \
+    li  x2, 2; \
+  )
+
+  TEST_CASE( 19, x2, 2, \
+    la  x5, tdat; \
+    ld  x2, 0(x5); \
+    nop; \
+    li  x2, 2; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .dword 0x00ff00ff00ff00ff
+tdat2:  .dword 0xff00ff00ff00ff00
+tdat3:  .dword 0x0ff00ff00ff00ff0
+tdat4:  .dword 0xf00ff00ff00ff00f
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lh.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lh.S
new file mode 100644
index 0000000..338ed69
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lh.S
@@ -0,0 +1,92 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# lh.S
+#-----------------------------------------------------------------------------
+#
+# Test lh instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_LD_OP( 2, lh, 0x00000000000000ff, 0,  tdat );
+  TEST_LD_OP( 3, lh, 0xffffffffffffff00, 2,  tdat );
+  TEST_LD_OP( 4, lh, 0x0000000000000ff0, 4,  tdat );
+  TEST_LD_OP( 5, lh, 0xfffffffffffff00f, 6, tdat );
+
+  # Test with negative offset
+
+  TEST_LD_OP( 6, lh, 0x00000000000000ff, -6,  tdat4 );
+  TEST_LD_OP( 7, lh, 0xffffffffffffff00, -4,  tdat4 );
+  TEST_LD_OP( 8, lh, 0x0000000000000ff0, -2,  tdat4 );
+  TEST_LD_OP( 9, lh, 0xfffffffffffff00f,  0, tdat4 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x00000000000000ff, \
+    la  x1, tdat; \
+    addi x1, x1, -32; \
+    lh x5, 32(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0xffffffffffffff00, \
+    la  x1, tdat; \
+    addi x1, x1, -5; \
+    lh x5, 7(x1); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_LD_DEST_BYPASS( 12, 0, lh, 0x0000000000000ff0, 2, tdat2 );
+  TEST_LD_DEST_BYPASS( 13, 1, lh, 0xfffffffffffff00f, 2, tdat3 );
+  TEST_LD_DEST_BYPASS( 14, 2, lh, 0xffffffffffffff00, 2, tdat1 );
+
+  TEST_LD_SRC1_BYPASS( 15, 0, lh, 0x0000000000000ff0, 2, tdat2 );
+  TEST_LD_SRC1_BYPASS( 16, 1, lh, 0xfffffffffffff00f, 2, tdat3 );
+  TEST_LD_SRC1_BYPASS( 17, 2, lh, 0xffffffffffffff00, 2, tdat1 );
+
+  #-------------------------------------------------------------
+  # Test write-after-write hazard
+  #-------------------------------------------------------------
+
+  TEST_CASE( 18, x2, 2, \
+    la  x5, tdat; \
+    lh  x2, 0(x5); \
+    li  x2, 2; \
+  )
+
+  TEST_CASE( 19, x2, 2, \
+    la  x5, tdat; \
+    lh  x2, 0(x5); \
+    nop; \
+    li  x2, 2; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .half 0x00ff
+tdat2:  .half 0xff00
+tdat3:  .half 0x0ff0
+tdat4:  .half 0xf00f
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lhu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lhu.S
new file mode 100644
index 0000000..a4cc49b
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lhu.S
@@ -0,0 +1,92 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# lhu.S
+#-----------------------------------------------------------------------------
+#
+# Test lhu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_LD_OP( 2, lhu, 0x00000000000000ff, 0,  tdat );
+  TEST_LD_OP( 3, lhu, 0x000000000000ff00, 2,  tdat );
+  TEST_LD_OP( 4, lhu, 0x0000000000000ff0, 4,  tdat );
+  TEST_LD_OP( 5, lhu, 0x000000000000f00f, 6, tdat );
+
+  # Test with negative offset
+
+  TEST_LD_OP( 6, lhu, 0x00000000000000ff, -6,  tdat4 );
+  TEST_LD_OP( 7, lhu, 0x000000000000ff00, -4,  tdat4 );
+  TEST_LD_OP( 8, lhu, 0x0000000000000ff0, -2,  tdat4 );
+  TEST_LD_OP( 9, lhu, 0x000000000000f00f,  0, tdat4 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x00000000000000ff, \
+    la  x1, tdat; \
+    addi x1, x1, -32; \
+    lhu x5, 32(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0x000000000000ff00, \
+    la  x1, tdat; \
+    addi x1, x1, -5; \
+    lhu x5, 7(x1); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_LD_DEST_BYPASS( 12, 0, lhu, 0x0000000000000ff0, 2, tdat2 );
+  TEST_LD_DEST_BYPASS( 13, 1, lhu, 0x000000000000f00f, 2, tdat3 );
+  TEST_LD_DEST_BYPASS( 14, 2, lhu, 0x000000000000ff00, 2, tdat1 );
+
+  TEST_LD_SRC1_BYPASS( 15, 0, lhu, 0x0000000000000ff0, 2, tdat2 );
+  TEST_LD_SRC1_BYPASS( 16, 1, lhu, 0x000000000000f00f, 2, tdat3 );
+  TEST_LD_SRC1_BYPASS( 17, 2, lhu, 0x000000000000ff00, 2, tdat1 );
+
+  #-------------------------------------------------------------
+  # Test write-after-write hazard
+  #-------------------------------------------------------------
+
+  TEST_CASE( 18, x2, 2, \
+    la  x5, tdat; \
+    lhu  x2, 0(x5); \
+    li  x2, 2; \
+  )
+
+  TEST_CASE( 19, x2, 2, \
+    la  x5, tdat; \
+    lhu  x2, 0(x5); \
+    nop; \
+    li  x2, 2; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .half 0x00ff
+tdat2:  .half 0xff00
+tdat3:  .half 0x0ff0
+tdat4:  .half 0xf00f
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lui.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lui.S
new file mode 100644
index 0000000..8a4e70c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lui.S
@@ -0,0 +1,36 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# lui.S
+#-----------------------------------------------------------------------------
+#
+# Test lui instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_CASE( 2, x1, 0x0000000000000000, lui x1, 0x00000 );
+  TEST_CASE( 3, x1, 0xfffffffffffff800, lui x1, 0xfffff;sra x1,x1,1);
+  TEST_CASE( 4, x1, 0x00000000000007ff, lui x1, 0x7ffff;sra x1,x1,20);
+  TEST_CASE( 5, x1, 0xfffffffffffff800, lui x1, 0x80000;sra x1,x1,20);
+
+  TEST_CASE( 6, x0, 0, lui x0, 0x80000 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lw.S
new file mode 100644
index 0000000..40a73f1
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lw.S
@@ -0,0 +1,92 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# lw.S
+#-----------------------------------------------------------------------------
+#
+# Test lw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_LD_OP( 2, lw, 0x0000000000ff00ff, 0,  tdat );
+  TEST_LD_OP( 3, lw, 0xffffffffff00ff00, 4,  tdat );
+  TEST_LD_OP( 4, lw, 0x000000000ff00ff0, 8,  tdat );
+  TEST_LD_OP( 5, lw, 0xfffffffff00ff00f, 12, tdat );
+
+  # Test with negative offset
+
+  TEST_LD_OP( 6, lw, 0x0000000000ff00ff, -12, tdat4 );
+  TEST_LD_OP( 7, lw, 0xffffffffff00ff00, -8,  tdat4 );
+  TEST_LD_OP( 8, lw, 0x000000000ff00ff0, -4,  tdat4 );
+  TEST_LD_OP( 9, lw, 0xfffffffff00ff00f, 0,   tdat4 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x0000000000ff00ff, \
+    la  x1, tdat; \
+    addi x1, x1, -32; \
+    lw x5, 32(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0xffffffffff00ff00, \
+    la  x1, tdat; \
+    addi x1, x1, -3; \
+    lw x5, 7(x1); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_LD_DEST_BYPASS( 12, 0, lw, 0x000000000ff00ff0, 4, tdat2 );
+  TEST_LD_DEST_BYPASS( 13, 1, lw, 0xfffffffff00ff00f, 4, tdat3 );
+  TEST_LD_DEST_BYPASS( 14, 2, lw, 0xffffffffff00ff00, 4, tdat1 );
+
+  TEST_LD_SRC1_BYPASS( 15, 0, lw, 0x000000000ff00ff0, 4, tdat2 );
+  TEST_LD_SRC1_BYPASS( 16, 1, lw, 0xfffffffff00ff00f, 4, tdat3 );
+  TEST_LD_SRC1_BYPASS( 17, 2, lw, 0xffffffffff00ff00, 4, tdat1 );
+
+  #-------------------------------------------------------------
+  # Test write-after-write hazard
+  #-------------------------------------------------------------
+
+  TEST_CASE( 18, x2, 2, \
+    la  x5, tdat; \
+    lw  x2, 0(x5); \
+    li  x2, 2; \
+  )
+
+  TEST_CASE( 19, x2, 2, \
+    la  x5, tdat; \
+    lw  x2, 0(x5); \
+    nop; \
+    li  x2, 2; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .word 0x00ff00ff
+tdat2:  .word 0xff00ff00
+tdat3:  .word 0x0ff00ff0
+tdat4:  .word 0xf00ff00f
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lwu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lwu.S
new file mode 100644
index 0000000..9f7cf67
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/lwu.S
@@ -0,0 +1,92 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# lwu.S
+#-----------------------------------------------------------------------------
+#
+# Test lwu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_LD_OP( 2, lwu, 0x0000000000ff00ff, 0,  tdat );
+  TEST_LD_OP( 3, lwu, 0x00000000ff00ff00, 4,  tdat );
+  TEST_LD_OP( 4, lwu, 0x000000000ff00ff0, 8,  tdat );
+  TEST_LD_OP( 5, lwu, 0x00000000f00ff00f, 12, tdat );
+
+  # Test with negative offset
+
+  TEST_LD_OP( 6, lwu, 0x0000000000ff00ff, -12, tdat4 );
+  TEST_LD_OP( 7, lwu, 0x00000000ff00ff00, -8,  tdat4 );
+  TEST_LD_OP( 8, lwu, 0x000000000ff00ff0, -4,  tdat4 );
+  TEST_LD_OP( 9, lwu, 0x00000000f00ff00f, 0,   tdat4 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x0000000000ff00ff, \
+    la  x1, tdat; \
+    addi x1, x1, -32; \
+    lwu x5, 32(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0x00000000ff00ff00, \
+    la  x1, tdat; \
+    addi x1, x1, -3; \
+    lwu x5, 7(x1); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_LD_DEST_BYPASS( 12, 0, lwu, 0x000000000ff00ff0, 4, tdat2 );
+  TEST_LD_DEST_BYPASS( 13, 1, lwu, 0x00000000f00ff00f, 4, tdat3 );
+  TEST_LD_DEST_BYPASS( 14, 2, lwu, 0x00000000ff00ff00, 4, tdat1 );
+
+  TEST_LD_SRC1_BYPASS( 15, 0, lwu, 0x000000000ff00ff0, 4, tdat2 );
+  TEST_LD_SRC1_BYPASS( 16, 1, lwu, 0x00000000f00ff00f, 4, tdat3 );
+  TEST_LD_SRC1_BYPASS( 17, 2, lwu, 0x00000000ff00ff00, 4, tdat1 );
+
+  #-------------------------------------------------------------
+  # Test write-after-write hazard
+  #-------------------------------------------------------------
+
+  TEST_CASE( 18, x2, 2, \
+    la  x5, tdat; \
+    lwu x2, 0(x5); \
+    li  x2, 2; \
+  )
+
+  TEST_CASE( 19, x2, 2, \
+    la  x5, tdat; \
+    lwu x2, 0(x5); \
+    nop; \
+    li  x2, 2; \
+  )
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .word 0x00ff00ff
+tdat2:  .word 0xff00ff00
+tdat3:  .word 0x0ff00ff0
+tdat4:  .word 0xf00ff00f
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/or.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/or.S
new file mode 100644
index 0000000..6d84f53
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/or.S
@@ -0,0 +1,69 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# or.S
+#-----------------------------------------------------------------------------
+#
+# Test or instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Logical tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_OP( 3, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_OP( 4, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
+  TEST_RR_OP( 5, or, 0xf0fff0ff, 0xf00ff00f, 0xf0f0f0f0 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 6, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC2_EQ_DEST( 7, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC12_EQ_DEST( 8, or, 0xff00ff00, 0xff00ff00 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 9,  0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_DEST_BYPASS( 10, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_DEST_BYPASS( 11, 2, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
+
+  TEST_RR_SRC12_BYPASS( 12, 0, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC12_BYPASS( 13, 0, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC12_BYPASS( 14, 0, 2, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
+  TEST_RR_SRC12_BYPASS( 15, 1, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC12_BYPASS( 16, 1, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC12_BYPASS( 17, 2, 0, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
+
+  TEST_RR_SRC21_BYPASS( 18, 0, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC21_BYPASS( 19, 0, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC21_BYPASS( 20, 0, 2, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
+  TEST_RR_SRC21_BYPASS( 21, 1, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC21_BYPASS( 22, 1, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC21_BYPASS( 23, 2, 0, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
+
+  TEST_RR_ZEROSRC1( 24, or, 0xff00ff00, 0xff00ff00 );
+  TEST_RR_ZEROSRC2( 25, or, 0x00ff00ff, 0x00ff00ff );
+  TEST_RR_ZEROSRC12( 26, or, 0 );
+  TEST_RR_ZERODEST( 27, or, 0x11111111, 0x22222222 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/ori.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/ori.S
new file mode 100644
index 0000000..437c00a
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/ori.S
@@ -0,0 +1,55 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# ori.S
+#-----------------------------------------------------------------------------
+#
+# Test ori instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Logical tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2, ori, 0xffffffffffffff0f, 0xffffffffff00ff00, 0xf0f );
+  TEST_IMM_OP( 3, ori, 0x000000000ff00ff0, 0x000000000ff00ff0, 0x0f0 );
+  TEST_IMM_OP( 4, ori, 0x0000000000ff07ff, 0x0000000000ff00ff, 0x70f );
+  TEST_IMM_OP( 5, ori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 6, ori, 0xff00fff0, 0xff00ff00, 0x0f0 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 7,  0, ori, 0x000000000ff00ff0, 0x000000000ff00ff0, 0x0f0 );
+  TEST_IMM_DEST_BYPASS( 8,  1, ori, 0x0000000000ff07ff, 0x0000000000ff00ff, 0x70f );
+  TEST_IMM_DEST_BYPASS( 9,  2, ori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 );
+
+  TEST_IMM_SRC1_BYPASS( 10, 0, ori, 0x000000000ff00ff0, 0x000000000ff00ff0, 0x0f0 );
+  TEST_IMM_SRC1_BYPASS( 11, 1, ori, 0xffffffffffffffff, 0x0000000000ff00ff, 0xf0f );
+  TEST_IMM_SRC1_BYPASS( 12, 2, ori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 );
+
+  TEST_IMM_ZEROSRC1( 13, ori, 0x0f0, 0x0f0 );
+  TEST_IMM_ZERODEST( 14, ori, 0x00ff00ff, 0x70f );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sb.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sb.S
new file mode 100644
index 0000000..19e32d6
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sb.S
@@ -0,0 +1,96 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sb.S
+#-----------------------------------------------------------------------------
+#
+# Test sb instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_ST_OP( 2, lb, sb, 0xffffffffffffffaa, 0, tdat );
+  TEST_ST_OP( 3, lb, sb, 0x0000000000000000, 1, tdat );
+  TEST_ST_OP( 4, lh, sb, 0xffffffffffffefa0, 2, tdat );
+  TEST_ST_OP( 5, lb, sb, 0x000000000000000a, 3, tdat );
+
+  # Test with negative offset
+
+  TEST_ST_OP( 6, lb, sb, 0xffffffffffffffaa, -3, tdat8 );
+  TEST_ST_OP( 7, lb, sb, 0x0000000000000000, -2, tdat8 );
+  TEST_ST_OP( 8, lb, sb, 0xffffffffffffffa0, -1, tdat8 );
+  TEST_ST_OP( 9, lb, sb, 0x000000000000000a, 0,  tdat8 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x78, \
+    la  x1, tdat9; \
+    li  x2, 0x12345678; \
+    addi x4, x1, -32; \
+    sb x2, 32(x4); \
+    lb x5, 0(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0xffffffffffffff98, \
+    la  x1, tdat9; \
+    li  x2, 0x00003098; \
+    addi x1, x1, -6; \
+    sb x2, 7(x1); \
+    la  x4, tdat10; \
+    lb x5, 0(x4); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_ST_SRC12_BYPASS( 12, 0, 0, lb, sb, 0xffffffffffffffdd, 0, tdat );
+  TEST_ST_SRC12_BYPASS( 13, 0, 1, lb, sb, 0xffffffffffffffcd, 1, tdat );
+  TEST_ST_SRC12_BYPASS( 14, 0, 2, lb, sb, 0xffffffffffffffcc, 2, tdat );
+  TEST_ST_SRC12_BYPASS( 15, 1, 0, lb, sb, 0xffffffffffffffbc, 3, tdat );
+  TEST_ST_SRC12_BYPASS( 16, 1, 1, lb, sb, 0xffffffffffffffbb, 4, tdat );
+  TEST_ST_SRC12_BYPASS( 17, 2, 0, lb, sb, 0xffffffffffffffab, 5, tdat );
+
+  TEST_ST_SRC21_BYPASS( 18, 0, 0, lb, sb, 0x33, 0, tdat );
+  TEST_ST_SRC21_BYPASS( 19, 0, 1, lb, sb, 0x23, 1, tdat );
+  TEST_ST_SRC21_BYPASS( 20, 0, 2, lb, sb, 0x22, 2, tdat );
+  TEST_ST_SRC21_BYPASS( 21, 1, 0, lb, sb, 0x12, 3, tdat );
+  TEST_ST_SRC21_BYPASS( 22, 1, 1, lb, sb, 0x11, 4, tdat );
+  TEST_ST_SRC21_BYPASS( 23, 2, 0, lb, sb, 0x01, 5, tdat );
+
+  li a0, 0xef
+  la a1, tdat
+  sb a0, 3(a1)
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .byte 0xef
+tdat2:  .byte 0xef
+tdat3:  .byte 0xef
+tdat4:  .byte 0xef
+tdat5:  .byte 0xef
+tdat6:  .byte 0xef
+tdat7:  .byte 0xef
+tdat8:  .byte 0xef
+tdat9:  .byte 0xef
+tdat10: .byte 0xef
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sd.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sd.S
new file mode 100644
index 0000000..b6fd66d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sd.S
@@ -0,0 +1,92 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sd.S
+#-----------------------------------------------------------------------------
+#
+# Test sd instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_ST_OP( 2, ld, sd, 0x00aa00aa00aa00aa, 0,  tdat );
+  TEST_ST_OP( 3, ld, sd, 0xaa00aa00aa00aa00, 8,  tdat );
+  TEST_ST_OP( 4, ld, sd, 0x0aa00aa00aa00aa0, 16,  tdat );
+  TEST_ST_OP( 5, ld, sd, 0xa00aa00aa00aa00a, 24, tdat );
+
+  # Test with negative offset
+
+  TEST_ST_OP( 6, ld, sd, 0x00aa00aa00aa00aa, -24, tdat8 );
+  TEST_ST_OP( 7, ld, sd, 0xaa00aa00aa00aa00, -16, tdat8 );
+  TEST_ST_OP( 8, ld, sd, 0x0aa00aa00aa00aa0, -8,  tdat8 );
+  TEST_ST_OP( 9, ld, sd, 0xa00aa00aa00aa00a, 0,   tdat8 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x1234567812345678, \
+    la  x1, tdat9; \
+    li  x2, 0x1234567812345678; \
+    addi x4, x1, -32; \
+    sd x2, 32(x4); \
+    ld x5, 0(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0x5821309858213098, \
+    la  x1, tdat9; \
+    li  x2, 0x5821309858213098; \
+    addi x1, x1, -3; \
+    sd x2, 11(x1); \
+    la  x4, tdat10; \
+    ld x5, 0(x4); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_ST_SRC12_BYPASS( 12, 0, 0, ld, sd, 0xabbccdd, 0,  tdat );
+  TEST_ST_SRC12_BYPASS( 13, 0, 1, ld, sd, 0xaabbccd, 8,  tdat );
+  TEST_ST_SRC12_BYPASS( 14, 0, 2, ld, sd, 0xdaabbcc, 16, tdat );
+  TEST_ST_SRC12_BYPASS( 15, 1, 0, ld, sd, 0xddaabbc, 24, tdat );
+  TEST_ST_SRC12_BYPASS( 16, 1, 1, ld, sd, 0xcddaabb, 32, tdat );
+  TEST_ST_SRC12_BYPASS( 17, 2, 0, ld, sd, 0xccddaab, 40, tdat );
+
+  TEST_ST_SRC21_BYPASS( 18, 0, 0, ld, sd, 0x00112233, 0,  tdat );
+  TEST_ST_SRC21_BYPASS( 19, 0, 1, ld, sd, 0x30011223, 8,  tdat );
+  TEST_ST_SRC21_BYPASS( 20, 0, 2, ld, sd, 0x33001122, 16, tdat );
+  TEST_ST_SRC21_BYPASS( 21, 1, 0, ld, sd, 0x23300112, 24, tdat );
+  TEST_ST_SRC21_BYPASS( 22, 1, 1, ld, sd, 0x22330011, 32, tdat );
+  TEST_ST_SRC21_BYPASS( 23, 2, 0, ld, sd, 0x12233001, 40, tdat );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .dword 0xdeadbeefdeadbeef
+tdat2:  .dword 0xdeadbeefdeadbeef
+tdat3:  .dword 0xdeadbeefdeadbeef
+tdat4:  .dword 0xdeadbeefdeadbeef
+tdat5:  .dword 0xdeadbeefdeadbeef
+tdat6:  .dword 0xdeadbeefdeadbeef
+tdat7:  .dword 0xdeadbeefdeadbeef
+tdat8:  .dword 0xdeadbeefdeadbeef
+tdat9:  .dword 0xdeadbeefdeadbeef
+tdat10: .dword 0xdeadbeefdeadbeef
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sh.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sh.S
new file mode 100644
index 0000000..ea9eb23
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sh.S
@@ -0,0 +1,96 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sh.S
+#-----------------------------------------------------------------------------
+#
+# Test sh instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_ST_OP( 2, lh, sh, 0x00000000000000aa, 0, tdat );
+  TEST_ST_OP( 3, lh, sh, 0xffffffffffffaa00, 2, tdat );
+  TEST_ST_OP( 4, lw, sh, 0xffffffffbeef0aa0, 4, tdat );
+  TEST_ST_OP( 5, lh, sh, 0xffffffffffffa00a, 6, tdat );
+
+  # Test with negative offset
+
+  TEST_ST_OP( 6, lh, sh, 0x00000000000000aa, -6, tdat8 );
+  TEST_ST_OP( 7, lh, sh, 0xffffffffffffaa00, -4, tdat8 );
+  TEST_ST_OP( 8, lh, sh, 0x0000000000000aa0, -2, tdat8 );
+  TEST_ST_OP( 9, lh, sh, 0xffffffffffffa00a, 0,  tdat8 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x5678, \
+    la  x1, tdat9; \
+    li  x2, 0x12345678; \
+    addi x4, x1, -32; \
+    sh x2, 32(x4); \
+    lh x5, 0(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0x3098, \
+    la  x1, tdat9; \
+    li  x2, 0x00003098; \
+    addi x1, x1, -5; \
+    sh x2, 7(x1); \
+    la  x4, tdat10; \
+    lh x5, 0(x4); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_ST_SRC12_BYPASS( 12, 0, 0, lh, sh, 0xffffffffffffccdd, 0,  tdat );
+  TEST_ST_SRC12_BYPASS( 13, 0, 1, lh, sh, 0xffffffffffffbccd, 2,  tdat );
+  TEST_ST_SRC12_BYPASS( 14, 0, 2, lh, sh, 0xffffffffffffbbcc, 4,  tdat );
+  TEST_ST_SRC12_BYPASS( 15, 1, 0, lh, sh, 0xffffffffffffabbc, 6, tdat );
+  TEST_ST_SRC12_BYPASS( 16, 1, 1, lh, sh, 0xffffffffffffaabb, 8, tdat );
+  TEST_ST_SRC12_BYPASS( 17, 2, 0, lh, sh, 0xffffffffffffdaab, 10, tdat );
+
+  TEST_ST_SRC21_BYPASS( 18, 0, 0, lh, sh, 0x2233, 0,  tdat );
+  TEST_ST_SRC21_BYPASS( 19, 0, 1, lh, sh, 0x1223, 2,  tdat );
+  TEST_ST_SRC21_BYPASS( 20, 0, 2, lh, sh, 0x1122, 4,  tdat );
+  TEST_ST_SRC21_BYPASS( 21, 1, 0, lh, sh, 0x0112, 6, tdat );
+  TEST_ST_SRC21_BYPASS( 22, 1, 1, lh, sh, 0x0011, 8, tdat );
+  TEST_ST_SRC21_BYPASS( 23, 2, 0, lh, sh, 0x3001, 10, tdat );
+
+  li a0, 0xbeef
+  la a1, tdat
+  sh a0, 6(a1)
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .half 0xbeef
+tdat2:  .half 0xbeef
+tdat3:  .half 0xbeef
+tdat4:  .half 0xbeef
+tdat5:  .half 0xbeef
+tdat6:  .half 0xbeef
+tdat7:  .half 0xbeef
+tdat8:  .half 0xbeef
+tdat9:  .half 0xbeef
+tdat10: .half 0xbeef
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/simple.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/simple.S
new file mode 100644
index 0000000..6c45fbd
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/simple.S
@@ -0,0 +1,27 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# simple.S
+#-----------------------------------------------------------------------------
+#
+# This is the most basic self checking test. If your simulator does not
+# pass thiss then there is little chance that it will pass any of the
+# more complicated self checking tests.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+RVTEST_PASS
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sll.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sll.S
new file mode 100644
index 0000000..257aa9d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sll.S
@@ -0,0 +1,96 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sll.S
+#-----------------------------------------------------------------------------
+#
+# Test sll instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  sll, 0x0000000000000001, 0x0000000000000001, 0  );
+  TEST_RR_OP( 3,  sll, 0x0000000000000002, 0x0000000000000001, 1  );
+  TEST_RR_OP( 4,  sll, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_OP( 5,  sll, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_OP( 6,  sll, 0x0000000080000000, 0x0000000000000001, 31 );
+
+  TEST_RR_OP( 7,  sll, 0xffffffffffffffff, 0xffffffffffffffff, 0  );
+  TEST_RR_OP( 8,  sll, 0xfffffffffffffffe, 0xffffffffffffffff, 1  );
+  TEST_RR_OP( 9,  sll, 0xffffffffffffff80, 0xffffffffffffffff, 7  );
+  TEST_RR_OP( 10, sll, 0xffffffffffffc000, 0xffffffffffffffff, 14 );
+  TEST_RR_OP( 11, sll, 0xffffffff80000000, 0xffffffffffffffff, 31 );
+
+  TEST_RR_OP( 12, sll, 0x0000000021212121, 0x0000000021212121, 0  );
+  TEST_RR_OP( 13, sll, 0x0000000042424242, 0x0000000021212121, 1  );
+  TEST_RR_OP( 14, sll, 0x0000001090909080, 0x0000000021212121, 7  );
+  TEST_RR_OP( 15, sll, 0x0000084848484000, 0x0000000021212121, 14 );
+  TEST_RR_OP( 16, sll, 0x1090909080000000, 0x0000000021212121, 31 );
+
+  # Verify that shifts only use bottom six bits
+
+  TEST_RR_OP( 17, sll, 0x0000000021212121, 0x0000000021212121, 0xffffffffffffffc0 );
+  TEST_RR_OP( 18, sll, 0x0000000042424242, 0x0000000021212121, 0xffffffffffffffc1 );
+  TEST_RR_OP( 19, sll, 0x0000001090909080, 0x0000000021212121, 0xffffffffffffffc7 );
+  TEST_RR_OP( 20, sll, 0x0000084848484000, 0x0000000021212121, 0xffffffffffffffce );
+
+#if __riscv_xlen == 64
+  TEST_RR_OP( 21, sll, 0x8000000000000000, 0x0000000021212121, 0xffffffffffffffff );
+  TEST_RR_OP( 50, sll, 0x8000000000000000, 0x0000000000000001, 63 );
+  TEST_RR_OP( 51, sll, 0xffffff8000000000, 0xffffffffffffffff, 39 );
+  TEST_RR_OP( 52, sll, 0x0909080000000000, 0x0000000021212121, 43 );
+#endif
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 22, sll, 0x00000080, 0x00000001, 7  );
+  TEST_RR_SRC2_EQ_DEST( 23, sll, 0x00004000, 0x00000001, 14 );
+  TEST_RR_SRC12_EQ_DEST( 24, sll, 24, 3 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 25, 0, sll, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_DEST_BYPASS( 26, 1, sll, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_DEST_BYPASS( 27, 2, sll, 0x0000000080000000, 0x0000000000000001, 31 );
+
+  TEST_RR_SRC12_BYPASS( 28, 0, 0, sll, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_SRC12_BYPASS( 29, 0, 1, sll, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_SRC12_BYPASS( 30, 0, 2, sll, 0x0000000080000000, 0x0000000000000001, 31 );
+  TEST_RR_SRC12_BYPASS( 31, 1, 0, sll, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_SRC12_BYPASS( 32, 1, 1, sll, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_SRC12_BYPASS( 33, 2, 0, sll, 0x0000000080000000, 0x0000000000000001, 31 );
+
+  TEST_RR_SRC21_BYPASS( 34, 0, 0, sll, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_SRC21_BYPASS( 35, 0, 1, sll, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_SRC21_BYPASS( 36, 0, 2, sll, 0x0000000080000000, 0x0000000000000001, 31 );
+  TEST_RR_SRC21_BYPASS( 37, 1, 0, sll, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_SRC21_BYPASS( 38, 1, 1, sll, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_SRC21_BYPASS( 39, 2, 0, sll, 0x0000000080000000, 0x0000000000000001, 31 );
+
+  TEST_RR_ZEROSRC1( 40, sll, 0, 15 );
+  TEST_RR_ZEROSRC2( 41, sll, 32, 32 );
+  TEST_RR_ZEROSRC12( 42, sll, 0 );
+  TEST_RR_ZERODEST( 43, sll, 1024, 2048 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slli.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slli.S
new file mode 100644
index 0000000..f28ea1c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slli.S
@@ -0,0 +1,74 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# slli.S
+#-----------------------------------------------------------------------------
+#
+# Test slli instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2,  slli, 0x0000000000000001, 0x0000000000000001, 0  );
+  TEST_IMM_OP( 3,  slli, 0x0000000000000002, 0x0000000000000001, 1  );
+  TEST_IMM_OP( 4,  slli, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_IMM_OP( 5,  slli, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_IMM_OP( 6,  slli, 0x0000000080000000, 0x0000000000000001, 31 );
+
+  TEST_IMM_OP( 7,  slli, 0xffffffffffffffff, 0xffffffffffffffff, 0  );
+  TEST_IMM_OP( 8,  slli, 0xfffffffffffffffe, 0xffffffffffffffff, 1  );
+  TEST_IMM_OP( 9,  slli, 0xffffffffffffff80, 0xffffffffffffffff, 7  );
+  TEST_IMM_OP( 10, slli, 0xffffffffffffc000, 0xffffffffffffffff, 14 );
+  TEST_IMM_OP( 11, slli, 0xffffffff80000000, 0xffffffffffffffff, 31 );
+
+  TEST_IMM_OP( 12, slli, 0x0000000021212121, 0x0000000021212121, 0  );
+  TEST_IMM_OP( 13, slli, 0x0000000042424242, 0x0000000021212121, 1  );
+  TEST_IMM_OP( 14, slli, 0x0000001090909080, 0x0000000021212121, 7  );
+  TEST_IMM_OP( 15, slli, 0x0000084848484000, 0x0000000021212121, 14 );
+  TEST_IMM_OP( 16, slli, 0x1090909080000000, 0x0000000021212121, 31 );
+
+#if __riscv_xlen == 64
+  TEST_RR_OP( 50, sll, 0x8000000000000000, 0x0000000000000001, 63 );
+  TEST_RR_OP( 51, sll, 0xffffff8000000000, 0xffffffffffffffff, 39 );
+  TEST_RR_OP( 52, sll, 0x0909080000000000, 0x0000000021212121, 43 );
+#endif
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, slli, 0x00000080, 0x00000001, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, slli, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_IMM_DEST_BYPASS( 19, 1, slli, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_IMM_DEST_BYPASS( 20, 2, slli, 0x0000000080000000, 0x0000000000000001, 31 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, slli, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_IMM_SRC1_BYPASS( 22, 1, slli, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, slli, 0x0000000080000000, 0x0000000000000001, 31 );
+
+  TEST_IMM_ZEROSRC1( 24, slli, 0, 31 );
+  TEST_IMM_ZERODEST( 25, slli, 33, 20 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slliw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slliw.S
new file mode 100644
index 0000000..7822f09
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slliw.S
@@ -0,0 +1,68 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# slliw.S
+#-----------------------------------------------------------------------------
+#
+# Test slliw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2,  slliw, 0x0000000000000001, 0x0000000000000001, 0  );
+  TEST_IMM_OP( 3,  slliw, 0x0000000000000002, 0x0000000000000001, 1  );
+  TEST_IMM_OP( 4,  slliw, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_IMM_OP( 5,  slliw, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_IMM_OP( 6,  slliw, 0xffffffff80000000, 0x0000000000000001, 31 );
+
+  TEST_IMM_OP( 7,  slliw, 0xffffffffffffffff, 0xffffffffffffffff, 0  );
+  TEST_IMM_OP( 8,  slliw, 0xfffffffffffffffe, 0xffffffffffffffff, 1  );
+  TEST_IMM_OP( 9,  slliw, 0xffffffffffffff80, 0xffffffffffffffff, 7  );
+  TEST_IMM_OP( 10, slliw, 0xffffffffffffc000, 0xffffffffffffffff, 14 );
+  TEST_IMM_OP( 11, slliw, 0xffffffff80000000, 0xffffffffffffffff, 31 );
+
+  TEST_IMM_OP( 12, slliw, 0x0000000021212121, 0x0000000021212121, 0  );
+  TEST_IMM_OP( 13, slliw, 0x0000000042424242, 0x0000000021212121, 1  );
+  TEST_IMM_OP( 14, slliw, 0xffffffff90909080, 0x0000000021212121, 7  );
+  TEST_IMM_OP( 15, slliw, 0x0000000048484000, 0x0000000021212121, 14 );
+  TEST_IMM_OP( 16, slliw, 0xffffffff80000000, 0x0000000021212121, 31 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, slliw, 0x00000080, 0x00000001, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, slliw, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_IMM_DEST_BYPASS( 19, 1, slliw, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_IMM_DEST_BYPASS( 20, 2, slliw, 0xffffffff80000000, 0x0000000000000001, 31 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, slliw, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_IMM_SRC1_BYPASS( 22, 1, slliw, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, slliw, 0xffffffff80000000, 0x0000000000000001, 31 );
+
+  TEST_IMM_ZEROSRC1( 24, slliw, 0, 31 );
+  TEST_IMM_ZERODEST( 25, slliw, 31, 28 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sllw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sllw.S
new file mode 100644
index 0000000..59770ee
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sllw.S
@@ -0,0 +1,90 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sllw.S
+#-----------------------------------------------------------------------------
+#
+# Test sllw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  sllw, 0x0000000000000001, 0x0000000000000001, 0  );
+  TEST_RR_OP( 3,  sllw, 0x0000000000000002, 0x0000000000000001, 1  );
+  TEST_RR_OP( 4,  sllw, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_OP( 5,  sllw, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_OP( 6,  sllw, 0xffffffff80000000, 0x0000000000000001, 31 );
+
+  TEST_RR_OP( 7,  sllw, 0xffffffffffffffff, 0xffffffffffffffff, 0  );
+  TEST_RR_OP( 8,  sllw, 0xfffffffffffffffe, 0xffffffffffffffff, 1  );
+  TEST_RR_OP( 9,  sllw, 0xffffffffffffff80, 0xffffffffffffffff, 7  );
+  TEST_RR_OP( 10, sllw, 0xffffffffffffc000, 0xffffffffffffffff, 14 );
+  TEST_RR_OP( 11, sllw, 0xffffffff80000000, 0xffffffffffffffff, 31 );
+
+  TEST_RR_OP( 12, sllw, 0x0000000021212121, 0x0000000021212121, 0  );
+  TEST_RR_OP( 13, sllw, 0x0000000042424242, 0x0000000021212121, 1  );
+  TEST_RR_OP( 14, sllw, 0xffffffff90909080, 0x0000000021212121, 7  );
+  TEST_RR_OP( 15, sllw, 0x0000000048484000, 0x0000000021212121, 14 );
+  TEST_RR_OP( 16, sllw, 0xffffffff80000000, 0x0000000021212121, 31 );
+
+  # Verify that shifts only use bottom five bits
+
+  TEST_RR_OP( 17, sllw, 0x0000000021212121, 0x0000000021212121, 0xffffffffffffffe0 );
+  TEST_RR_OP( 18, sllw, 0x0000000042424242, 0x0000000021212121, 0xffffffffffffffe1 );
+  TEST_RR_OP( 19, sllw, 0xffffffff90909080, 0x0000000021212121, 0xffffffffffffffe7 );
+  TEST_RR_OP( 20, sllw, 0x0000000048484000, 0x0000000021212121, 0xffffffffffffffee );
+  TEST_RR_OP( 21, sllw, 0xffffffff80000000, 0x0000000021212121, 0xffffffffffffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 22, sllw, 0x00000080, 0x00000001, 7  );
+  TEST_RR_SRC2_EQ_DEST( 23, sllw, 0x00004000, 0x00000001, 14 );
+  TEST_RR_SRC12_EQ_DEST( 24, sllw, 24, 3 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 25, 0, sllw, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_DEST_BYPASS( 26, 1, sllw, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_DEST_BYPASS( 27, 2, sllw, 0xffffffff80000000, 0x0000000000000001, 31 );
+
+  TEST_RR_SRC12_BYPASS( 28, 0, 0, sllw, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_SRC12_BYPASS( 29, 0, 1, sllw, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_SRC12_BYPASS( 30, 0, 2, sllw, 0xffffffff80000000, 0x0000000000000001, 31 );
+  TEST_RR_SRC12_BYPASS( 31, 1, 0, sllw, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_SRC12_BYPASS( 32, 1, 1, sllw, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_SRC12_BYPASS( 33, 2, 0, sllw, 0xffffffff80000000, 0x0000000000000001, 31 );
+
+  TEST_RR_SRC21_BYPASS( 34, 0, 0, sllw, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_SRC21_BYPASS( 35, 0, 1, sllw, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_SRC21_BYPASS( 36, 0, 2, sllw, 0xffffffff80000000, 0x0000000000000001, 31 );
+  TEST_RR_SRC21_BYPASS( 37, 1, 0, sllw, 0x0000000000000080, 0x0000000000000001, 7  );
+  TEST_RR_SRC21_BYPASS( 38, 1, 1, sllw, 0x0000000000004000, 0x0000000000000001, 14 );
+  TEST_RR_SRC21_BYPASS( 39, 2, 0, sllw, 0xffffffff80000000, 0x0000000000000001, 31 );
+
+  TEST_RR_ZEROSRC1( 40, sllw, 0, 15 );
+  TEST_RR_ZEROSRC2( 41, sllw, 32, 32 );
+  TEST_RR_ZEROSRC12( 42, sllw, 0 );
+  TEST_RR_ZERODEST( 43, sllw, 1024, 2048 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slt.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slt.S
new file mode 100644
index 0000000..644a51a
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slt.S
@@ -0,0 +1,84 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# slt.S
+#-----------------------------------------------------------------------------
+#
+# Test slt instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  slt, 0, 0x0000000000000000, 0x0000000000000000 );
+  TEST_RR_OP( 3,  slt, 0, 0x0000000000000001, 0x0000000000000001 );
+  TEST_RR_OP( 4,  slt, 1, 0x0000000000000003, 0x0000000000000007 );
+  TEST_RR_OP( 5,  slt, 0, 0x0000000000000007, 0x0000000000000003 );
+
+  TEST_RR_OP( 6,  slt, 0, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 7,  slt, 1, 0xffffffff80000000, 0x0000000000000000 );
+  TEST_RR_OP( 8,  slt, 1, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 9,  slt, 1, 0x0000000000000000, 0x0000000000007fff );
+  TEST_RR_OP( 10, slt, 0, 0x000000007fffffff, 0x0000000000000000 );
+  TEST_RR_OP( 11, slt, 0, 0x000000007fffffff, 0x0000000000007fff );
+
+  TEST_RR_OP( 12, slt, 1, 0xffffffff80000000, 0x0000000000007fff );
+  TEST_RR_OP( 13, slt, 0, 0x000000007fffffff, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 14, slt, 0, 0x0000000000000000, 0xffffffffffffffff );
+  TEST_RR_OP( 15, slt, 1, 0xffffffffffffffff, 0x0000000000000001 );
+  TEST_RR_OP( 16, slt, 0, 0xffffffffffffffff, 0xffffffffffffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 17, slt, 0, 14, 13 );
+  TEST_RR_SRC2_EQ_DEST( 18, slt, 1, 11, 13 );
+  TEST_RR_SRC12_EQ_DEST( 19, slt, 0, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 20, 0, slt, 1, 11, 13 );
+  TEST_RR_DEST_BYPASS( 21, 1, slt, 0, 14, 13 );
+  TEST_RR_DEST_BYPASS( 22, 2, slt, 1, 12, 13 );
+
+  TEST_RR_SRC12_BYPASS( 23, 0, 0, slt, 0, 14, 13 );
+  TEST_RR_SRC12_BYPASS( 24, 0, 1, slt, 1, 11, 13 );
+  TEST_RR_SRC12_BYPASS( 25, 0, 2, slt, 0, 15, 13 );
+  TEST_RR_SRC12_BYPASS( 26, 1, 0, slt, 1, 10, 13 );
+  TEST_RR_SRC12_BYPASS( 27, 1, 1, slt, 0, 16, 13 );
+  TEST_RR_SRC12_BYPASS( 28, 2, 0, slt, 1,  9, 13 );
+
+  TEST_RR_SRC21_BYPASS( 29, 0, 0, slt, 0, 17, 13 );
+  TEST_RR_SRC21_BYPASS( 30, 0, 1, slt, 1,  8, 13 );
+  TEST_RR_SRC21_BYPASS( 31, 0, 2, slt, 0, 18, 13 );
+  TEST_RR_SRC21_BYPASS( 32, 1, 0, slt, 1,  7, 13 );
+  TEST_RR_SRC21_BYPASS( 33, 1, 1, slt, 0, 19, 13 );
+  TEST_RR_SRC21_BYPASS( 34, 2, 0, slt, 1,  6, 13 );
+
+  TEST_RR_ZEROSRC1( 35, slt, 0, -1 );
+  TEST_RR_ZEROSRC2( 36, slt, 1, -1 );
+  TEST_RR_ZEROSRC12( 37, slt, 0 );
+  TEST_RR_ZERODEST( 38, slt, 16, 30 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slti.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slti.S
new file mode 100644
index 0000000..9222fa4
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/slti.S
@@ -0,0 +1,70 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# slti.S
+#-----------------------------------------------------------------------------
+#
+# Test slti instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2,  slti, 0, 0x0000000000000000, 0x000 );
+  TEST_IMM_OP( 3,  slti, 0, 0x0000000000000001, 0x001 );
+  TEST_IMM_OP( 4,  slti, 1, 0x0000000000000003, 0x007 );
+  TEST_IMM_OP( 5,  slti, 0, 0x0000000000000007, 0x003 );
+
+  TEST_IMM_OP( 6,  slti, 0, 0x0000000000000000, 0x800 );
+  TEST_IMM_OP( 7,  slti, 1, 0xffffffff80000000, 0x000 );
+  TEST_IMM_OP( 8,  slti, 1, 0xffffffff80000000, 0x800 );
+
+  TEST_IMM_OP( 9,  slti, 1, 0x0000000000000000, 0x7ff );
+  TEST_IMM_OP( 10, slti, 0, 0x000000007fffffff, 0x000 );
+  TEST_IMM_OP( 11, slti, 0, 0x000000007fffffff, 0x7ff );
+
+  TEST_IMM_OP( 12, slti, 1, 0xffffffff80000000, 0x7ff );
+  TEST_IMM_OP( 13, slti, 0, 0x000000007fffffff, 0x800 );
+
+  TEST_IMM_OP( 14, slti, 0, 0x0000000000000000, 0xfff );
+  TEST_IMM_OP( 15, slti, 1, 0xffffffffffffffff, 0x001 );
+  TEST_IMM_OP( 16, slti, 0, 0xffffffffffffffff, 0xfff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, slti, 1, 11, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, slti, 0, 15, 10 );
+  TEST_IMM_DEST_BYPASS( 19, 1, slti, 1, 10, 16 );
+  TEST_IMM_DEST_BYPASS( 20, 2, slti, 0, 16,  9 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, slti, 1, 11, 15 );
+  TEST_IMM_SRC1_BYPASS( 22, 1, slti, 0, 17,  8 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, slti, 1, 12, 14 );
+
+  TEST_IMM_ZEROSRC1( 24, slti, 0, 0xfff );
+  TEST_IMM_ZERODEST( 25, slti, 0x00ff00ff, 0xfff );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sltiu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sltiu.S
new file mode 100644
index 0000000..f6a719b
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sltiu.S
@@ -0,0 +1,70 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sltiu.S
+#-----------------------------------------------------------------------------
+#
+# Test sltiu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2,  sltiu, 0, 0x0000000000000000, 0x000 );
+  TEST_IMM_OP( 3,  sltiu, 0, 0x0000000000000001, 0x001 );
+  TEST_IMM_OP( 4,  sltiu, 1, 0x0000000000000003, 0x007 );
+  TEST_IMM_OP( 5,  sltiu, 0, 0x0000000000000007, 0x003 );
+
+  TEST_IMM_OP( 6,  sltiu, 1, 0x0000000000000000, 0x800 );
+  TEST_IMM_OP( 7,  sltiu, 0, 0xffffffff80000000, 0x000 );
+  TEST_IMM_OP( 8,  sltiu, 1, 0xffffffff80000000, 0x800 );
+
+  TEST_IMM_OP( 9,  sltiu, 1, 0x0000000000000000, 0x7ff );
+  TEST_IMM_OP( 10, sltiu, 0, 0x000000007fffffff, 0x000 );
+  TEST_IMM_OP( 11, sltiu, 0, 0x000000007fffffff, 0x7ff );
+
+  TEST_IMM_OP( 12, sltiu, 0, 0xffffffff80000000, 0x7ff );
+  TEST_IMM_OP( 13, sltiu, 1, 0x000000007fffffff, 0x800 );
+
+  TEST_IMM_OP( 14, sltiu, 1, 0x0000000000000000, 0xfff );
+  TEST_IMM_OP( 15, sltiu, 0, 0xffffffffffffffff, 0x001 );
+  TEST_IMM_OP( 16, sltiu, 0, 0xffffffffffffffff, 0xfff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, sltiu, 1, 11, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, sltiu, 0, 15, 10 );
+  TEST_IMM_DEST_BYPASS( 19, 1, sltiu, 1, 10, 16 );
+  TEST_IMM_DEST_BYPASS( 20, 2, sltiu, 0, 16,  9 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, sltiu, 1, 11, 15 );
+  TEST_IMM_SRC1_BYPASS( 22, 1, sltiu, 0, 17,  8 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, sltiu, 1, 12, 14 );
+
+  TEST_IMM_ZEROSRC1( 24, sltiu, 1, 0xfff );
+  TEST_IMM_ZERODEST( 25, sltiu, 0x00ff00ff, 0xfff );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sltu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sltu.S
new file mode 100644
index 0000000..52ff685
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sltu.S
@@ -0,0 +1,84 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sltu.S
+#-----------------------------------------------------------------------------
+#
+# Test sltu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  sltu, 0, 0x00000000, 0x00000000 );
+  TEST_RR_OP( 3,  sltu, 0, 0x00000001, 0x00000001 );
+  TEST_RR_OP( 4,  sltu, 1, 0x00000003, 0x00000007 );
+  TEST_RR_OP( 5,  sltu, 0, 0x00000007, 0x00000003 );
+
+  TEST_RR_OP( 6,  sltu, 1, 0x00000000, 0xffff8000 );
+  TEST_RR_OP( 7,  sltu, 0, 0x80000000, 0x00000000 );
+  TEST_RR_OP( 8,  sltu, 1, 0x80000000, 0xffff8000 );
+
+  TEST_RR_OP( 9,  sltu, 1, 0x00000000, 0x00007fff );
+  TEST_RR_OP( 10, sltu, 0, 0x7fffffff, 0x00000000 );
+  TEST_RR_OP( 11, sltu, 0, 0x7fffffff, 0x00007fff );
+
+  TEST_RR_OP( 12, sltu, 0, 0x80000000, 0x00007fff );
+  TEST_RR_OP( 13, sltu, 1, 0x7fffffff, 0xffff8000 );
+
+  TEST_RR_OP( 14, sltu, 1, 0x00000000, 0xffffffff );
+  TEST_RR_OP( 15, sltu, 0, 0xffffffff, 0x00000001 );
+  TEST_RR_OP( 16, sltu, 0, 0xffffffff, 0xffffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 17, sltu, 0, 14, 13 );
+  TEST_RR_SRC2_EQ_DEST( 18, sltu, 1, 11, 13 );
+  TEST_RR_SRC12_EQ_DEST( 19, sltu, 0, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 20, 0, sltu, 1, 11, 13 );
+  TEST_RR_DEST_BYPASS( 21, 1, sltu, 0, 14, 13 );
+  TEST_RR_DEST_BYPASS( 22, 2, sltu, 1, 12, 13 );
+
+  TEST_RR_SRC12_BYPASS( 23, 0, 0, sltu, 0, 14, 13 );
+  TEST_RR_SRC12_BYPASS( 24, 0, 1, sltu, 1, 11, 13 );
+  TEST_RR_SRC12_BYPASS( 25, 0, 2, sltu, 0, 15, 13 );
+  TEST_RR_SRC12_BYPASS( 26, 1, 0, sltu, 1, 10, 13 );
+  TEST_RR_SRC12_BYPASS( 27, 1, 1, sltu, 0, 16, 13 );
+  TEST_RR_SRC12_BYPASS( 28, 2, 0, sltu, 1,  9, 13 );
+
+  TEST_RR_SRC21_BYPASS( 29, 0, 0, sltu, 0, 17, 13 );
+  TEST_RR_SRC21_BYPASS( 30, 0, 1, sltu, 1,  8, 13 );
+  TEST_RR_SRC21_BYPASS( 31, 0, 2, sltu, 0, 18, 13 );
+  TEST_RR_SRC21_BYPASS( 32, 1, 0, sltu, 1,  7, 13 );
+  TEST_RR_SRC21_BYPASS( 33, 1, 1, sltu, 0, 19, 13 );
+  TEST_RR_SRC21_BYPASS( 34, 2, 0, sltu, 1,  6, 13 );
+
+  TEST_RR_ZEROSRC1( 35, sltu, 1, -1 );
+  TEST_RR_ZEROSRC2( 36, sltu, 0, -1 );
+  TEST_RR_ZEROSRC12( 37, sltu, 0 );
+  TEST_RR_ZERODEST( 38, sltu, 16, 30 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sra.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sra.S
new file mode 100644
index 0000000..9b359a3
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sra.S
@@ -0,0 +1,90 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sra.S
+#-----------------------------------------------------------------------------
+#
+# Test sra instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  sra, 0xffffffff80000000, 0xffffffff80000000, 0  );
+  TEST_RR_OP( 3,  sra, 0xffffffffc0000000, 0xffffffff80000000, 1  );
+  TEST_RR_OP( 4,  sra, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_OP( 5,  sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_OP( 6,  sra, 0xffffffffffffffff, 0xffffffff80000001, 31 );
+
+  TEST_RR_OP( 7,  sra, 0x000000007fffffff, 0x000000007fffffff, 0  );
+  TEST_RR_OP( 8,  sra, 0x000000003fffffff, 0x000000007fffffff, 1  );
+  TEST_RR_OP( 9,  sra, 0x0000000000ffffff, 0x000000007fffffff, 7  );
+  TEST_RR_OP( 10, sra, 0x000000000001ffff, 0x000000007fffffff, 14 );
+  TEST_RR_OP( 11, sra, 0x0000000000000000, 0x000000007fffffff, 31 );
+
+  TEST_RR_OP( 12, sra, 0xffffffff81818181, 0xffffffff81818181, 0  );
+  TEST_RR_OP( 13, sra, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1  );
+  TEST_RR_OP( 14, sra, 0xffffffffff030303, 0xffffffff81818181, 7  );
+  TEST_RR_OP( 15, sra, 0xfffffffffffe0606, 0xffffffff81818181, 14 );
+  TEST_RR_OP( 16, sra, 0xffffffffffffffff, 0xffffffff81818181, 31 );
+
+  # Verify that shifts only use bottom five bits
+
+  TEST_RR_OP( 17, sra, 0xffffffff81818181, 0xffffffff81818181, 0xffffffffffffffc0 );
+  TEST_RR_OP( 18, sra, 0xffffffffc0c0c0c0, 0xffffffff81818181, 0xffffffffffffffc1 );
+  TEST_RR_OP( 19, sra, 0xffffffffff030303, 0xffffffff81818181, 0xffffffffffffffc7 );
+  TEST_RR_OP( 20, sra, 0xfffffffffffe0606, 0xffffffff81818181, 0xffffffffffffffce );
+  TEST_RR_OP( 21, sra, 0xffffffffffffffff, 0xffffffff81818181, 0xffffffffffffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 22, sra, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC2_EQ_DEST( 23, sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC12_EQ_DEST( 24, sra, 0, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 25, 0, sra, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_DEST_BYPASS( 26, 1, sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_DEST_BYPASS( 27, 2, sra, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+
+  TEST_RR_SRC12_BYPASS( 28, 0, 0, sra, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC12_BYPASS( 29, 0, 1, sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC12_BYPASS( 30, 0, 2, sra, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+  TEST_RR_SRC12_BYPASS( 31, 1, 0, sra, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC12_BYPASS( 32, 1, 1, sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC12_BYPASS( 33, 2, 0, sra, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+
+  TEST_RR_SRC21_BYPASS( 34, 0, 0, sra, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC21_BYPASS( 35, 0, 1, sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC21_BYPASS( 36, 0, 2, sra, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+  TEST_RR_SRC21_BYPASS( 37, 1, 0, sra, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC21_BYPASS( 38, 1, 1, sra, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC21_BYPASS( 39, 2, 0, sra, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+
+  TEST_RR_ZEROSRC1( 40, sra, 0, 15 );
+  TEST_RR_ZEROSRC2( 41, sra, 32, 32 );
+  TEST_RR_ZEROSRC12( 42, sra, 0 );
+  TEST_RR_ZERODEST( 43, sra, 1024, 2048 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srai.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srai.S
new file mode 100644
index 0000000..8d05213
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srai.S
@@ -0,0 +1,68 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# srai.S
+#-----------------------------------------------------------------------------
+#
+# Test srai instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2,  srai, 0xffffff8000000000, 0xffffff8000000000, 0  );
+  TEST_IMM_OP( 3,  srai, 0xffffffffc0000000, 0xffffffff80000000, 1  );
+  TEST_IMM_OP( 4,  srai, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_IMM_OP( 5,  srai, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_IMM_OP( 6,  srai, 0xffffffffffffffff, 0xffffffff80000001, 31 );
+
+  TEST_IMM_OP( 7,  srai, 0x000000007fffffff, 0x000000007fffffff, 0  );
+  TEST_IMM_OP( 8,  srai, 0x000000003fffffff, 0x000000007fffffff, 1  );
+  TEST_IMM_OP( 9,  srai, 0x0000000000ffffff, 0x000000007fffffff, 7  );
+  TEST_IMM_OP( 10, srai, 0x000000000001ffff, 0x000000007fffffff, 14 );
+  TEST_IMM_OP( 11, srai, 0x0000000000000000, 0x000000007fffffff, 31 );
+
+  TEST_IMM_OP( 12, srai, 0xffffffff81818181, 0xffffffff81818181, 0  );
+  TEST_IMM_OP( 13, srai, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1  );
+  TEST_IMM_OP( 14, srai, 0xffffffffff030303, 0xffffffff81818181, 7  );
+  TEST_IMM_OP( 15, srai, 0xfffffffffffe0606, 0xffffffff81818181, 14 );
+  TEST_IMM_OP( 16, srai, 0xffffffffffffffff, 0xffffffff81818181, 31 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, srai, 0xffffffffff000000, 0xffffffff80000000, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, srai, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_IMM_DEST_BYPASS( 19, 1, srai, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_IMM_DEST_BYPASS( 20, 2, srai, 0xffffffffffffffff, 0xffffffff80000001, 31 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, srai, 0xffffffffff000000, 0xffffffff80000000, 7 );
+  TEST_IMM_SRC1_BYPASS( 22, 1, srai, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, srai, 0xffffffffffffffff, 0xffffffff80000001, 31 );
+
+  TEST_IMM_ZEROSRC1( 24, srai, 0, 4 );
+  TEST_IMM_ZERODEST( 25, srai, 33, 10 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sraiw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sraiw.S
new file mode 100644
index 0000000..9240c9b
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sraiw.S
@@ -0,0 +1,71 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sraiw.S
+#-----------------------------------------------------------------------------
+#
+# Test sraiw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2,  sraiw, 0xffffffff80000000, 0xffffffff80000000, 0  );
+  TEST_IMM_OP( 3,  sraiw, 0xffffffffc0000000, 0xffffffff80000000, 1  );
+  TEST_IMM_OP( 4,  sraiw, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_IMM_OP( 5,  sraiw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_IMM_OP( 6,  sraiw, 0xffffffffffffffff, 0xffffffff80000001, 31 );
+
+  TEST_IMM_OP( 7,  sraiw, 0x000000007fffffff, 0x000000007fffffff, 0  );
+  TEST_IMM_OP( 8,  sraiw, 0x000000003fffffff, 0x000000007fffffff, 1  );
+  TEST_IMM_OP( 9,  sraiw, 0x0000000000ffffff, 0x000000007fffffff, 7  );
+  TEST_IMM_OP( 10, sraiw, 0x000000000001ffff, 0x000000007fffffff, 14 );
+  TEST_IMM_OP( 11, sraiw, 0x0000000000000000, 0x000000007fffffff, 31 );
+
+  TEST_IMM_OP( 12, sraiw, 0xffffffff81818181, 0xffffffff81818181, 0  );
+  TEST_IMM_OP( 13, sraiw, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1  );
+  TEST_IMM_OP( 14, sraiw, 0xffffffffff030303, 0xffffffff81818181, 7  );
+  TEST_IMM_OP( 15, sraiw, 0xfffffffffffe0606, 0xffffffff81818181, 14 );
+  TEST_IMM_OP( 16, sraiw, 0xffffffffffffffff, 0xffffffff81818181, 31 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, sraiw, 0xffffffffff000000, 0xffffffff80000000, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, sraiw, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_IMM_DEST_BYPASS( 19, 1, sraiw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_IMM_DEST_BYPASS( 20, 2, sraiw, 0xffffffffffffffff, 0xffffffff80000001, 31 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, sraiw, 0xffffffffff000000, 0xffffffff80000000, 7 );
+  TEST_IMM_SRC1_BYPASS( 22, 1, sraiw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, sraiw, 0xffffffffffffffff, 0xffffffff80000001, 31 );
+
+  TEST_IMM_ZEROSRC1( 24, sraiw, 0, 31 );
+  TEST_IMM_ZERODEST( 25, sraiw, 31, 28 );
+
+  TEST_IMM_OP( 26, sraiw, 0x0000000000000000, 0x00e0000000000000, 28)
+  TEST_IMM_OP( 27, sraiw, 0xffffffffff000000, 0x00000000f0000000, 4)
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sraw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sraw.S
new file mode 100644
index 0000000..8c234c1
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sraw.S
@@ -0,0 +1,90 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sraw.S
+#-----------------------------------------------------------------------------
+#
+# Test sraw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  sraw, 0xffffffff80000000, 0xffffffff80000000, 0  );
+  TEST_RR_OP( 3,  sraw, 0xffffffffc0000000, 0xffffffff80000000, 1  );
+  TEST_RR_OP( 4,  sraw, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_OP( 5,  sraw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_OP( 6,  sraw, 0xffffffffffffffff, 0xffffffff80000001, 31 );
+
+  TEST_RR_OP( 7,  sraw, 0x000000007fffffff, 0x000000007fffffff, 0  );
+  TEST_RR_OP( 8,  sraw, 0x000000003fffffff, 0x000000007fffffff, 1  );
+  TEST_RR_OP( 9,  sraw, 0x0000000000ffffff, 0x000000007fffffff, 7  );
+  TEST_RR_OP( 10, sraw, 0x000000000001ffff, 0x000000007fffffff, 14 );
+  TEST_RR_OP( 11, sraw, 0x0000000000000000, 0x000000007fffffff, 31 );
+
+  TEST_RR_OP( 12, sraw, 0xffffffff81818181, 0xffffffff81818181, 0  );
+  TEST_RR_OP( 13, sraw, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1  );
+  TEST_RR_OP( 14, sraw, 0xffffffffff030303, 0xffffffff81818181, 7  );
+  TEST_RR_OP( 15, sraw, 0xfffffffffffe0606, 0xffffffff81818181, 14 );
+  TEST_RR_OP( 16, sraw, 0xffffffffffffffff, 0xffffffff81818181, 31 );
+
+  # Verify that shifts only use bottom five bits
+
+  TEST_RR_OP( 17, sraw, 0xffffffff81818181, 0xffffffff81818181, 0xffffffffffffffe0 );
+  TEST_RR_OP( 18, sraw, 0xffffffffc0c0c0c0, 0xffffffff81818181, 0xffffffffffffffe1 );
+  TEST_RR_OP( 19, sraw, 0xffffffffff030303, 0xffffffff81818181, 0xffffffffffffffe7 );
+  TEST_RR_OP( 20, sraw, 0xfffffffffffe0606, 0xffffffff81818181, 0xffffffffffffffee );
+  TEST_RR_OP( 21, sraw, 0xffffffffffffffff, 0xffffffff81818181, 0xffffffffffffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 22, sraw, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC2_EQ_DEST( 23, sraw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC12_EQ_DEST( 24, sraw, 0, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 25, 0, sraw, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_DEST_BYPASS( 26, 1, sraw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_DEST_BYPASS( 27, 2, sraw, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+
+  TEST_RR_SRC12_BYPASS( 28, 0, 0, sraw, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC12_BYPASS( 29, 0, 1, sraw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC12_BYPASS( 30, 0, 2, sraw, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+  TEST_RR_SRC12_BYPASS( 31, 1, 0, sraw, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC12_BYPASS( 32, 1, 1, sraw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC12_BYPASS( 33, 2, 0, sraw, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+
+  TEST_RR_SRC21_BYPASS( 34, 0, 0, sraw, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC21_BYPASS( 35, 0, 1, sraw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC21_BYPASS( 36, 0, 2, sraw, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+  TEST_RR_SRC21_BYPASS( 37, 1, 0, sraw, 0xffffffffff000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC21_BYPASS( 38, 1, 1, sraw, 0xfffffffffffe0000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC21_BYPASS( 39, 2, 0, sraw, 0xffffffffffffffff, 0xffffffff80000000, 31 );
+
+  TEST_RR_ZEROSRC1( 40, sraw, 0, 15 );
+  TEST_RR_ZEROSRC2( 41, sraw, 32, 32 );
+  TEST_RR_ZEROSRC12( 42, sraw, 0 );
+  TEST_RR_ZERODEST( 43, sraw, 1024, 2048 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srl.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srl.S
new file mode 100644
index 0000000..c1e936a
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srl.S
@@ -0,0 +1,93 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# srl.S
+#-----------------------------------------------------------------------------
+#
+# Test srl instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+#define TEST_SRL(n, v, a) \
+  TEST_RR_OP(n, srl, ((v) & ((1 << (__riscv_xlen-1) << 1) - 1)) >> (a), v, a)
+
+  TEST_SRL( 2,  0xffffffff80000000, 0  );
+  TEST_SRL( 3,  0xffffffff80000000, 1  );
+  TEST_SRL( 4,  0xffffffff80000000, 7  );
+  TEST_SRL( 5,  0xffffffff80000000, 14 );
+  TEST_SRL( 6,  0xffffffff80000001, 31 );
+
+  TEST_SRL( 7,  0xffffffffffffffff, 0  );
+  TEST_SRL( 8,  0xffffffffffffffff, 1  );
+  TEST_SRL( 9,  0xffffffffffffffff, 7  );
+  TEST_SRL( 10, 0xffffffffffffffff, 14 );
+  TEST_SRL( 11, 0xffffffffffffffff, 31 );
+
+  TEST_SRL( 12, 0x0000000021212121, 0  );
+  TEST_SRL( 13, 0x0000000021212121, 1  );
+  TEST_SRL( 14, 0x0000000021212121, 7  );
+  TEST_SRL( 15, 0x0000000021212121, 14 );
+  TEST_SRL( 16, 0x0000000021212121, 31 );
+
+  # Verify that shifts only use bottom five bits
+
+  TEST_RR_OP( 17, srl, 0x0000000021212121, 0x0000000021212121, 0xffffffffffffffc0 );
+  TEST_RR_OP( 18, srl, 0x0000000010909090, 0x0000000021212121, 0xffffffffffffffc1 );
+  TEST_RR_OP( 19, srl, 0x0000000000424242, 0x0000000021212121, 0xffffffffffffffc7 );
+  TEST_RR_OP( 20, srl, 0x0000000000008484, 0x0000000021212121, 0xffffffffffffffce );
+  TEST_RR_OP( 21, srl, 0x0000000000000000, 0x0000000021212121, 0xffffffffffffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 22, srl, 0x01000000, 0x80000000, 7  );
+  TEST_RR_SRC2_EQ_DEST( 23, srl, 0x00020000, 0x80000000, 14 );
+  TEST_RR_SRC12_EQ_DEST( 24, srl, 0, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 25, 0, srl, 0x01000000, 0x80000000, 7  );
+  TEST_RR_DEST_BYPASS( 26, 1, srl, 0x00020000, 0x80000000, 14 );
+  TEST_RR_DEST_BYPASS( 27, 2, srl, 0x00000001, 0x80000000, 31 );
+
+  TEST_RR_SRC12_BYPASS( 28, 0, 0, srl, 0x01000000, 0x80000000, 7  );
+  TEST_RR_SRC12_BYPASS( 29, 0, 1, srl, 0x00020000, 0x80000000, 14 );
+  TEST_RR_SRC12_BYPASS( 30, 0, 2, srl, 0x00000001, 0x80000000, 31 );
+  TEST_RR_SRC12_BYPASS( 31, 1, 0, srl, 0x01000000, 0x80000000, 7  );
+  TEST_RR_SRC12_BYPASS( 32, 1, 1, srl, 0x00020000, 0x80000000, 14 );
+  TEST_RR_SRC12_BYPASS( 33, 2, 0, srl, 0x00000001, 0x80000000, 31 );
+
+  TEST_RR_SRC21_BYPASS( 34, 0, 0, srl, 0x01000000, 0x80000000, 7  );
+  TEST_RR_SRC21_BYPASS( 35, 0, 1, srl, 0x00020000, 0x80000000, 14 );
+  TEST_RR_SRC21_BYPASS( 36, 0, 2, srl, 0x00000001, 0x80000000, 31 );
+  TEST_RR_SRC21_BYPASS( 37, 1, 0, srl, 0x01000000, 0x80000000, 7  );
+  TEST_RR_SRC21_BYPASS( 38, 1, 1, srl, 0x00020000, 0x80000000, 14 );
+  TEST_RR_SRC21_BYPASS( 39, 2, 0, srl, 0x00000001, 0x80000000, 31 );
+
+  TEST_RR_ZEROSRC1( 40, srl, 0, 15 );
+  TEST_RR_ZEROSRC2( 41, srl, 32, 32 );
+  TEST_RR_ZEROSRC12( 42, srl, 0 );
+  TEST_RR_ZERODEST( 43, srl, 1024, 2048 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srli.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srli.S
new file mode 100644
index 0000000..88ee8d2
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srli.S
@@ -0,0 +1,71 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# srli.S
+#-----------------------------------------------------------------------------
+#
+# Test srli instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+#define TEST_SRL(n, v, a) \
+  TEST_IMM_OP(n, srli, ((v) & ((1 << (__riscv_xlen-1) << 1) - 1)) >> (a), v, a)
+
+  TEST_SRL( 2,  0xffffffff80000000, 0  );
+  TEST_SRL( 3,  0xffffffff80000000, 1  );
+  TEST_SRL( 4,  0xffffffff80000000, 7  );
+  TEST_SRL( 5,  0xffffffff80000000, 14 );
+  TEST_SRL( 6,  0xffffffff80000001, 31 );
+
+  TEST_SRL( 7,  0xffffffffffffffff, 0  );
+  TEST_SRL( 8,  0xffffffffffffffff, 1  );
+  TEST_SRL( 9,  0xffffffffffffffff, 7  );
+  TEST_SRL( 10, 0xffffffffffffffff, 14 );
+  TEST_SRL( 11, 0xffffffffffffffff, 31 );
+
+  TEST_SRL( 12, 0x0000000021212121, 0  );
+  TEST_SRL( 13, 0x0000000021212121, 1  );
+  TEST_SRL( 14, 0x0000000021212121, 7  );
+  TEST_SRL( 15, 0x0000000021212121, 14 );
+  TEST_SRL( 16, 0x0000000021212121, 31 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, srli, 0x01000000, 0x80000000, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, srli, 0x01000000, 0x80000000, 7  );
+  TEST_IMM_DEST_BYPASS( 19, 1, srli, 0x00020000, 0x80000000, 14 );
+  TEST_IMM_DEST_BYPASS( 20, 2, srli, 0x00000001, 0x80000001, 31 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, srli, 0x01000000, 0x80000000, 7  );
+  TEST_IMM_SRC1_BYPASS( 22, 1, srli, 0x00020000, 0x80000000, 14 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, srli, 0x00000001, 0x80000001, 31 );
+
+  TEST_IMM_ZEROSRC1( 24, srli, 0, 4 );
+  TEST_IMM_ZERODEST( 25, srli, 33, 10 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srliw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srliw.S
new file mode 100644
index 0000000..a8b9fd7
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srliw.S
@@ -0,0 +1,68 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# srliw.S
+#-----------------------------------------------------------------------------
+#
+# Test srliw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2,  srliw, 0xffffffff80000000, 0xffffffff80000000, 0  );
+  TEST_IMM_OP( 3,  srliw, 0x0000000040000000, 0xffffffff80000000, 1  );
+  TEST_IMM_OP( 4,  srliw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_IMM_OP( 5,  srliw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_IMM_OP( 6,  srliw, 0x0000000000000001, 0xffffffff80000001, 31 );
+
+  TEST_IMM_OP( 7,  srliw, 0xffffffffffffffff, 0xffffffffffffffff, 0  );
+  TEST_IMM_OP( 8,  srliw, 0x000000007fffffff, 0xffffffffffffffff, 1  );
+  TEST_IMM_OP( 9,  srliw, 0x0000000001ffffff, 0xffffffffffffffff, 7  );
+  TEST_IMM_OP( 10, srliw, 0x000000000003ffff, 0xffffffffffffffff, 14 );
+  TEST_IMM_OP( 11, srliw, 0x0000000000000001, 0xffffffffffffffff, 31 );
+
+  TEST_IMM_OP( 12, srliw, 0x0000000021212121, 0x0000000021212121, 0  );
+  TEST_IMM_OP( 13, srliw, 0x0000000010909090, 0x0000000021212121, 1  );
+  TEST_IMM_OP( 14, srliw, 0x0000000000424242, 0x0000000021212121, 7  );
+  TEST_IMM_OP( 15, srliw, 0x0000000000008484, 0x0000000021212121, 14 );
+  TEST_IMM_OP( 16, srliw, 0x0000000000000000, 0x0000000021212121, 31 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 17, srliw, 0x0000000001000000, 0xffffffff80000000, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 18, 0, srliw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_IMM_DEST_BYPASS( 19, 1, srliw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_IMM_DEST_BYPASS( 20, 2, srliw, 0x0000000000000001, 0xffffffff80000001, 31 );
+
+  TEST_IMM_SRC1_BYPASS( 21, 0, srliw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_IMM_SRC1_BYPASS( 22, 1, srliw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_IMM_SRC1_BYPASS( 23, 2, srliw, 0x0000000000000001, 0xffffffff80000001, 31 );
+
+  TEST_IMM_ZEROSRC1( 24, srliw, 0, 31 );
+  TEST_IMM_ZERODEST( 25, srliw, 31, 28 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srlw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srlw.S
new file mode 100644
index 0000000..24a492a
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/srlw.S
@@ -0,0 +1,90 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# srlw.S
+#-----------------------------------------------------------------------------
+#
+# Test srlw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  srlw, 0xffffffff80000000, 0xffffffff80000000, 0  );
+  TEST_RR_OP( 3,  srlw, 0x0000000040000000, 0xffffffff80000000, 1  );
+  TEST_RR_OP( 4,  srlw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_RR_OP( 5,  srlw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_RR_OP( 6,  srlw, 0x0000000000000001, 0xffffffff80000001, 31 );
+
+  TEST_RR_OP( 7,  srlw, 0xffffffffffffffff, 0xffffffffffffffff, 0  );
+  TEST_RR_OP( 8,  srlw, 0x000000007fffffff, 0xffffffffffffffff, 1  );
+  TEST_RR_OP( 9,  srlw, 0x0000000001ffffff, 0xffffffffffffffff, 7  );
+  TEST_RR_OP( 10, srlw, 0x000000000003ffff, 0xffffffffffffffff, 14 );
+  TEST_RR_OP( 11, srlw, 0x0000000000000001, 0xffffffffffffffff, 31 );
+
+  TEST_RR_OP( 12, srlw, 0x0000000021212121, 0x0000000021212121, 0  );
+  TEST_RR_OP( 13, srlw, 0x0000000010909090, 0x0000000021212121, 1  );
+  TEST_RR_OP( 14, srlw, 0x0000000000424242, 0x0000000021212121, 7  );
+  TEST_RR_OP( 15, srlw, 0x0000000000008484, 0x0000000021212121, 14 );
+  TEST_RR_OP( 16, srlw, 0x0000000000000000, 0x0000000021212121, 31 );
+
+  # Verify that shifts only use bottom five bits
+
+  TEST_RR_OP( 17, srlw, 0x0000000021212121, 0x0000000021212121, 0xffffffffffffffe0 );
+  TEST_RR_OP( 18, srlw, 0x0000000010909090, 0x0000000021212121, 0xffffffffffffffe1 );
+  TEST_RR_OP( 19, srlw, 0x0000000000424242, 0x0000000021212121, 0xffffffffffffffe7 );
+  TEST_RR_OP( 20, srlw, 0x0000000000008484, 0x0000000021212121, 0xffffffffffffffee );
+  TEST_RR_OP( 21, srlw, 0x0000000000000000, 0x0000000021212121, 0xffffffffffffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 22, srlw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC2_EQ_DEST( 23, srlw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC12_EQ_DEST( 24, srlw, 0, 7 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 25, 0, srlw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_RR_DEST_BYPASS( 26, 1, srlw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_RR_DEST_BYPASS( 27, 2, srlw, 0x0000000000000001, 0xffffffff80000000, 31 );
+
+  TEST_RR_SRC12_BYPASS( 28, 0, 0, srlw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC12_BYPASS( 29, 0, 1, srlw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC12_BYPASS( 30, 0, 2, srlw, 0x0000000000000001, 0xffffffff80000000, 31 );
+  TEST_RR_SRC12_BYPASS( 31, 1, 0, srlw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC12_BYPASS( 32, 1, 1, srlw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC12_BYPASS( 33, 2, 0, srlw, 0x0000000000000001, 0xffffffff80000000, 31 );
+
+  TEST_RR_SRC21_BYPASS( 34, 0, 0, srlw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC21_BYPASS( 35, 0, 1, srlw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC21_BYPASS( 36, 0, 2, srlw, 0x0000000000000001, 0xffffffff80000000, 31 );
+  TEST_RR_SRC21_BYPASS( 37, 1, 0, srlw, 0x0000000001000000, 0xffffffff80000000, 7  );
+  TEST_RR_SRC21_BYPASS( 38, 1, 1, srlw, 0x0000000000020000, 0xffffffff80000000, 14 );
+  TEST_RR_SRC21_BYPASS( 39, 2, 0, srlw, 0x0000000000000001, 0xffffffff80000000, 31 );
+
+  TEST_RR_ZEROSRC1( 40, srlw, 0, 15 );
+  TEST_RR_ZEROSRC2( 41, srlw, 32, 32 );
+  TEST_RR_ZEROSRC12( 42, srlw, 0 );
+  TEST_RR_ZERODEST( 43, srlw, 1024, 2048 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sub.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sub.S
new file mode 100644
index 0000000..005bdea
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sub.S
@@ -0,0 +1,83 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sub.S
+#-----------------------------------------------------------------------------
+#
+# Test sub instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  sub, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 );
+  TEST_RR_OP( 3,  sub, 0x0000000000000000, 0x0000000000000001, 0x0000000000000001 );
+  TEST_RR_OP( 4,  sub, 0xfffffffffffffffc, 0x0000000000000003, 0x0000000000000007 );
+
+  TEST_RR_OP( 5,  sub, 0x0000000000008000, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 6,  sub, 0xffffffff80000000, 0xffffffff80000000, 0x0000000000000000 );
+  TEST_RR_OP( 7,  sub, 0xffffffff80008000, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 8,  sub, 0xffffffffffff8001, 0x0000000000000000, 0x0000000000007fff );
+  TEST_RR_OP( 9,  sub, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 );
+  TEST_RR_OP( 10, sub, 0x000000007fff8000, 0x000000007fffffff, 0x0000000000007fff );
+
+  TEST_RR_OP( 11, sub, 0xffffffff7fff8001, 0xffffffff80000000, 0x0000000000007fff );
+  TEST_RR_OP( 12, sub, 0x0000000080007fff, 0x000000007fffffff, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 13, sub, 0x0000000000000001, 0x0000000000000000, 0xffffffffffffffff );
+  TEST_RR_OP( 14, sub, 0xfffffffffffffffe, 0xffffffffffffffff, 0x0000000000000001 );
+  TEST_RR_OP( 15, sub, 0x0000000000000000, 0xffffffffffffffff, 0xffffffffffffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 16, sub, 2, 13, 11 );
+  TEST_RR_SRC2_EQ_DEST( 17, sub, 3, 14, 11 );
+  TEST_RR_SRC12_EQ_DEST( 18, sub, 0, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 19, 0, sub, 2, 13, 11 );
+  TEST_RR_DEST_BYPASS( 20, 1, sub, 3, 14, 11 );
+  TEST_RR_DEST_BYPASS( 21, 2, sub, 4, 15, 11 );
+
+  TEST_RR_SRC12_BYPASS( 22, 0, 0, sub, 2, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 23, 0, 1, sub, 3, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 24, 0, 2, sub, 4, 15, 11 );
+  TEST_RR_SRC12_BYPASS( 25, 1, 0, sub, 2, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 26, 1, 1, sub, 3, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 27, 2, 0, sub, 4, 15, 11 );
+
+  TEST_RR_SRC21_BYPASS( 28, 0, 0, sub, 2, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 29, 0, 1, sub, 3, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 30, 0, 2, sub, 4, 15, 11 );
+  TEST_RR_SRC21_BYPASS( 31, 1, 0, sub, 2, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 32, 1, 1, sub, 3, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 33, 2, 0, sub, 4, 15, 11 );
+
+  TEST_RR_ZEROSRC1( 34, sub, 15, -15 );
+  TEST_RR_ZEROSRC2( 35, sub, 32, 32 );
+  TEST_RR_ZEROSRC12( 36, sub, 0 );
+  TEST_RR_ZERODEST( 37, sub, 16, 30 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/subw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/subw.S
new file mode 100644
index 0000000..9940d8c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/subw.S
@@ -0,0 +1,83 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# subw.S
+#-----------------------------------------------------------------------------
+#
+# Test subw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  subw, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 );
+  TEST_RR_OP( 3,  subw, 0x0000000000000000, 0x0000000000000001, 0x0000000000000001 );
+  TEST_RR_OP( 4,  subw, 0xfffffffffffffffc, 0x0000000000000003, 0x0000000000000007 );
+
+  TEST_RR_OP( 5,  subw, 0x0000000000008000, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 6,  subw, 0xffffffff80000000, 0xffffffff80000000, 0x0000000000000000 );
+  TEST_RR_OP( 7,  subw, 0xffffffff80008000, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 8,  subw, 0xffffffffffff8001, 0x0000000000000000, 0x0000000000007fff );
+  TEST_RR_OP( 9,  subw, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 );
+  TEST_RR_OP( 10, subw, 0x000000007fff8000, 0x000000007fffffff, 0x0000000000007fff );
+
+  TEST_RR_OP( 11, subw, 0x000000007fff8001, 0xffffffff80000000, 0x0000000000007fff );
+  TEST_RR_OP( 12, subw, 0xffffffff80007fff, 0x000000007fffffff, 0xffffffffffff8000 );
+
+  TEST_RR_OP( 13, subw, 0x0000000000000001, 0x0000000000000000, 0xffffffffffffffff );
+  TEST_RR_OP( 14, subw, 0xfffffffffffffffe, 0xffffffffffffffff, 0x0000000000000001 );
+  TEST_RR_OP( 15, subw, 0x0000000000000000, 0xffffffffffffffff, 0xffffffffffffffff );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 16, subw, 2, 13, 11 );
+  TEST_RR_SRC2_EQ_DEST( 17, subw, 3, 14, 11 );
+  TEST_RR_SRC12_EQ_DEST( 18, subw, 0, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 19, 0, subw, 2, 13, 11 );
+  TEST_RR_DEST_BYPASS( 20, 1, subw, 3, 14, 11 );
+  TEST_RR_DEST_BYPASS( 21, 2, subw, 4, 15, 11 );
+
+  TEST_RR_SRC12_BYPASS( 22, 0, 0, subw, 2, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 23, 0, 1, subw, 3, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 24, 0, 2, subw, 4, 15, 11 );
+  TEST_RR_SRC12_BYPASS( 25, 1, 0, subw, 2, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 26, 1, 1, subw, 3, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 27, 2, 0, subw, 4, 15, 11 );
+
+  TEST_RR_SRC21_BYPASS( 28, 0, 0, subw, 2, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 29, 0, 1, subw, 3, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 30, 0, 2, subw, 4, 15, 11 );
+  TEST_RR_SRC21_BYPASS( 31, 1, 0, subw, 2, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 32, 1, 1, subw, 3, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 33, 2, 0, subw, 4, 15, 11 );
+
+  TEST_RR_ZEROSRC1( 34, subw, 15, -15 );
+  TEST_RR_ZEROSRC2( 35, subw, 32, 32 );
+  TEST_RR_ZEROSRC12( 36, subw, 0 );
+  TEST_RR_ZERODEST( 37, subw, 16, 30 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sw.S
new file mode 100644
index 0000000..ab094b3
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/sw.S
@@ -0,0 +1,92 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# sw.S
+#-----------------------------------------------------------------------------
+#
+# Test sw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Basic tests
+  #-------------------------------------------------------------
+
+  TEST_ST_OP( 2, lw, sw, 0x0000000000aa00aa, 0,  tdat );
+  TEST_ST_OP( 3, lw, sw, 0xffffffffaa00aa00, 4,  tdat );
+  TEST_ST_OP( 4, lw, sw, 0x000000000aa00aa0, 8,  tdat );
+  TEST_ST_OP( 5, lw, sw, 0xffffffffa00aa00a, 12, tdat );
+
+  # Test with negative offset
+
+  TEST_ST_OP( 6, lw, sw, 0x0000000000aa00aa, -12, tdat8 );
+  TEST_ST_OP( 7, lw, sw, 0xffffffffaa00aa00, -8,  tdat8 );
+  TEST_ST_OP( 8, lw, sw, 0x000000000aa00aa0, -4,  tdat8 );
+  TEST_ST_OP( 9, lw, sw, 0xffffffffa00aa00a, 0,   tdat8 );
+
+  # Test with a negative base
+
+  TEST_CASE( 10, x5, 0x12345678, \
+    la  x1, tdat9; \
+    li  x2, 0x12345678; \
+    addi x4, x1, -32; \
+    sw x2, 32(x4); \
+    lw x5, 0(x1); \
+  )
+
+  # Test with unaligned base
+
+  TEST_CASE( 11, x5, 0x58213098, \
+    la  x1, tdat9; \
+    li  x2, 0x58213098; \
+    addi x1, x1, -3; \
+    sw x2, 7(x1); \
+    la  x4, tdat10; \
+    lw x5, 0(x4); \
+  )
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_ST_SRC12_BYPASS( 12, 0, 0, lw, sw, 0xffffffffaabbccdd, 0,  tdat );
+  TEST_ST_SRC12_BYPASS( 13, 0, 1, lw, sw, 0xffffffffdaabbccd, 4,  tdat );
+  TEST_ST_SRC12_BYPASS( 14, 0, 2, lw, sw, 0xffffffffddaabbcc, 8,  tdat );
+  TEST_ST_SRC12_BYPASS( 15, 1, 0, lw, sw, 0xffffffffcddaabbc, 12, tdat );
+  TEST_ST_SRC12_BYPASS( 16, 1, 1, lw, sw, 0xffffffffccddaabb, 16, tdat );
+  TEST_ST_SRC12_BYPASS( 17, 2, 0, lw, sw, 0xffffffffbccddaab, 20, tdat );
+
+  TEST_ST_SRC21_BYPASS( 18, 0, 0, lw, sw, 0x00112233, 0,  tdat );
+  TEST_ST_SRC21_BYPASS( 19, 0, 1, lw, sw, 0x30011223, 4,  tdat );
+  TEST_ST_SRC21_BYPASS( 20, 0, 2, lw, sw, 0x33001122, 8,  tdat );
+  TEST_ST_SRC21_BYPASS( 21, 1, 0, lw, sw, 0x23300112, 12, tdat );
+  TEST_ST_SRC21_BYPASS( 22, 1, 1, lw, sw, 0x22330011, 16, tdat );
+  TEST_ST_SRC21_BYPASS( 23, 2, 0, lw, sw, 0x12233001, 20, tdat );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+tdat:
+tdat1:  .word 0xdeadbeef
+tdat2:  .word 0xdeadbeef
+tdat3:  .word 0xdeadbeef
+tdat4:  .word 0xdeadbeef
+tdat5:  .word 0xdeadbeef
+tdat6:  .word 0xdeadbeef
+tdat7:  .word 0xdeadbeef
+tdat8:  .word 0xdeadbeef
+tdat9:  .word 0xdeadbeef
+tdat10: .word 0xdeadbeef
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/test.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/test.S
new file mode 100644
index 0000000..2bd3306
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/test.S
@@ -0,0 +1,88 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# addi.S
+#-----------------------------------------------------------------------------
+#
+# Test addi instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  li    a2, 100
+  li    a0, 0
+  li    a0, 0
+  li    a0, 0
+  li    a0, 0
+
+loop:
+  addi  a1, a0, 1
+  addi  a1, a0, 1
+  addi  a1, a0, 1
+  addi  a1, a0, 1
+  addi  a1, a0, 1
+  addi  a1, a0, 1
+  addi  a1, a0, 1
+  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+  addi  a2, a2, -1
+  bnez  a2, loop
+
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  mul   a1, a2, a3
+#  mul   a1, a2, a3
+#  mul   a1, a2, a3
+#  mul   a1, a2, a3
+#  mul   a1, a2, a3
+#  mul   a1, a2, a3
+#  mul   a1, a2, a3
+#  mul   a1, a2, a3
+#  mul   a1, a2, a3
+#  mul   a1, a2, a3
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+#  addi  a1, a0, 1
+
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/xor.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/xor.S
new file mode 100644
index 0000000..c4e9552
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/xor.S
@@ -0,0 +1,69 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# xor.S
+#-----------------------------------------------------------------------------
+#
+# Test xor instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Logical tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_OP( 3, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_OP( 4, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
+  TEST_RR_OP( 5, xor, 0x00ff00ff, 0xf00ff00f, 0xf0f0f0f0 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 6, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC2_EQ_DEST( 7, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC12_EQ_DEST( 8, xor, 0x00000000, 0xff00ff00 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 9,  0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_DEST_BYPASS( 10, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_DEST_BYPASS( 11, 2, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
+
+  TEST_RR_SRC12_BYPASS( 12, 0, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC12_BYPASS( 13, 0, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC12_BYPASS( 14, 0, 2, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
+  TEST_RR_SRC12_BYPASS( 15, 1, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC12_BYPASS( 16, 1, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC12_BYPASS( 17, 2, 0, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
+
+  TEST_RR_SRC21_BYPASS( 18, 0, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC21_BYPASS( 19, 0, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC21_BYPASS( 20, 0, 2, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
+  TEST_RR_SRC21_BYPASS( 21, 1, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
+  TEST_RR_SRC21_BYPASS( 22, 1, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
+  TEST_RR_SRC21_BYPASS( 23, 2, 0, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
+
+  TEST_RR_ZEROSRC1( 24, xor, 0xff00ff00, 0xff00ff00 );
+  TEST_RR_ZEROSRC2( 25, xor, 0x00ff00ff, 0x00ff00ff );
+  TEST_RR_ZEROSRC12( 26, xor, 0 );
+  TEST_RR_ZERODEST( 27, xor, 0x11111111, 0x22222222 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64ui/xori.S b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/xori.S
new file mode 100644
index 0000000..eb59d12
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64ui/xori.S
@@ -0,0 +1,55 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# xori.S
+#-----------------------------------------------------------------------------
+#
+# Test xori instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Logical tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_OP( 2, xori, 0xffffffffff00f00f, 0x0000000000ff0f00, 0xf0f );
+  TEST_IMM_OP( 3, xori, 0x000000000ff00f00, 0x000000000ff00ff0, 0x0f0 );
+  TEST_IMM_OP( 4, xori, 0x0000000000ff0ff0, 0x0000000000ff08ff, 0x70f );
+  TEST_IMM_OP( 5, xori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_SRC1_EQ_DEST( 6, xori, 0xffffffffff00f00f, 0xffffffffff00f700, 0x70f );
+
+   #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_IMM_DEST_BYPASS( 7,  0, xori, 0x000000000ff00f00, 0x000000000ff00ff0, 0x0f0 );
+  TEST_IMM_DEST_BYPASS( 8,  1, xori, 0x0000000000ff0ff0, 0x0000000000ff08ff, 0x70f );
+  TEST_IMM_DEST_BYPASS( 9,  2, xori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 );
+
+  TEST_IMM_SRC1_BYPASS( 10, 0, xori, 0x000000000ff00f00, 0x000000000ff00ff0, 0x0f0 );
+  TEST_IMM_SRC1_BYPASS( 11, 1, xori, 0x0000000000ff0ff0, 0x0000000000ff0fff, 0x00f );
+  TEST_IMM_SRC1_BYPASS( 12, 2, xori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 );
+
+  TEST_IMM_ZEROSRC1( 13, xori, 0x0f0, 0x0f0 );
+  TEST_IMM_ZERODEST( 14, xori, 0x00ff00ff, 0x70f );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/Makefrag b/tests/test-progs/asmtest/src/riscv/isa/rv64um/Makefrag
new file mode 100644
index 0000000..64ae738
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/Makefrag
@@ -0,0 +1,14 @@
+#=======================================================================
+# Makefrag for rv64um tests
+#-----------------------------------------------------------------------
+
+rv64um_sc_tests = \
+	div divu divuw divw \
+	mul mulh mulhsu mulhu mulw \
+	rem remu remuw remw \
+
+rv64um_p_tests = $(addprefix rv64um-p-, $(rv64um_sc_tests))
+rv64um_v_tests = $(addprefix rv64um-v-, $(rv64um_sc_tests))
+rv64um_ps_tests = $(addprefix rv64um-ps-, $(rv64um_sc_tests))
+
+spike_tests += $(rv64um_p_tests) $(rv64um_v_tests)
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/div.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/div.S
new file mode 100644
index 0000000..ee21f0c
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/div.S
@@ -0,0 +1,41 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# div.S
+#-----------------------------------------------------------------------------
+#
+# Test div instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, div,  3,  20,   6 );
+  TEST_RR_OP( 3, div, -3, -20,   6 );
+  TEST_RR_OP( 4, div, -3,  20,  -6 );
+  TEST_RR_OP( 5, div,  3, -20,  -6 );
+
+  TEST_RR_OP( 6, div, -1<<63, -1<<63,  1 );
+  TEST_RR_OP( 7, div, -1<<63, -1<<63, -1 );
+
+  TEST_RR_OP( 8, div, -1, -1<<63, 0 );
+  TEST_RR_OP( 9, div, -1,      1, 0 );
+  TEST_RR_OP(10, div, -1,      0, 0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/divu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/divu.S
new file mode 100644
index 0000000..e63fd65
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/divu.S
@@ -0,0 +1,41 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# divu.S
+#-----------------------------------------------------------------------------
+#
+# Test divu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, divu,                   3,  20,   6 );
+  TEST_RR_OP( 3, divu, 3074457345618258599, -20,   6 );
+  TEST_RR_OP( 4, divu,                   0,  20,  -6 );
+  TEST_RR_OP( 5, divu,                   0, -20,  -6 );
+
+  TEST_RR_OP( 6, divu, -1<<63, -1<<63,  1 );
+  TEST_RR_OP( 7, divu,     0,  -1<<63, -1 );
+
+  TEST_RR_OP( 8, divu, -1, -1<<63, 0 );
+  TEST_RR_OP( 9, divu, -1,      1, 0 );
+  TEST_RR_OP(10, divu, -1,      0, 0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/divuw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/divuw.S
new file mode 100644
index 0000000..4c9eee7
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/divuw.S
@@ -0,0 +1,41 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# divuw.S
+#-----------------------------------------------------------------------------
+#
+# Test divuw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, divuw,         3,  20,   6 );
+  TEST_RR_OP( 3, divuw, 715827879, -20 << 32 >> 32,   6 );
+  TEST_RR_OP( 4, divuw,         0,  20,  -6 );
+  TEST_RR_OP( 5, divuw,         0, -20,  -6 );
+
+  TEST_RR_OP( 6, divuw, -1<<31, -1<<31,  1 );
+  TEST_RR_OP( 7, divuw, 0,      -1<<31, -1 );
+
+  TEST_RR_OP( 8, divuw, -1, -1<<31, 0 );
+  TEST_RR_OP( 9, divuw, -1,      1, 0 );
+  TEST_RR_OP(10, divuw, -1,      0, 0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/divw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/divw.S
new file mode 100644
index 0000000..4cffa1a
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/divw.S
@@ -0,0 +1,41 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# divw.S
+#-----------------------------------------------------------------------------
+#
+# Test divw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, divw,  3,  20,   6 );
+  TEST_RR_OP( 3, divw, -3, -20,   6 );
+  TEST_RR_OP( 4, divw, -3,  20,  -6 );
+  TEST_RR_OP( 5, divw,  3, -20,  -6 );
+
+  TEST_RR_OP( 6, divw, -1<<31, -1<<31,  1 );
+  TEST_RR_OP( 7, divw, -1<<31, -1<<31, -1 );
+
+  TEST_RR_OP( 8, divw, -1, -1<<31, 0 );
+  TEST_RR_OP( 9, divw, -1,      1, 0 );
+  TEST_RR_OP(10, divw, -1,      0, 0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/mul.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mul.S
new file mode 100644
index 0000000..c647e97
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mul.S
@@ -0,0 +1,78 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# mul.S
+#-----------------------------------------------------------------------------
+#
+# Test mul instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP(32,  mul, 0x0000000000001200, 0x0000000000007e00, 0x6db6db6db6db6db7 );
+  TEST_RR_OP(33,  mul, 0x0000000000001240, 0x0000000000007fc0, 0x6db6db6db6db6db7 );
+
+  TEST_RR_OP( 2,  mul, 0x00000000, 0x00000000, 0x00000000 );
+  TEST_RR_OP( 3,  mul, 0x00000001, 0x00000001, 0x00000001 );
+  TEST_RR_OP( 4,  mul, 0x00000015, 0x00000003, 0x00000007 );
+
+  TEST_RR_OP( 5,  mul, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 6,  mul, 0x0000000000000000, 0xffffffff80000000, 0x00000000 );
+  TEST_RR_OP( 7,  mul, 0x0000400000000000, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  TEST_RR_OP(30,  mul, 0x000000000000ff7f, 0xaaaaaaaaaaaaaaab, 0x000000000002fe7d );
+  TEST_RR_OP(31,  mul, 0x000000000000ff7f, 0x000000000002fe7d, 0xaaaaaaaaaaaaaaab );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 8, mul, 143, 13, 11 );
+  TEST_RR_SRC2_EQ_DEST( 9, mul, 154, 14, 11 );
+  TEST_RR_SRC12_EQ_DEST( 10, mul, 169, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 11, 0, mul, 143, 13, 11 );
+  TEST_RR_DEST_BYPASS( 12, 1, mul, 154, 14, 11 );
+  TEST_RR_DEST_BYPASS( 13, 2, mul, 165, 15, 11 );
+
+  TEST_RR_SRC12_BYPASS( 14, 0, 0, mul, 143, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 15, 0, 1, mul, 154, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 16, 0, 2, mul, 165, 15, 11 );
+  TEST_RR_SRC12_BYPASS( 17, 1, 0, mul, 143, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 18, 1, 1, mul, 154, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 19, 2, 0, mul, 165, 15, 11 );
+
+  TEST_RR_SRC21_BYPASS( 20, 0, 0, mul, 143, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 21, 0, 1, mul, 154, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 22, 0, 2, mul, 165, 15, 11 );
+  TEST_RR_SRC21_BYPASS( 23, 1, 0, mul, 143, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 24, 1, 1, mul, 154, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 25, 2, 0, mul, 165, 15, 11 );
+
+  TEST_RR_ZEROSRC1( 26, mul, 0, 31 );
+  TEST_RR_ZEROSRC2( 27, mul, 0, 32 );
+  TEST_RR_ZEROSRC12( 28, mul, 0 );
+  TEST_RR_ZERODEST( 29, mul, 33, 34 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulh.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulh.S
new file mode 100644
index 0000000..1fd12a1
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulh.S
@@ -0,0 +1,72 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# mulh.S
+#-----------------------------------------------------------------------------
+#
+# Test mulh instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  mulh, 0x00000000, 0x00000000, 0x00000000 );
+  TEST_RR_OP( 3,  mulh, 0x00000000, 0x00000001, 0x00000001 );
+  TEST_RR_OP( 4,  mulh, 0x00000000, 0x00000003, 0x00000007 );
+
+  TEST_RR_OP( 5,  mulh, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 6,  mulh, 0x0000000000000000, 0xffffffff80000000, 0x00000000 );
+  TEST_RR_OP( 7,  mulh, 0x0000000000000000, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 8, mulh, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC2_EQ_DEST( 9, mulh, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC12_EQ_DEST( 10, mulh, 169, 13<<32 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 11, 0, mulh, 143, 13<<32, 11<<32 );
+  TEST_RR_DEST_BYPASS( 12, 1, mulh, 154, 14<<32, 11<<32 );
+  TEST_RR_DEST_BYPASS( 13, 2, mulh, 165, 15<<32, 11<<32 );
+
+  TEST_RR_SRC12_BYPASS( 14, 0, 0, mulh, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 15, 0, 1, mulh, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 16, 0, 2, mulh, 165, 15<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 17, 1, 0, mulh, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 18, 1, 1, mulh, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 19, 2, 0, mulh, 165, 15<<32, 11<<32 );
+
+  TEST_RR_SRC21_BYPASS( 20, 0, 0, mulh, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 21, 0, 1, mulh, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 22, 0, 2, mulh, 165, 15<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 23, 1, 0, mulh, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 24, 1, 1, mulh, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 25, 2, 0, mulh, 165, 15<<32, 11<<32 );
+
+  TEST_RR_ZEROSRC1( 26, mulh, 0, 31<<32 );
+  TEST_RR_ZEROSRC2( 27, mulh, 0, 32<<32 );
+  TEST_RR_ZEROSRC12( 28, mulh, 0 );
+  TEST_RR_ZERODEST( 29, mulh, 33<<32, 34<<32 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulhsu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulhsu.S
new file mode 100644
index 0000000..c037db2
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulhsu.S
@@ -0,0 +1,72 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# mulhsu.S
+#-----------------------------------------------------------------------------
+#
+# Test mulhsu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  mulhsu, 0x00000000, 0x00000000, 0x00000000 );
+  TEST_RR_OP( 3,  mulhsu, 0x00000000, 0x00000001, 0x00000001 );
+  TEST_RR_OP( 4,  mulhsu, 0x00000000, 0x00000003, 0x00000007 );
+
+  TEST_RR_OP( 5,  mulhsu, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 6,  mulhsu, 0x0000000000000000, 0xffffffff80000000, 0x00000000 );
+  TEST_RR_OP( 7,  mulhsu, 0xffffffff80000000, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 8, mulhsu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC2_EQ_DEST( 9, mulhsu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC12_EQ_DEST( 10, mulhsu, 169, 13<<32 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 11, 0, mulhsu, 143, 13<<32, 11<<32 );
+  TEST_RR_DEST_BYPASS( 12, 1, mulhsu, 154, 14<<32, 11<<32 );
+  TEST_RR_DEST_BYPASS( 13, 2, mulhsu, 165, 15<<32, 11<<32 );
+
+  TEST_RR_SRC12_BYPASS( 14, 0, 0, mulhsu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 15, 0, 1, mulhsu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 16, 0, 2, mulhsu, 165, 15<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 17, 1, 0, mulhsu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 18, 1, 1, mulhsu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 19, 2, 0, mulhsu, 165, 15<<32, 11<<32 );
+
+  TEST_RR_SRC21_BYPASS( 20, 0, 0, mulhsu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 21, 0, 1, mulhsu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 22, 0, 2, mulhsu, 165, 15<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 23, 1, 0, mulhsu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 24, 1, 1, mulhsu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 25, 2, 0, mulhsu, 165, 15<<32, 11<<32 );
+
+  TEST_RR_ZEROSRC1( 26, mulhsu, 0, 31<<32 );
+  TEST_RR_ZEROSRC2( 27, mulhsu, 0, 32<<32 );
+  TEST_RR_ZEROSRC12( 28, mulhsu, 0 );
+  TEST_RR_ZERODEST( 29, mulhsu, 33<<32, 34<<32 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulhu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulhu.S
new file mode 100644
index 0000000..aa7b762
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulhu.S
@@ -0,0 +1,75 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# mulhu.S
+#-----------------------------------------------------------------------------
+#
+# Test mulhu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  mulhu, 0x00000000, 0x00000000, 0x00000000 );
+  TEST_RR_OP( 3,  mulhu, 0x00000000, 0x00000001, 0x00000001 );
+  TEST_RR_OP( 4,  mulhu, 0x00000000, 0x00000003, 0x00000007 );
+
+  TEST_RR_OP( 5,  mulhu, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 6,  mulhu, 0x0000000000000000, 0xffffffff80000000, 0x00000000 );
+  TEST_RR_OP( 7,  mulhu, 0xffffffff7fff8000, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  TEST_RR_OP(30,  mulhu, 0x000000000001fefe, 0xaaaaaaaaaaaaaaab, 0x000000000002fe7d );
+  TEST_RR_OP(31,  mulhu, 0x000000000001fefe, 0x000000000002fe7d, 0xaaaaaaaaaaaaaaab );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 8, mulhu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC2_EQ_DEST( 9, mulhu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC12_EQ_DEST( 10, mulhu, 169, 13<<32 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 11, 0, mulhu, 143, 13<<32, 11<<32 );
+  TEST_RR_DEST_BYPASS( 12, 1, mulhu, 154, 14<<32, 11<<32 );
+  TEST_RR_DEST_BYPASS( 13, 2, mulhu, 165, 15<<32, 11<<32 );
+
+  TEST_RR_SRC12_BYPASS( 14, 0, 0, mulhu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 15, 0, 1, mulhu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 16, 0, 2, mulhu, 165, 15<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 17, 1, 0, mulhu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 18, 1, 1, mulhu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC12_BYPASS( 19, 2, 0, mulhu, 165, 15<<32, 11<<32 );
+
+  TEST_RR_SRC21_BYPASS( 20, 0, 0, mulhu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 21, 0, 1, mulhu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 22, 0, 2, mulhu, 165, 15<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 23, 1, 0, mulhu, 143, 13<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 24, 1, 1, mulhu, 154, 14<<32, 11<<32 );
+  TEST_RR_SRC21_BYPASS( 25, 2, 0, mulhu, 165, 15<<32, 11<<32 );
+
+  TEST_RR_ZEROSRC1( 26, mulhu, 0, 31<<32 );
+  TEST_RR_ZEROSRC2( 27, mulhu, 0, 32<<32 );
+  TEST_RR_ZEROSRC12( 28, mulhu, 0 );
+  TEST_RR_ZERODEST( 29, mulhu, 33<<32, 34<<32 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulw.S
new file mode 100644
index 0000000..379c3f2
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/mulw.S
@@ -0,0 +1,72 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# mulw.S
+#-----------------------------------------------------------------------------
+#
+# Test mulw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2,  mulw, 0x00000000, 0x00000000, 0x00000000 );
+  TEST_RR_OP( 3,  mulw, 0x00000001, 0x00000001, 0x00000001 );
+  TEST_RR_OP( 4,  mulw, 0x00000015, 0x00000003, 0x00000007 );
+
+  TEST_RR_OP( 5,  mulw, 0x0000000000000000, 0x0000000000000000, 0xffffffffffff8000 );
+  TEST_RR_OP( 6,  mulw, 0x0000000000000000, 0xffffffff80000000, 0x00000000 );
+  TEST_RR_OP( 7,  mulw, 0x0000000000000000, 0xffffffff80000000, 0xffffffffffff8000 );
+
+  #-------------------------------------------------------------
+  # Source/Destination tests
+  #-------------------------------------------------------------
+
+  TEST_RR_SRC1_EQ_DEST( 8, mulw, 143, 13, 11 );
+  TEST_RR_SRC2_EQ_DEST( 9, mulw, 154, 14, 11 );
+  TEST_RR_SRC12_EQ_DEST( 10, mulw, 169, 13 );
+
+  #-------------------------------------------------------------
+  # Bypassing tests
+  #-------------------------------------------------------------
+
+  TEST_RR_DEST_BYPASS( 11, 0, mulw, 143, 13, 11 );
+  TEST_RR_DEST_BYPASS( 12, 1, mulw, 154, 14, 11 );
+  TEST_RR_DEST_BYPASS( 13, 2, mulw, 165, 15, 11 );
+
+  TEST_RR_SRC12_BYPASS( 14, 0, 0, mulw, 143, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 15, 0, 1, mulw, 154, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 16, 0, 2, mulw, 165, 15, 11 );
+  TEST_RR_SRC12_BYPASS( 17, 1, 0, mulw, 143, 13, 11 );
+  TEST_RR_SRC12_BYPASS( 18, 1, 1, mulw, 154, 14, 11 );
+  TEST_RR_SRC12_BYPASS( 19, 2, 0, mulw, 165, 15, 11 );
+
+  TEST_RR_SRC21_BYPASS( 20, 0, 0, mulw, 143, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 21, 0, 1, mulw, 154, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 22, 0, 2, mulw, 165, 15, 11 );
+  TEST_RR_SRC21_BYPASS( 23, 1, 0, mulw, 143, 13, 11 );
+  TEST_RR_SRC21_BYPASS( 24, 1, 1, mulw, 154, 14, 11 );
+  TEST_RR_SRC21_BYPASS( 25, 2, 0, mulw, 165, 15, 11 );
+
+  TEST_RR_ZEROSRC1( 26, mulw, 0, 31 );
+  TEST_RR_ZEROSRC2( 27, mulw, 0, 32 );
+  TEST_RR_ZEROSRC12( 28, mulw, 0 );
+  TEST_RR_ZERODEST( 29, mulw, 33, 34 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/rem.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/rem.S
new file mode 100644
index 0000000..e3248ff
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/rem.S
@@ -0,0 +1,41 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# rem.S
+#-----------------------------------------------------------------------------
+#
+# Test rem instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, rem,  2,  20,   6 );
+  TEST_RR_OP( 3, rem, -2, -20,   6 );
+  TEST_RR_OP( 4, rem,  2,  20,  -6 );
+  TEST_RR_OP( 5, rem, -2, -20,  -6 );
+
+  TEST_RR_OP( 6, rem,  0, -1<<63,  1 );
+  TEST_RR_OP( 7, rem,  0, -1<<63, -1 );
+
+  TEST_RR_OP( 8, rem, -1<<63, -1<<63, 0 );
+  TEST_RR_OP( 9, rem,      1,      1, 0 );
+  TEST_RR_OP(10, rem,      0,      0, 0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/remu.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/remu.S
new file mode 100644
index 0000000..6946d0d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/remu.S
@@ -0,0 +1,41 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# remu.S
+#-----------------------------------------------------------------------------
+#
+# Test remu instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, remu,   2,  20,   6 );
+  TEST_RR_OP( 3, remu,   2, -20,   6 );
+  TEST_RR_OP( 4, remu,  20,  20,  -6 );
+  TEST_RR_OP( 5, remu, -20, -20,  -6 );
+
+  TEST_RR_OP( 6, remu,      0, -1<<63,  1 );
+  TEST_RR_OP( 7, remu, -1<<63, -1<<63, -1 );
+
+  TEST_RR_OP( 8, remu, -1<<63, -1<<63, 0 );
+  TEST_RR_OP( 9, remu,      1,      1, 0 );
+  TEST_RR_OP(10, remu,      0,      0, 0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/remuw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/remuw.S
new file mode 100644
index 0000000..334b5c5
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/remuw.S
@@ -0,0 +1,41 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# remuw.S
+#-----------------------------------------------------------------------------
+#
+# Test remuw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, remuw,   2,  20,   6 );
+  TEST_RR_OP( 3, remuw,   2, -20,   6 );
+  TEST_RR_OP( 4, remuw,  20,  20,  -6 );
+  TEST_RR_OP( 5, remuw, -20, -20,  -6 );
+
+  TEST_RR_OP( 6, remuw,      0, -1<<31,  1 );
+  TEST_RR_OP( 7, remuw, -1<<31, -1<<31, -1 );
+
+  TEST_RR_OP( 8, remuw, -1<<31, -1<<31, 0 );
+  TEST_RR_OP( 9, remuw,      1,      1, 0 );
+  TEST_RR_OP(10, remuw,      0,      0, 0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/isa/rv64um/remw.S b/tests/test-progs/asmtest/src/riscv/isa/rv64um/remw.S
new file mode 100644
index 0000000..3ae8e3d
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/isa/rv64um/remw.S
@@ -0,0 +1,42 @@
+# See LICENSE for license details.
+
+#*****************************************************************************
+# remw.S
+#-----------------------------------------------------------------------------
+#
+# Test remw instruction.
+#
+
+#include "riscv_test.h"
+#include "test_macros.h"
+
+RVTEST_RV64U
+RVTEST_CODE_BEGIN
+
+  #-------------------------------------------------------------
+  # Arithmetic tests
+  #-------------------------------------------------------------
+
+  TEST_RR_OP( 2, remw,  2,  20,   6 );
+  TEST_RR_OP( 3, remw, -2, -20,   6 );
+  TEST_RR_OP( 4, remw,  2,  20,  -6 );
+  TEST_RR_OP( 5, remw, -2, -20,  -6 );
+
+  TEST_RR_OP( 6, remw,  0, -1<<31,  1 );
+  TEST_RR_OP( 7, remw,  0, -1<<31, -1 );
+
+  TEST_RR_OP( 8, remw, -1<<31, -1<<31, 0 );
+  TEST_RR_OP( 9, remw,      1,      1, 0 );
+  TEST_RR_OP(10, remw,      0,      0, 0 );
+  TEST_RR_OP(11, remw, 0xfffffffffffff897,0xfffffffffffff897, 0 );
+
+  TEST_PASSFAIL
+
+RVTEST_CODE_END
+
+  .data
+RVTEST_DATA_BEGIN
+
+  TEST_DATA
+
+RVTEST_DATA_END
diff --git a/tests/test-progs/asmtest/src/riscv/run-tests.py b/tests/test-progs/asmtest/src/riscv/run-tests.py
new file mode 100755
index 0000000..53a8476
--- /dev/null
+++ b/tests/test-progs/asmtest/src/riscv/run-tests.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2018, Cornell University
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 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.
+#
+# Neither the name of Cornell 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+#
+# Authors: Tuan Ta
+
+import os
+import sys
+import argparse
+import subprocess
+
+from multiprocessing import Pool
+
+import clusterjob
+from clusterjob import *
+
+#-------------------------------------------------------------------------
+# utility function to run a process
+#-------------------------------------------------------------------------
+def execute(cmd):
+  try:
+    return subprocess.check_output(cmd, shell=True)
+  except subprocess.CalledProcessError, err:
+    print "ERROR: " + err.output
+
+#-------------------------------------------------------------------------
+# Input options
+#-------------------------------------------------------------------------
+
+# general options
+parser = argparse.ArgumentParser(description='run RISC-V assembly tests')
+parser.add_argument('--max-tick',
+                    help = 'maximum simulated tick',
+                    type = int,
+                    default = 10000000000)
+parser.add_argument('--num-cpus',
+                    help = 'number of CPUs\
+                            (some tests require at least 4 CPUs)',
+                    type = int,
+                    default = 4)
+parser.add_argument('--ruby',
+                    help = 'Use Ruby memory?',
+                    action = 'store_true')
+
+args = parser.parse_args()
+
+# convert all paths to absolute paths
+test_dir = os.path.abspath('../../bin/riscv/')
+test_summary_out = './test-summary.out'
+
+#-------------------------------------------------------------------------
+# gem5 variables
+#-------------------------------------------------------------------------
+gem5_dir = os.path.abspath('../../../../../')
+gem5_bin = os.path.join(gem5_dir, 'build', 'RISCV', 'gem5.opt')
+config = os.path.join(gem5_dir, 'configs', 'example', 'se.py')
+
+# list of CPU models to be tested
+cpu_models = ['AtomicSimpleCPU',
+              'TimingSimpleCPU',
+              'MinorCPU',
+              'DerivO3CPU']
+
+# get a list of test binaries in the given directory
+tests = []
+for line in execute("ls %s/*" % (test_dir)).splitlines():
+  if line:
+    tests.append(line.split('/')[-1])
+
+# total number of tests to run
+n_tests = len(tests) * len(cpu_models)
+
+# make a list of jobs
+job_cmds = []
+job_names = []
+for test in tests:
+  for model in cpu_models:
+    test_name = test + '-' + model
+    job_names.append(test_name)
+    job_cmds.append([gem5_bin,
+                     config,
+                     '-m', str(args.max_tick),
+                     '--cpu-type', model,
+                     '-n', str(args.num_cpus),
+                     '-c', test_dir + '/' + test,
+                     '--ruby' if args.ruby else '--caches',
+                    ])
+
+# execute all jobs
+job_pool = Pool(processes = n_tests)
+job_outputs = job_pool.map(subprocess.call, job_cmds)
+job_pool.close()
+
+# process job outputs
+file = open(test_summary_out, "w")
+
+job_outputs = zip(job_names, job_outputs)
+for entry in job_outputs:
+  # a negative return value indicates that the job was terminated
+  # by a signal
+  # a positive return value indicates that the job exited with a return
+  # value
+  if entry[1] < 0:
+    file.write("%-50s failed - signal = %d\n" % (entry[0], -1 * entry[1]))
+  elif entry[1] > 0:
+    file.write("%-50s failed - status = %d\n" % (entry[0], entry[1]))
+  else:
+    file.write("%-50s passed\n" % (entry[0]))
+
+file.close()
diff --git a/util/style/style.py b/util/style/style.py
index 317caa3..0f58590 100644
--- a/util/style/style.py
+++ b/util/style/style.py
@@ -115,6 +115,11 @@
     _re_ignore("^ext/"),
     # Ignore test data, as they are not code
     _re_ignore("^tests/(?:quick|long)/"),
+    # Ignore RISC-V assembly tests as they are maintained in an external
+    # project that does not follow the gem5 coding convention
+    _re_ignore("tests/test-progs/asmtest/src/riscv/"),
+    # Ignore RISC-V assembly dump files
+    _re_ignore("tests/test-progs/asmtest/dump/riscv/")
 ]
 
 def check_ignores(fname):