use crate::riscv64::{reg, csr, Instruction, Riscv64InstructionBuilder};
#[cfg(feature = "std")]
use std::vec;
#[cfg(not(feature = "std"))]
use alloc::vec;
#[cfg(feature = "std")]
use std::process::Command;
#[cfg(feature = "std")]
use std::fs;
#[cfg(feature = "std")]
use crate::common::InstructionBuilder;
#[cfg(feature = "std")]
fn assemble_riscv(assembly: &str) -> Vec<u8> {
use std::io::Write;
let mut asm_file = tempfile::NamedTempFile::new().expect("Failed to create temp assembly file");
writeln!(asm_file, ".section .text").expect("Failed to write section directive");
writeln!(asm_file, ".global _start").expect("Failed to write global directive");
writeln!(asm_file, "_start:").expect("Failed to write label");
write!(asm_file, "{}", assembly).expect("Failed to write assembly");
asm_file.flush().expect("Failed to flush assembly file");
let obj_file = tempfile::NamedTempFile::new().expect("Failed to create temp object file");
let output = Command::new("riscv64-linux-gnu-as")
.args(&["-march=rv64im"])
.arg(asm_file.path())
.arg("-o")
.arg(obj_file.path())
.output();
match output {
Ok(result) => {
if !result.status.success() {
println!("Warning: GNU assembler (riscv64-linux-gnu-as) failed, skipping comparison test: {}",
String::from_utf8_lossy(&result.stderr));
return vec![];
}
}
Err(e) => {
println!("Warning: GNU assembler (riscv64-linux-gnu-as) not available, skipping comparison test: {}", e);
return vec![];
}
}
if let Ok(metadata) = fs::metadata(obj_file.path()) {
if metadata.len() == 0 {
println!("Warning: GNU assembler produced empty object file, skipping comparison test");
return vec![];
}
}
let bin_file = tempfile::NamedTempFile::new().expect("Failed to create temp binary file");
let objcopy_result = Command::new("riscv64-linux-gnu-objcopy")
.arg("-O")
.arg("binary")
.arg("--only-section=.text")
.arg(obj_file.path())
.arg(bin_file.path())
.output()
.expect("Failed to run objcopy");
if !objcopy_result.status.success() {
println!("Warning: objcopy failed, skipping comparison test: {}",
String::from_utf8_lossy(&objcopy_result.stderr));
return vec![];
}
match fs::read(bin_file.path()) {
Ok(data) => data,
Err(e) => {
println!("Warning: Failed to read binary file, skipping comparison test: {}", e);
vec![]
}
}
}
#[cfg(feature = "std")]
fn compare_instruction(jit_instr: Instruction, gnu_assembly: &str) {
let jit_bytes = jit_instr.bytes();
let gnu_bytes = assemble_riscv(gnu_assembly);
if gnu_bytes.is_empty() {
return;
}
assert_eq!(jit_bytes.len(), 4, "JIT instruction should be 4 bytes");
assert!(gnu_bytes.len() >= 4, "GNU assembler output should be at least 4 bytes");
assert_eq!(
jit_bytes,
&gnu_bytes[0..4],
"JIT assembler output does not match GNU assembler output\nJIT: {:02x?}\nGNU: {:02x?}\nAssembly: {}",
jit_bytes,
&gnu_bytes[0..4],
gnu_assembly
);
}
#[test]
fn test_csr_instructions() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X1, csr::MSTATUS, reg::X2);
builder.csrrs(reg::X3, csr::MEPC, reg::X4);
builder.csrrwi(reg::X5, csr::MTVEC, 0x10);
builder.csrr(reg::X6, csr::MHARTID);
builder.csrw(csr::MEPC, reg::X7);
builder.csrs(csr::MIE, reg::X8);
builder.csrc(csr::MIP, reg::X9);
builder.csrwi(csr::MTVEC, 0x20);
builder.csrsi(csr::MIE, 0x08);
builder.csrci(csr::MIP, 0x04);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 10);
assert!(instructions[0].value() != 0);
}
#[test]
fn test_comprehensive_csr_support() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X1, csr::MSTATUS); builder.csrr(reg::X2, csr::MISA); builder.csrr(reg::X3, csr::MIE); builder.csrr(reg::X4, csr::MTVEC); builder.csrr(reg::X5, csr::MSCRATCH); builder.csrr(reg::X6, csr::MEPC); builder.csrr(reg::X7, csr::MCAUSE); builder.csrr(reg::X8, csr::MTVAL); builder.csrr(reg::X9, csr::MIP); builder.csrr(reg::X10, csr::MHARTID);
builder.csrr(reg::X11, csr::SSTATUS); builder.csrr(reg::X12, csr::SIE); builder.csrr(reg::X13, csr::STVEC); builder.csrr(reg::X14, csr::SSCRATCH); builder.csrr(reg::X15, csr::SEPC); builder.csrr(reg::X16, csr::SCAUSE); builder.csrr(reg::X17, csr::STVAL); builder.csrr(reg::X18, csr::SIP);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 18);
for (i, instr) in instructions.iter().enumerate() {
assert!(instr.value() != 0, "Instruction {} should be non-zero", i);
}
}
#[test]
fn test_csr_write_operations() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X1, csr::MSTATUS, reg::X2);
builder.csrrw(reg::X3, csr::SSTATUS, reg::X4);
builder.csrrs(reg::X5, csr::MIE, reg::X6);
builder.csrrs(reg::X7, csr::SIE, reg::X8);
builder.csrrc(reg::X9, csr::MTVEC, reg::X10);
builder.csrrc(reg::X11, csr::STVEC, reg::X12);
builder.csrrwi(reg::X13, csr::MSCRATCH, 0x1f);
builder.csrrwi(reg::X14, csr::SSCRATCH, 0x0f);
builder.csrrsi(reg::X15, csr::MEPC, 0x10);
builder.csrrsi(reg::X16, csr::SEPC, 0x08);
builder.csrrci(reg::X17, csr::MCAUSE, 0x04);
builder.csrrci(reg::X18, csr::SCAUSE, 0x02);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 12);
for instr in instructions {
assert!(instr.value() != 0);
}
}
#[test]
fn test_csr_addresses() {
assert_eq!(csr::MSTATUS.value(), 0x300);
assert_eq!(csr::MISA.value(), 0x301);
assert_eq!(csr::MIE.value(), 0x304);
assert_eq!(csr::MTVEC.value(), 0x305);
assert_eq!(csr::MSCRATCH.value(), 0x340);
assert_eq!(csr::MEPC.value(), 0x341);
assert_eq!(csr::MCAUSE.value(), 0x342);
assert_eq!(csr::MTVAL.value(), 0x343);
assert_eq!(csr::MIP.value(), 0x344);
assert_eq!(csr::MHARTID.value(), 0xf14);
assert_eq!(csr::SSTATUS.value(), 0x100);
assert_eq!(csr::SIE.value(), 0x104);
assert_eq!(csr::STVEC.value(), 0x105);
assert_eq!(csr::SSCRATCH.value(), 0x140);
assert_eq!(csr::SEPC.value(), 0x141);
assert_eq!(csr::SCAUSE.value(), 0x142);
assert_eq!(csr::STVAL.value(), 0x143);
assert_eq!(csr::SIP.value(), 0x144);
}
#[test]
fn test_csr_with_macro() {
let instructions = crate::riscv64_asm! {
csrr(reg::T0, csr::MSTATUS); csrr(reg::T1, csr::MISA); csrrw(reg::T2, csr::MTVEC, reg::T0); csrrs(reg::T3, csr::MIE, reg::ZERO);
csrr(reg::T4, csr::SSTATUS); csrr(reg::T5, csr::STVEC); csrrw(reg::T6, csr::SSCRATCH, reg::T4); csrrs(reg::A0, csr::SIE, reg::ZERO);
csrrwi(reg::A1, csr::SEPC, 0x10); csrrsi(reg::A2, csr::SCAUSE, 0x08); csrrci(reg::A3, csr::SIP, 0x04); };
assert_eq!(instructions.len(), 11);
for (i, instr) in instructions.iter().enumerate() {
assert!(instr.value() != 0, "Instruction {} should be non-zero", i);
}
}
#[test]
fn test_csr_encoding_verification() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X1, csr::SSTATUS); builder.csrr(reg::X2, csr::MSTATUS); builder.csrr(reg::X3, csr::SEPC); builder.csrr(reg::X4, csr::MHARTID);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 4);
let sstatus_csr = (instructions[0].value() >> 20) & 0xfff;
let mstatus_csr = (instructions[1].value() >> 20) & 0xfff;
let sepc_csr = (instructions[2].value() >> 20) & 0xfff;
let mhartid_csr = (instructions[3].value() >> 20) & 0xfff;
assert_eq!(sstatus_csr, 0x100, "SSTATUS CSR address should be 0x100");
assert_eq!(mstatus_csr, 0x300, "MSTATUS CSR address should be 0x300");
assert_eq!(sepc_csr, 0x141, "SEPC CSR address should be 0x141");
assert_eq!(mhartid_csr, 0xf14, "MHARTID CSR address should be 0xf14");
}
#[test]
fn test_issue_requested_csrs() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X1, csr::MSCRATCH);
builder.csrr(reg::X2, csr::MHARTID);
builder.csrr(reg::X3, csr::MISA);
builder.csrr(reg::X4, csr::MSTATUS);
builder.csrr(reg::X5, csr::MIE);
builder.csrr(reg::X6, csr::MIP);
builder.csrr(reg::X7, csr::MTVEC);
builder.csrr(reg::X8, csr::MCAUSE);
builder.csrr(reg::X9, csr::MEPC);
builder.csrr(reg::X10, csr::MTVAL);
builder.csrr(reg::X11, csr::SSCRATCH);
builder.csrr(reg::X12, csr::SSTATUS);
builder.csrr(reg::X13, csr::SIE);
builder.csrr(reg::X14, csr::SIP);
builder.csrr(reg::X15, csr::STVEC);
builder.csrr(reg::X16, csr::SCAUSE);
builder.csrr(reg::X17, csr::SEPC);
builder.csrr(reg::X18, csr::STVAL);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 18, "Should have 18 CSR instructions (10 M-mode + 8 S-mode)");
for (i, instr) in instructions.iter().enumerate() {
assert!(instr.value() != 0, "Instruction {} should be non-zero", i);
}
let mut builder2 = Riscv64InstructionBuilder::new();
builder2.csrrw(reg::A0, csr::MSCRATCH, reg::A1);
builder2.csrrw(reg::A2, csr::SSCRATCH, reg::A3);
builder2.csrrsi(reg::A4, csr::MSTATUS, 0x08);
builder2.csrrci(reg::A5, csr::SSTATUS, 0x02);
let write_instructions = builder2.instructions();
assert_eq!(write_instructions.len(), 4);
for instr in write_instructions {
assert!(instr.value() != 0, "Write instruction should be non-zero");
}
}
#[test]
fn test_arithmetic_instructions() {
let mut builder = Riscv64InstructionBuilder::new();
builder.addi(reg::X1, reg::X2, 100);
builder.add(reg::X3, reg::X1, reg::X2);
builder.sub(reg::X4, reg::X3, reg::X1);
builder.andi(reg::X5, reg::X1, 0xFF); builder.ori(reg::X6, reg::X1, 0x100); builder.xori(reg::X7, reg::X1, 0x200); builder.slti(reg::X8, reg::X1, 50); builder.sltiu(reg::X9, reg::X1, 200); builder.lbu(reg::X10, reg::X2, 0); builder.lhu(reg::X11, reg::X2, 0); builder.lwu(reg::X12, reg::X2, 0); builder.slt(reg::X13, reg::X1, reg::X2); builder.sltu(reg::X14, reg::X1, reg::X2);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 13);
}
#[test]
fn test_m_extension_instructions() {
let mut builder = Riscv64InstructionBuilder::new();
builder.mul(reg::X1, reg::X2, reg::X3); builder.mulh(reg::X4, reg::X5, reg::X6); builder.mulhsu(reg::X7, reg::X8, reg::X9); builder.mulhu(reg::X10, reg::X11, reg::X12);
builder.div(reg::X13, reg::X14, reg::X15); builder.divu(reg::X16, reg::X17, reg::X18);
builder.rem(reg::X19, reg::X20, reg::X21); builder.remu(reg::X22, reg::X23, reg::X24);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 8);
for instr in instructions.iter() {
assert_eq!(instr.size(), 4); assert!(!instr.is_compressed());
}
}
#[cfg(feature = "std")]
#[test]
fn test_m_extension_binary_correctness() {
let mut builder = Riscv64InstructionBuilder::new();
builder.mul(reg::X1, reg::X2, reg::X3);
let instructions = builder.instructions();
let bytes = instructions.to_bytes();
let expected_mul = vec![0xB3, 0x00, 0x31, 0x02]; assert_eq!(bytes, expected_mul);
let mut builder2 = Riscv64InstructionBuilder::new();
builder2.div(reg::X4, reg::X5, reg::X6);
let instructions2 = builder2.instructions();
let bytes2 = instructions2.to_bytes();
let expected_div = vec![0x33, 0xC2, 0x62, 0x02]; assert_eq!(bytes2, expected_div);
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_m_extension() {
let mut builder = Riscv64InstructionBuilder::new();
builder.mul(reg::X1, reg::X2, reg::X3);
let instructions = builder.instructions();
compare_instruction(instructions[0], "mul x1, x2, x3\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.mulh(reg::X4, reg::X5, reg::X6);
let instructions = builder.instructions();
compare_instruction(instructions[0], "mulh x4, x5, x6\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.mulhsu(reg::X7, reg::X8, reg::X9);
let instructions = builder.instructions();
compare_instruction(instructions[0], "mulhsu x7, x8, x9\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.mulhu(reg::X10, reg::X11, reg::X12);
let instructions = builder.instructions();
compare_instruction(instructions[0], "mulhu x10, x11, x12\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.div(reg::X13, reg::X14, reg::X15);
let instructions = builder.instructions();
compare_instruction(instructions[0], "div x13, x14, x15\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.divu(reg::X16, reg::X17, reg::X18);
let instructions = builder.instructions();
compare_instruction(instructions[0], "divu x16, x17, x18\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.rem(reg::X19, reg::X20, reg::X21);
let instructions = builder.instructions();
compare_instruction(instructions[0], "rem x19, x20, x21\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.remu(reg::X22, reg::X23, reg::X24);
let instructions = builder.instructions();
compare_instruction(instructions[0], "remu x22, x23, x24\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_m_extension() {
let mut builder = Riscv64InstructionBuilder::new();
builder.mul(reg::X1, reg::X2, reg::X3);
builder.div(reg::X4, reg::X1, reg::X2);
builder.rem(reg::X5, reg::X4, reg::X3);
builder.mulh(reg::X6, reg::X5, reg::X4);
let instructions = builder.instructions();
let assembly = r"
mul x1, x2, x3
div x4, x1, x2
rem x5, x4, x3
mulh x6, x5, x4
";
compare_instructions(&instructions, assembly);
}
#[test]
fn test_instruction_encoding() {
let instr = Instruction::Standard(0x12345678);
assert_eq!(instr.value(), 0x12345678);
assert_eq!(instr.size(), 4);
assert!(!instr.is_compressed());
let bytes = instr.bytes();
assert_eq!(bytes, vec![0x78, 0x56, 0x34, 0x12]); }
#[test]
fn test_compressed_instruction() {
let instr = Instruction::Compressed(0x1234);
assert_eq!(instr.value(), 0x1234);
assert_eq!(instr.size(), 2);
assert!(instr.is_compressed());
let bytes = instr.bytes();
assert_eq!(bytes, vec![0x34, 0x12]); }
#[test]
fn test_method_chaining() {
let mut builder = Riscv64InstructionBuilder::new();
builder
.csrrw(reg::X1, csr::MSTATUS, reg::X2)
.addi(reg::X3, reg::X1, 100)
.add(reg::X4, reg::X1, reg::X2)
.sub(reg::X5, reg::X4, reg::X3);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 4);
let mut builder2 = Riscv64InstructionBuilder::new();
let instructions2 = builder2
.csrrs(reg::X10, csr::MEPC, reg::X0) .addi(reg::X11, reg::X10, 42)
.instructions();
assert_eq!(instructions2.len(), 2);
}
#[test]
fn test_register_aliases() {
assert_eq!(reg::ZERO.value(), 0);
assert_eq!(reg::RA.value(), 1);
assert_eq!(reg::SP.value(), 2);
assert_eq!(reg::GP.value(), 3);
assert_eq!(reg::TP.value(), 4);
assert_eq!(reg::T0.value(), 5);
assert_eq!(reg::T1.value(), 6);
assert_eq!(reg::T2.value(), 7);
assert_eq!(reg::S0.value(), 8);
assert_eq!(reg::FP.value(), 8); assert_eq!(reg::S1.value(), 9);
assert_eq!(reg::A0.value(), 10);
assert_eq!(reg::A1.value(), 11);
assert_eq!(reg::A2.value(), 12);
assert_eq!(reg::A3.value(), 13);
assert_eq!(reg::A4.value(), 14);
assert_eq!(reg::A5.value(), 15);
assert_eq!(reg::A6.value(), 16);
assert_eq!(reg::A7.value(), 17);
assert_eq!(reg::S2.value(), 18);
assert_eq!(reg::S3.value(), 19);
assert_eq!(reg::S4.value(), 20);
assert_eq!(reg::S5.value(), 21);
assert_eq!(reg::S6.value(), 22);
assert_eq!(reg::S7.value(), 23);
assert_eq!(reg::S8.value(), 24);
assert_eq!(reg::S9.value(), 25);
assert_eq!(reg::S10.value(), 26);
assert_eq!(reg::S11.value(), 27);
assert_eq!(reg::T3.value(), 28);
assert_eq!(reg::T4.value(), 29);
assert_eq!(reg::T5.value(), 30);
assert_eq!(reg::T6.value(), 31);
}
#[test]
fn test_register_aliases_usage() {
let mut builder = Riscv64InstructionBuilder::new();
builder
.addi(reg::A0, reg::ZERO, 42) .add(reg::A1, reg::A0, reg::SP) .sub(reg::T0, reg::A1, reg::A0);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 3);
let mut builder2 = Riscv64InstructionBuilder::new();
builder2
.addi(reg::X10, reg::X0, 42) .add(reg::X11, reg::X10, reg::X2) .sub(reg::X5, reg::X11, reg::X10);
let instructions2 = builder2.instructions();
assert_eq!(instructions, instructions2);
}
#[test]
fn test_ret_instruction() {
let mut builder = Riscv64InstructionBuilder::new();
builder.ret();
let instructions = builder.instructions();
assert_eq!(instructions.len(), 1);
let mut builder2 = Riscv64InstructionBuilder::new();
builder2.jalr(reg::X0, reg::X1, 0);
let instructions2 = builder2.instructions();
assert_eq!(instructions, instructions2);
}
#[test]
fn test_ret_instruction_with_aliases() {
let mut builder = Riscv64InstructionBuilder::new();
builder.ret();
let instructions = builder.instructions();
assert_eq!(instructions.len(), 1);
let mut builder2 = Riscv64InstructionBuilder::new();
builder2.jalr(reg::ZERO, reg::RA, 0);
let instructions2 = builder2.instructions();
assert_eq!(instructions, instructions2);
}
#[test]
fn test_privileged_instructions() {
let mut builder = Riscv64InstructionBuilder::new();
builder.sret(); builder.mret(); builder.ecall(); builder.ebreak(); builder.wfi();
let instructions = builder.instructions();
assert_eq!(instructions.len(), 5);
for instr in instructions {
assert!(instr.value() != 0);
}
}
#[test]
fn test_aliases_with_macro() {
let instructions = crate::riscv64_asm! {
addi(reg::A0, reg::ZERO, 42); add(reg::A1, reg::A0, reg::SP); sub(reg::T0, reg::A1, reg::A0); ret(); };
assert_eq!(instructions.len(), 4);
let builder_instructions = Riscv64InstructionBuilder::new()
.addi(reg::A0, reg::ZERO, 42)
.add(reg::A1, reg::A0, reg::SP)
.sub(reg::T0, reg::A1, reg::A0)
.ret()
.instructions()
.to_vec();
assert_eq!(instructions, builder_instructions);
}
#[test]
fn test_comprehensive_alias_demo() {
println!("Testing RISC-V register aliases and ret instruction...\n");
println!("Register alias mappings:");
println!(" a0 = x{}", reg::A0.value());
println!(" sp = x{}", reg::SP.value());
println!(" ra = x{}", reg::RA.value());
println!(" zero = x{}", reg::ZERO.value());
println!(" t0 = x{}", reg::T0.value());
println!();
let instructions = crate::riscv64_asm! {
addi(reg::SP, reg::SP, -16); sd(reg::RA, reg::SP, 8); sd(reg::S0, reg::SP, 0); addi(reg::S0, reg::SP, 16);
addi(reg::A0, reg::ZERO, 42);
ld(reg::S0, reg::SP, 0); ld(reg::RA, reg::SP, 8); addi(reg::SP, reg::SP, 16); ret(); };
assert_eq!(instructions.len(), 9);
println!("Generated {} instructions using aliases", instructions.len());
for (i, instr) in instructions.iter().enumerate() {
println!(" {}: {}", i, instr);
}
}
#[test]
fn test_macro_chaining() {
let instructions = crate::riscv64_asm! {
addi(reg::X1, reg::X0, 10);
add(reg::X2, reg::X1, reg::X0);
csrrw(reg::X3, csr::MSTATUS, reg::X2);
};
assert_eq!(instructions.len(), 3);
let builder_instructions = Riscv64InstructionBuilder::new()
.addi(reg::X1, reg::X0, 10)
.add(reg::X2, reg::X1, reg::X0)
.csrrw(reg::X3, csr::MSTATUS, reg::X2)
.instructions()
.to_vec();
assert_eq!(instructions, builder_instructions);
}
#[test]
fn test_macro_comprehensive() {
let instructions = crate::riscv64_asm! {
lui(reg::X1, 0x12345);
addi(reg::X2, reg::X1, 100);
add(reg::X3, reg::X1, reg::X2);
beq(reg::X1, reg::X2, 8);
jal(reg::X1, 16);
csrr(reg::X4, csr::MSTATUS);
};
assert_eq!(instructions.len(), 6);
let builder_instructions = Riscv64InstructionBuilder::new()
.lui(reg::X1, 0x12345)
.addi(reg::X2, reg::X1, 100)
.add(reg::X3, reg::X1, reg::X2)
.beq(reg::X1, reg::X2, 8)
.jal(reg::X1, 16)
.csrrs(reg::X4, csr::MSTATUS, reg::X0) .instructions()
.to_vec();
assert_eq!(instructions, builder_instructions);
for instr in &instructions {
assert!(instr.value() != 0);
}
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_arithmetic() {
let mut builder = Riscv64InstructionBuilder::new();
builder.addi(reg::X1, reg::X0, 100);
let instructions = builder.instructions();
compare_instruction(instructions[0], "addi x1, x0, 100\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.add(reg::X3, reg::X1, reg::X2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "add x3, x1, x2\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.sub(reg::X4, reg::X3, reg::X1);
let instructions = builder.instructions();
compare_instruction(instructions[0], "sub x4, x3, x1\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_immediate_arithmetic() {
let test_cases = vec![
(0, "addi x1, x0, 0\n"),
(1, "addi x1, x0, 1\n"),
(-1, "addi x1, x0, -1\n"),
(100, "addi x1, x0, 100\n"),
(-100, "addi x1, x0, -100\n"),
(2047, "addi x1, x0, 2047\n"), (-2048, "addi x1, x0, -2048\n"), ];
for (imm, assembly) in test_cases {
let mut builder = Riscv64InstructionBuilder::new();
builder.addi(reg::X1, reg::X0, imm);
let instructions = builder.instructions();
compare_instruction(instructions[0], assembly);
}
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_logical() {
let mut builder = Riscv64InstructionBuilder::new();
builder.xor(reg::X5, reg::X1, reg::X2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "xor x5, x1, x2\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.or(reg::X6, reg::X3, reg::X4);
let instructions = builder.instructions();
compare_instruction(instructions[0], "or x6, x3, x4\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.and(reg::X7, reg::X5, reg::X6);
let instructions = builder.instructions();
compare_instruction(instructions[0], "and x7, x5, x6\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.andi(reg::X8, reg::X1, 0xFF);
let instructions = builder.instructions();
compare_instruction(instructions[0], "andi x8, x1, 255\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.ori(reg::X9, reg::X2, 0x100);
let instructions = builder.instructions();
compare_instruction(instructions[0], "ori x9, x2, 256\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.xori(reg::X10, reg::X3, 0x200);
let instructions = builder.instructions();
compare_instruction(instructions[0], "xori x10, x3, 512\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.slti(reg::X11, reg::X4, 50);
let instructions = builder.instructions();
compare_instruction(instructions[0], "slti x11, x4, 50\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.sltiu(reg::X12, reg::X5, 200);
let instructions = builder.instructions();
compare_instruction(instructions[0], "sltiu x12, x5, 200\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.slt(reg::X13, reg::X6, reg::X7);
let instructions = builder.instructions();
compare_instruction(instructions[0], "slt x13, x6, x7\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.sltu(reg::X14, reg::X8, reg::X9);
let instructions = builder.instructions();
compare_instruction(instructions[0], "sltu x14, x8, x9\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_shifts() {
let mut builder = Riscv64InstructionBuilder::new();
builder.sll(reg::X8, reg::X1, reg::X2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "sll x8, x1, x2\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.srl(reg::X9, reg::X3, reg::X4);
let instructions = builder.instructions();
compare_instruction(instructions[0], "srl x9, x3, x4\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.sra(reg::X10, reg::X5, reg::X6);
let instructions = builder.instructions();
compare_instruction(instructions[0], "sra x10, x5, x6\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.slli(reg::X11, reg::X1, 5);
let instructions = builder.instructions();
compare_instruction(instructions[0], "slli x11, x1, 5\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.srli(reg::X12, reg::X2, 10);
let instructions = builder.instructions();
compare_instruction(instructions[0], "srli x12, x2, 10\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.srai(reg::X13, reg::X3, 15);
let instructions = builder.instructions();
compare_instruction(instructions[0], "srai x13, x3, 15\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_upper_immediate() {
let mut builder = Riscv64InstructionBuilder::new();
builder.lui(reg::X1, 0x12345);
let instructions = builder.instructions();
compare_instruction(instructions[0], "lui x1, 0x12345\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.auipc(reg::X2, 0x6789A);
let instructions = builder.instructions();
compare_instruction(instructions[0], "auipc x2, 0x6789A\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_csr() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X1, csr::MSTATUS, reg::X2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrrw x1, mstatus, x2\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrs(reg::X3, csr::MEPC, reg::X4);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrrs x3, mepc, x4\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrwi(reg::X5, csr::MTVEC, 0x10);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrrwi x5, mtvec, 0x10\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X4, csr::MSTATUS);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrr x4, mstatus\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrw(csr::MEPC, reg::X1);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrw mepc, x1\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrs(csr::MIE, reg::X2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrs mie, x2\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrc(csr::MIP, reg::X3);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrc mip, x3\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrwi(csr::MTVEC, 0x8);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrwi mtvec, 0x8\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrsi(csr::MIE, 0x4);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrsi mie, 0x4\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrci(csr::MIP, 0x2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrci mip, 0x2\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_s_mode_csrs() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X1, csr::SSTATUS);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrr x1, sstatus\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X2, csr::SIE);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrr x2, sie\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X3, csr::STVEC);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrr x3, stvec\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X4, csr::SSCRATCH);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrr x4, sscratch\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X5, csr::SEPC);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrr x5, sepc\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X6, csr::SCAUSE);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrr x6, scause\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X7, csr::STVAL);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrr x7, stval\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X8, csr::SIP);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrr x8, sip\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_s_mode_csr_write_operations() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X1, csr::SSTATUS, reg::X2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrrw x1, sstatus, x2\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrs(reg::X3, csr::SIE, reg::X4);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrrs x3, sie, x4\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrc(reg::X5, csr::STVEC, reg::X6);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrrc x5, stvec, x6\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrwi(reg::X7, csr::SSCRATCH, 0x1f);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrrwi x7, sscratch, 0x1f\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrsi(reg::X8, csr::SEPC, 0x10);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrrsi x8, sepc, 0x10\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrci(reg::X9, csr::SIP, 0x08);
let instructions = builder.instructions();
compare_instruction(instructions[0], "csrrci x9, sip, 0x08\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_privileged() {
let mut builder = Riscv64InstructionBuilder::new();
builder.sret();
let instructions = builder.instructions();
compare_instruction(instructions[0], "sret\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.mret();
let instructions = builder.instructions();
compare_instruction(instructions[0], "mret\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.ecall();
let instructions = builder.instructions();
compare_instruction(instructions[0], "ecall\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.ebreak();
let instructions = builder.instructions();
compare_instruction(instructions[0], "ebreak\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.wfi();
let instructions = builder.instructions();
compare_instruction(instructions[0], "wfi\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_branches() {
let mut builder = Riscv64InstructionBuilder::new();
builder.beq(reg::X1, reg::X2, 0);
let instructions = builder.instructions();
compare_instruction(instructions[0], "beq x1, x2, .\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.bne(reg::X3, reg::X4, 0);
let instructions = builder.instructions();
compare_instruction(instructions[0], "bne x3, x4, .\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.blt(reg::X5, reg::X6, 0);
let instructions = builder.instructions();
compare_instruction(instructions[0], "blt x5, x6, .\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.bge(reg::X7, reg::X8, 0);
let instructions = builder.instructions();
compare_instruction(instructions[0], "bge x7, x8, .\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.bltu(reg::X9, reg::X10, 0);
let instructions = builder.instructions();
compare_instruction(instructions[0], "bltu x9, x10, .\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.bgeu(reg::X11, reg::X12, 0);
let instructions = builder.instructions();
compare_instruction(instructions[0], "bgeu x11, x12, .\n");
}
#[cfg(feature = "std")]
#[test]
fn test_jump_instructions_comprehensive() {
let test_cases = vec![
(0, "jal x1, ."), (4, "jal x1, .+4"), (100, "jal x1, .+100"), (1000, "jal x1, .+1000"), (-4, "jal x1, .-4"), (-100, "jal x1, .-100"), (-1000, "jal x1, .-1000"), ];
for (imm, assembly) in test_cases {
let mut builder = Riscv64InstructionBuilder::new();
builder.jal(reg::X1, imm);
let instructions = builder.instructions();
compare_instruction(instructions[0], &format!("{}\n", assembly));
}
let jalr_test_cases = vec![
(0, "jalr x0, x1, 0"), (4, "jalr x0, x1, 4"), (100, "jalr x0, x1, 100"), (1000, "jalr x0, x1, 1000"), (-4, "jalr x0, x1, -4"), (-100, "jalr x0, x1, -100"), (-1000, "jalr x0, x1, -1000"), ];
for (imm, assembly) in jalr_test_cases {
let mut builder = Riscv64InstructionBuilder::new();
builder.jalr(reg::X0, reg::X1, imm);
let instructions = builder.instructions();
compare_instruction(instructions[0], &format!("{}\n", assembly));
}
}
#[cfg(feature = "std")]
#[test]
fn test_jump_instruction_encoding_correctness() {
let mut builder = Riscv64InstructionBuilder::new();
builder.jal(reg::X1, 0);
let instructions = builder.instructions();
compare_instruction(instructions[0], "jal x1, .\n");
let mut builder2 = Riscv64InstructionBuilder::new();
builder2.jalr(reg::X0, reg::X1, 0);
let instructions2 = builder2.instructions();
compare_instruction(instructions2[0], "jalr x0, x1, 0\n");
let mut builder3 = Riscv64InstructionBuilder::new();
builder3.jal(reg::X1, 4);
let instructions3 = builder3.instructions();
compare_instruction(instructions3[0], "jal x1, .+4\n");
let mut builder4 = Riscv64InstructionBuilder::new();
builder4.jalr(reg::X2, reg::X3, 8);
let instructions4 = builder4.instructions();
compare_instruction(instructions4[0], "jalr x2, x3, 8\n");
let mut builder5 = Riscv64InstructionBuilder::new();
builder5.jal(reg::X1, -4);
let instructions5 = builder5.instructions();
compare_instruction(instructions5[0], "jal x1, .-4\n");
}
#[cfg(feature = "std")]
#[test]
fn test_jump_branch_edge_cases() {
let mut builder = Riscv64InstructionBuilder::new();
builder.jal(reg::X1, 1048575); let instructions = builder.instructions();
compare_instruction(instructions[0], "jal x1, .+1048575\n");
let mut builder2 = Riscv64InstructionBuilder::new();
builder2.jal(reg::X1, -1048576); let instructions2 = builder2.instructions();
compare_instruction(instructions2[0], "jal x1, .-1048576\n");
let mut builder3 = Riscv64InstructionBuilder::new();
builder3.jalr(reg::X0, reg::X1, 2047); let instructions3 = builder3.instructions();
compare_instruction(instructions3[0], "jalr x0, x1, 2047\n");
let mut builder4 = Riscv64InstructionBuilder::new();
builder4.jalr(reg::X0, reg::X1, -2048); let instructions4 = builder4.instructions();
compare_instruction(instructions4[0], "jalr x0, x1, -2048\n");
let mut builder5 = Riscv64InstructionBuilder::new();
builder5.beq(reg::X1, reg::X2, 4095); let instructions5 = builder5.instructions();
compare_instruction(instructions5[0], "beq x1, x2, .+4095\n");
let mut builder6 = Riscv64InstructionBuilder::new();
builder6.beq(reg::X1, reg::X2, -4096); let instructions6 = builder6.instructions();
compare_instruction(instructions6[0], "beq x1, x2, .-4096\n");
}
#[cfg(feature = "std")]
#[test]
fn test_branch_instructions_comprehensive() {
let branch_test_cases = vec![
(0, "."), (4, ".+4"), (100, ".+100"), (1000, ".+1000"), (-4, ".-4"), (-100, ".-100"), (-1000, ".-1000"), ];
for (imm, offset_str) in branch_test_cases {
let mut builder = Riscv64InstructionBuilder::new();
builder.beq(reg::X1, reg::X2, imm);
let instructions = builder.instructions();
compare_instruction(instructions[0], &format!("beq x1, x2, {}\n", offset_str));
let mut builder2 = Riscv64InstructionBuilder::new();
builder2.bne(reg::X3, reg::X4, imm);
let instructions2 = builder2.instructions();
compare_instruction(instructions2[0], &format!("bne x3, x4, {}\n", offset_str));
let mut builder3 = Riscv64InstructionBuilder::new();
builder3.blt(reg::X5, reg::X6, imm);
let instructions3 = builder3.instructions();
compare_instruction(instructions3[0], &format!("blt x5, x6, {}\n", offset_str));
let mut builder4 = Riscv64InstructionBuilder::new();
builder4.bge(reg::X7, reg::X8, imm);
let instructions4 = builder4.instructions();
compare_instruction(instructions4[0], &format!("bge x7, x8, {}\n", offset_str));
let mut builder5 = Riscv64InstructionBuilder::new();
builder5.bltu(reg::X9, reg::X10, imm);
let instructions5 = builder5.instructions();
compare_instruction(instructions5[0], &format!("bltu x9, x10, {}\n", offset_str));
let mut builder6 = Riscv64InstructionBuilder::new();
builder6.bgeu(reg::X11, reg::X12, imm);
let instructions6 = builder6.instructions();
compare_instruction(instructions6[0], &format!("bgeu x11, x12, {}\n", offset_str));
}
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_jumps() {
let mut builder = Riscv64InstructionBuilder::new();
builder.jal(reg::X1, 0);
let instructions = builder.instructions();
compare_instruction(instructions[0], "jal x1, .\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.jalr(reg::X0, reg::X1, 0);
let instructions = builder.instructions();
compare_instruction(instructions[0], "jalr x0, x1, 0\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_memory() {
let mut builder = Riscv64InstructionBuilder::new();
builder.ld(reg::X1, reg::X2, 8);
let instructions = builder.instructions();
compare_instruction(instructions[0], "ld x1, 8(x2)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.lw(reg::X3, reg::X4, 4);
let instructions = builder.instructions();
compare_instruction(instructions[0], "lw x3, 4(x4)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.lh(reg::X5, reg::X6, 2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "lh x5, 2(x6)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.lb(reg::X7, reg::X8, 1);
let instructions = builder.instructions();
compare_instruction(instructions[0], "lb x7, 1(x8)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.lbu(reg::X9, reg::X10, 1);
let instructions = builder.instructions();
compare_instruction(instructions[0], "lbu x9, 1(x10)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.lhu(reg::X11, reg::X12, 2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "lhu x11, 2(x12)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.lwu(reg::X13, reg::X14, 4);
let instructions = builder.instructions();
compare_instruction(instructions[0], "lwu x13, 4(x14)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.sd(reg::X9, reg::X10, 8);
let instructions = builder.instructions();
compare_instruction(instructions[0], "sd x10, 8(x9)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.sw(reg::X11, reg::X12, 4);
let instructions = builder.instructions();
compare_instruction(instructions[0], "sw x12, 4(x11)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.sh(reg::X13, reg::X14, 2);
let instructions = builder.instructions();
compare_instruction(instructions[0], "sh x14, 2(x13)\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.sb(reg::X15, reg::X16, 1);
let instructions = builder.instructions();
compare_instruction(instructions[0], "sb x16, 1(x15)\n");
}
#[cfg(feature = "std")]
fn compare_instructions(jit_instrs: &[Instruction], gnu_assembly: &str) {
let gnu_bytes = assemble_riscv(gnu_assembly);
if gnu_bytes.is_empty() {
return;
}
let mut jit_bytes = Vec::new();
for instr in jit_instrs {
jit_bytes.extend_from_slice(&instr.bytes());
}
assert_eq!(jit_bytes.len(), jit_instrs.len() * 4, "JIT instructions should be 4 bytes each");
assert!(gnu_bytes.len() >= jit_bytes.len(), "GNU assembler output should be at least {} bytes", jit_bytes.len());
assert_eq!(
jit_bytes,
&gnu_bytes[0..jit_bytes.len()],
"JIT assembler output does not match GNU assembler output\nJIT: {:02x?}\nGNU: {:02x?}\nAssembly:\n{}",
jit_bytes,
&gnu_bytes[0..jit_bytes.len()],
gnu_assembly
);
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_arithmetic() {
let mut builder = Riscv64InstructionBuilder::new();
builder.addi(reg::X1, reg::X0, 10);
builder.addi(reg::X2, reg::X0, 20);
builder.add(reg::X3, reg::X1, reg::X2);
builder.sub(reg::X4, reg::X3, reg::X1);
let instructions = builder.instructions();
compare_instructions(&instructions,
"addi x1, x0, 10\naddi x2, x0, 20\nadd x3, x1, x2\nsub x4, x3, x1\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_logic_shifts() {
let mut builder = Riscv64InstructionBuilder::new();
builder.lui(reg::X1, 0x12345);
builder.addi(reg::X2, reg::X1, 0x678);
builder.xor(reg::X3, reg::X1, reg::X2);
builder.slli(reg::X4, reg::X3, 4);
builder.srli(reg::X5, reg::X4, 2);
let instructions = builder.instructions();
compare_instructions(&instructions,
"lui x1, 0x12345\naddi x2, x1, 0x678\nxor x3, x1, x2\nslli x4, x3, 4\nsrli x5, x4, 2\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_csr_operations() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X1, csr::MSTATUS);
builder.addi(reg::X2, reg::X1, 1);
builder.csrrw(reg::X3, csr::MSTATUS, reg::X2);
builder.csrrs(reg::X4, csr::MEPC, reg::X0);
let instructions = builder.instructions();
compare_instructions(&instructions,
"csrr x1, mstatus\naddi x2, x1, 1\ncsrrw x3, mstatus, x2\ncsrrs x4, mepc, x0\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_mixed_mode_csr_operations() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X1, csr::MSTATUS); builder.csrr(reg::X2, csr::SSTATUS); builder.csrrw(reg::X3, csr::MTVEC, reg::X1); builder.csrrw(reg::X4, csr::STVEC, reg::X2); builder.csrrs(reg::X5, csr::MIE, reg::X0); builder.csrrs(reg::X6, csr::SIE, reg::X0);
let instructions = builder.instructions();
compare_instructions(&instructions,
"csrr x1, mstatus\ncsrr x2, sstatus\ncsrrw x3, mtvec, x1\ncsrrw x4, stvec, x2\ncsrrs x5, mie, x0\ncsrrs x6, sie, x0\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_s_mode_supervisor_context_switch() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X1, csr::SSTATUS); builder.csrr(reg::X2, csr::SEPC); builder.csrr(reg::X3, csr::SCAUSE); builder.csrr(reg::X4, csr::STVAL); builder.csrrw(reg::X5, csr::SSCRATCH, reg::SP); builder.csrrwi(reg::X6, csr::SIE, 0x0);
let instructions = builder.instructions();
compare_instructions(&instructions,
"csrr x1, sstatus\ncsrr x2, sepc\ncsrr x3, scause\ncsrr x4, stval\ncsrrw x5, sscratch, x2\ncsrrwi x6, sie, 0x0\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_memory_operations() {
let mut builder = Riscv64InstructionBuilder::new();
builder.lui(reg::X1, 0x10000);
builder.addi(reg::X2, reg::X0, 42);
builder.sw(reg::X1, reg::X2, 0);
builder.lw(reg::X3, reg::X1, 0);
builder.addi(reg::X4, reg::X3, 1);
builder.sw(reg::X1, reg::X4, 4);
let instructions = builder.instructions();
compare_instructions(&instructions,
"lui x1, 0x10000\naddi x2, x0, 42\nsw x2, 0(x1)\nlw x3, 0(x1)\naddi x4, x3, 1\nsw x4, 4(x1)\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_control_flow() {
let mut builder = Riscv64InstructionBuilder::new();
builder.addi(reg::X1, reg::X0, 5);
builder.addi(reg::X2, reg::X0, 10);
builder.beq(reg::X1, reg::X2, 0); builder.bne(reg::X1, reg::X2, 0); builder.jal(reg::X3, 0);
let instructions = builder.instructions();
compare_instructions(&instructions,
"addi x1, x0, 5\naddi x2, x0, 10\nbeq x1, x2, .\nbne x1, x2, .\njal x3, .\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_comprehensive() {
let mut builder = Riscv64InstructionBuilder::new();
builder.lui(reg::X1, 0x12345); builder.addi(reg::X1, reg::X1, 0x678); builder.add(reg::X2, reg::X1, reg::X0); builder.slli(reg::X3, reg::X2, 1); builder.xor(reg::X4, reg::X2, reg::X3); builder.csrr(reg::X5, csr::MSTATUS); builder.sw(reg::X1, reg::X4, 8); builder.lw(reg::X6, reg::X1, 8); builder.beq(reg::X4, reg::X6, 0);
let instructions = builder.instructions();
compare_instructions(&instructions,
"lui x1, 0x12345\naddi x1, x1, 0x678\nadd x2, x1, x0\nslli x3, x2, 1\nxor x4, x2, x3\ncsrr x5, mstatus\nsw x4, 8(x1)\nlw x6, 8(x1)\nbeq x4, x6, .\n");
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_multiline_macro_comparison() {
let macro_instructions = crate::riscv64_asm! {
lui(reg::X1, 0x12345);
addi(reg::X2, reg::X1, 100);
add(reg::X3, reg::X1, reg::X2);
sub(reg::X4, reg::X3, reg::X1);
xor(reg::X5, reg::X3, reg::X4);
};
let mut builder = Riscv64InstructionBuilder::new();
builder.lui(reg::X1, 0x12345);
builder.addi(reg::X2, reg::X1, 100);
builder.add(reg::X3, reg::X1, reg::X2);
builder.sub(reg::X4, reg::X3, reg::X1);
builder.xor(reg::X5, reg::X3, reg::X4);
let builder_instructions = builder.instructions();
assert_eq!(macro_instructions.len(), builder_instructions.len());
for (i, (macro_instr, builder_instr)) in macro_instructions.iter().zip(builder_instructions.iter()).enumerate() {
assert_eq!(macro_instr.bytes(), builder_instr.bytes(),
"Instruction {} differs between macro and builder", i);
}
compare_instructions(¯o_instructions,
"lui x1, 0x12345\naddi x2, x1, 100\nadd x3, x1, x2\nsub x4, x3, x1\nxor x5, x3, x4\n");
}
#[cfg(feature = "std")]
#[test]
fn test_li_pseudo_instruction() {
let mut builder = Riscv64InstructionBuilder::new();
builder.li(reg::X1, 0);
let instructions = builder.instructions();
println!("li(x1, 0) generated {} instructions:", instructions.len());
for (i, instr) in instructions.iter().enumerate() {
let val = instr.value() as u32;
println!(" Instruction {}: 0x{:08x}", i, val);
let opcode = val & 0x7F;
let rd = (val >> 7) & 0x1F;
let rs1 = (val >> 15) & 0x1F;
let imm = (val as i32) >> 20;
println!(" opcode=0x{:02x}, rd=x{}, rs1=x{}, imm={}", opcode, rd, rs1, imm);
}
compare_instruction(instructions[0], "addi x1, x0, 0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.li(reg::X2, 100);
let instructions = builder.instructions();
compare_instruction(instructions[0], "addi x2, x0, 100\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.li(reg::X3, -50);
let instructions = builder.instructions();
compare_instruction(instructions[0], "addi x3, x0, -50\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.li(reg::X4, 0x12345678);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 2);
compare_instructions(&instructions, "lui x4, 0x12345\naddi x4, x4, 0x678\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.li(reg::X5, 2047);
let instructions = builder.instructions();
compare_instruction(instructions[0], "addi x5, x0, 2047\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.li(reg::X6, -2048);
let instructions = builder.instructions();
compare_instruction(instructions[0], "addi x6, x0, -2048\n");
}
#[cfg(feature = "std")]
#[test]
fn test_jit_basic_function_creation() {
let jit_func = unsafe {
Riscv64InstructionBuilder::new()
.addi(reg::A0, reg::ZERO, 42) .ret() .function::<fn() -> u64>()
};
assert!(jit_func.is_ok(), "JIT function creation should succeed");
}
#[cfg(feature = "std")]
#[test]
fn test_jit_add_function() {
let jit_func = unsafe {
Riscv64InstructionBuilder::new()
.add(reg::A0, reg::A0, reg::A1) .ret() .function::<fn(u64, u64) -> u64>()
};
assert!(jit_func.is_ok(), "JIT add function creation should succeed");
}
#[cfg(feature = "std")]
#[test]
fn test_jit_constant_function() {
let jit_func = unsafe {
Riscv64InstructionBuilder::new()
.lui(reg::A0, 0x12345) .addi(reg::A0, reg::A0, 0x678) .ret() .function::<fn() -> u64>()
};
assert!(jit_func.is_ok(), "JIT constant function creation should succeed");
}
#[cfg(feature = "std")]
#[test]
fn test_jit_function_chaining() {
let result = unsafe {
Riscv64InstructionBuilder::new()
.addi(reg::A0, reg::ZERO, 10)
.addi(reg::A1, reg::ZERO, 20)
.add(reg::A0, reg::A0, reg::A1)
.ret()
.function::<fn() -> u64>()
};
assert!(result.is_ok(), "Chained JIT function creation should succeed");
}
#[cfg(feature = "std")]
#[test]
fn test_natural_call_syntax() {
let _func0 = unsafe {
Riscv64InstructionBuilder::new()
.addi(reg::A0, reg::ZERO, 42)
.ret()
.function::<fn() -> u64>()
}.expect("Failed to create function");
#[cfg(target_arch = "riscv64")]
{
let _result0 = _func0.call();
}
let _func4 = unsafe {
Riscv64InstructionBuilder::new()
.add(reg::A0, reg::A0, reg::A1) .add(reg::A0, reg::A0, reg::A2) .add(reg::A0, reg::A0, reg::A3) .ret()
.function::<fn(u64, u64, u64, u64) -> u64>()
}.expect("Failed to create function");
let _func7 = unsafe {
Riscv64InstructionBuilder::new()
.add(reg::A0, reg::A0, reg::A1) .add(reg::A0, reg::A0, reg::A2)
.add(reg::A0, reg::A0, reg::A3)
.add(reg::A0, reg::A0, reg::A4)
.add(reg::A0, reg::A0, reg::A5)
.add(reg::A0, reg::A0, reg::A6)
.ret()
.function::<fn(u64, u64, u64, u64, u64, u64, u64) -> u64>()
}.expect("Failed to create function");
#[cfg(target_arch = "riscv64")]
{
let r4 = _func4.call(10u64, 20u64, 30u64, 40u64);
let r8 = _func7.call(1u64, 2u64, 3u64, 4u64, 5u64, 6u64, 7u64);
assert_eq!(r4, 100); assert_eq!(r8, 28); }
}
#[cfg(feature = "register-tracking")]
mod register_tracking_tests {
use super::*;
use crate::common::InstructionBuilder;
#[test]
fn test_basic_r_type_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder.add(reg::T0, reg::T1, reg::T2);
let usage = builder.register_usage();
let written = usage.written_registers();
assert_eq!(written.len(), 1);
assert!(usage.contains_written_register(®::T0));
let read = usage.read_registers();
assert_eq!(read.len(), 2);
assert!(usage.contains_read_register(®::T1));
assert!(usage.contains_read_register(®::T2));
assert_eq!(usage.register_count(), 3);
assert!(usage.has_used_registers());
}
#[test]
fn test_i_type_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder.addi(reg::A0, reg::SP, 16);
let usage = builder.register_usage();
assert!(usage.contains_written_register(®::A0));
assert!(usage.contains_read_register(®::SP));
assert_eq!(usage.register_count(), 2);
assert!(!usage.needs_stack_frame()); }
#[test]
fn test_stack_frame_detection() {
let mut builder = Riscv64InstructionBuilder::new();
builder.add(reg::T0, reg::T1, reg::T2);
assert!(!builder.register_usage().needs_stack_frame());
builder.add(reg::S0, reg::T0, reg::T1);
assert!(builder.register_usage().needs_stack_frame());
}
#[test]
fn test_load_store_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder.ld(reg::T0, reg::SP, 8);
let usage = builder.register_usage();
assert!(usage.contains_written_register(®::T0));
assert!(usage.contains_read_register(®::SP));
builder.clear();
builder.sd(reg::SP, reg::T1, -16);
let usage = builder.register_usage();
assert_eq!(usage.written_registers().len(), 0);
assert_eq!(usage.read_registers().len(), 2);
assert!(usage.contains_read_register(®::SP));
assert!(usage.contains_read_register(®::T1));
}
#[test]
fn test_m_extension_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder.mul(reg::A0, reg::A1, reg::A2);
let usage = builder.register_usage();
assert!(usage.contains_written_register(®::A0));
assert!(usage.contains_read_register(®::A1));
assert!(usage.contains_read_register(®::A2));
assert_eq!(usage.register_count(), 3);
}
#[test]
fn test_branch_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder.beq(reg::T0, reg::T1, 100);
let usage = builder.register_usage();
assert_eq!(usage.written_registers().len(), 0);
assert_eq!(usage.read_registers().len(), 2);
assert!(usage.contains_read_register(®::T0));
assert!(usage.contains_read_register(®::T1));
}
#[test]
fn test_u_type_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder.lui(reg::T0, 0x12345);
let usage = builder.register_usage();
assert_eq!(usage.written_registers().len(), 1);
assert_eq!(usage.read_registers().len(), 0);
assert!(usage.contains_written_register(®::T0));
}
#[test]
fn test_j_type_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder.jal(reg::RA, 1000);
let usage = builder.register_usage();
assert_eq!(usage.written_registers().len(), 1);
assert!(usage.contains_written_register(®::RA));
}
#[test]
fn test_csr_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::T0, csr::MSTATUS, reg::T1);
let usage = builder.register_usage();
assert!(usage.contains_written_register(®::T0));
assert!(usage.contains_read_register(®::T1));
assert_eq!(usage.register_count(), 2);
}
#[test]
fn test_complex_function_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder
.addi(reg::SP, reg::SP, -16) .sd(reg::SP, reg::S0, 8) .add(reg::S0, reg::A0, reg::A1) .mul(reg::T0, reg::S0, reg::A2) .ld(reg::S0, reg::SP, 8) .addi(reg::SP, reg::SP, 16) .add(reg::A0, reg::T0, reg::ZERO);
let usage = builder.register_usage();
assert!(usage.has_used_registers());
assert!(usage.needs_stack_frame());
let written = usage.written_registers();
let read = usage.read_registers();
assert!(usage.contains_written_register(®::SP));
assert!(usage.contains_written_register(®::S0));
assert!(usage.contains_written_register(®::T0));
assert!(usage.contains_written_register(®::A0));
assert!(usage.contains_read_register(®::A0)); assert!(usage.contains_read_register(®::A1));
assert!(usage.contains_read_register(®::A2));
let caller_saved_written = usage.caller_saved_written();
let callee_saved_written = usage.callee_saved_written();
assert!(!caller_saved_written.is_empty());
assert!(!callee_saved_written.is_empty());
println!("Complex function register usage: {}", usage);
}
#[test]
fn test_register_reuse_tracking() {
let mut builder = Riscv64InstructionBuilder::new();
builder
.addi(reg::T0, reg::ZERO, 10) .add(reg::T1, reg::T0, reg::T0);
let usage = builder.register_usage();
assert!(usage.contains_written_register(®::T0));
assert!(usage.contains_read_register(®::T0));
let used = usage.used_registers();
let t0_count = used.iter().filter(|&&r| r == reg::T0).count();
assert_eq!(t0_count, 1);
}
}
#[test]
fn test_all_m_mode_csr_addresses() {
assert_eq!(csr::MVENDORID.value(), 0xf11);
assert_eq!(csr::MARCHID.value(), 0xf12);
assert_eq!(csr::MIMPID.value(), 0xf13);
assert_eq!(csr::MHARTID.value(), 0xf14);
assert_eq!(csr::MCONFIGPTR.value(), 0xf15);
assert_eq!(csr::MSTATUS.value(), 0x300);
assert_eq!(csr::MISA.value(), 0x301);
assert_eq!(csr::MEDELEG.value(), 0x302);
assert_eq!(csr::MIDELEG.value(), 0x303);
assert_eq!(csr::MIE.value(), 0x304);
assert_eq!(csr::MTVEC.value(), 0x305);
assert_eq!(csr::MCOUNTEREN.value(), 0x306);
assert_eq!(csr::MSTATUSH.value(), 0x310);
assert_eq!(csr::MSCRATCH.value(), 0x340);
assert_eq!(csr::MEPC.value(), 0x341);
assert_eq!(csr::MCAUSE.value(), 0x342);
assert_eq!(csr::MTVAL.value(), 0x343);
assert_eq!(csr::MIP.value(), 0x344);
assert_eq!(csr::MTINST.value(), 0x34a);
assert_eq!(csr::MTVAL2.value(), 0x34b);
assert_eq!(csr::MENVCFG.value(), 0x30a);
assert_eq!(csr::MENVCFGH.value(), 0x31a);
assert_eq!(csr::MSECCFG.value(), 0x747);
assert_eq!(csr::MSECCFGH.value(), 0x757);
assert_eq!(csr::PMPCFG0.value(), 0x3a0);
assert_eq!(csr::PMPCFG1.value(), 0x3a1);
assert_eq!(csr::PMPCFG2.value(), 0x3a2);
assert_eq!(csr::PMPCFG3.value(), 0x3a3);
assert_eq!(csr::PMPCFG4.value(), 0x3a4);
assert_eq!(csr::PMPCFG5.value(), 0x3a5);
assert_eq!(csr::PMPCFG6.value(), 0x3a6);
assert_eq!(csr::PMPCFG7.value(), 0x3a7);
assert_eq!(csr::PMPCFG8.value(), 0x3a8);
assert_eq!(csr::PMPCFG9.value(), 0x3a9);
assert_eq!(csr::PMPCFG10.value(), 0x3aa);
assert_eq!(csr::PMPCFG11.value(), 0x3ab);
assert_eq!(csr::PMPCFG12.value(), 0x3ac);
assert_eq!(csr::PMPCFG13.value(), 0x3ad);
assert_eq!(csr::PMPCFG14.value(), 0x3ae);
assert_eq!(csr::PMPCFG15.value(), 0x3af);
assert_eq!(csr::PMPADDR0.value(), 0x3b0);
assert_eq!(csr::PMPADDR1.value(), 0x3b1);
assert_eq!(csr::PMPADDR15.value(), 0x3bf);
assert_eq!(csr::PMPADDR31.value(), 0x3cf);
assert_eq!(csr::PMPADDR63.value(), 0x3ef);
assert_eq!(csr::MCYCLE.value(), 0xb00);
assert_eq!(csr::MINSTRET.value(), 0xb02);
assert_eq!(csr::MHPMCOUNTER3.value(), 0xb03);
assert_eq!(csr::MHPMCOUNTER4.value(), 0xb04);
assert_eq!(csr::MHPMCOUNTER31.value(), 0xb1f);
assert_eq!(csr::MCYCLEH.value(), 0xb80);
assert_eq!(csr::MINSTRETH.value(), 0xb82);
assert_eq!(csr::MHPMCOUNTER3H.value(), 0xb83);
assert_eq!(csr::MHPMCOUNTER31H.value(), 0xb9f);
assert_eq!(csr::MCOUNTINHIBIT.value(), 0x320);
assert_eq!(csr::MHPMEVENT3.value(), 0x323);
assert_eq!(csr::MHPMEVENT4.value(), 0x324);
assert_eq!(csr::MHPMEVENT31.value(), 0x33f);
}
#[test]
fn test_m_mode_csr_usage() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrr(reg::X1, csr::MVENDORID);
builder.csrr(reg::X2, csr::MARCHID);
builder.csrr(reg::X3, csr::MIMPID);
builder.csrr(reg::X4, csr::MCONFIGPTR);
builder.csrr(reg::X5, csr::MCOUNTEREN);
builder.csrr(reg::X6, csr::MTINST);
builder.csrr(reg::X7, csr::MTVAL2);
builder.csrr(reg::X8, csr::MENVCFG);
builder.csrr(reg::X9, csr::MSECCFG);
builder.csrr(reg::X10, csr::PMPCFG0);
builder.csrr(reg::X11, csr::PMPADDR0);
builder.csrr(reg::X12, csr::MCYCLE);
builder.csrr(reg::X13, csr::MINSTRET);
builder.csrr(reg::X14, csr::MHPMCOUNTER3);
builder.csrr(reg::X15, csr::MCOUNTINHIBIT);
builder.csrr(reg::X16, csr::MHPMEVENT3);
let instructions = builder.instructions();
assert_eq!(instructions.len(), 16);
for (i, instr) in instructions.iter().enumerate() {
assert!(instr.value() != 0, "Instruction {} should be non-zero", i);
}
}
#[cfg(feature = "std")]
#[test]
fn test_binary_correctness_m_mode_csrs() {
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MVENDORID, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mvendorid, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MARCHID, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, marchid, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MIMPID, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mimpid, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MCONFIGPTR, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mconfigptr, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MCOUNTEREN, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mcounteren, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MSTATUSH, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mstatush, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MTINST, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mtinst, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MTVAL2, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mtval2, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MENVCFG, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, menvcfg, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MENVCFGH, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, menvcfgh, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MSECCFG, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mseccfg, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MSECCFGH, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mseccfgh, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG0, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg0, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG1, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg1, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG2, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg2, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG3, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg3, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG4, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg4, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG5, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg5, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG6, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg6, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG7, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg7, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG8, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg8, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG9, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg9, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG10, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg10, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG11, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg11, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG12, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg12, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG13, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg13, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG14, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg14, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPCFG15, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpcfg15, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR0, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr0, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR1, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr1, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR2, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr2, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR3, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr3, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR4, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr4, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR5, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr5, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR6, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr6, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR7, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr7, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR8, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr8, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR9, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr9, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR10, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr10, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR11, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr11, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR12, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr12, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR13, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr13, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR14, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr14, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR15, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr15, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR16, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr16, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR17, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr17, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR18, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr18, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR19, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr19, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR20, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr20, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR21, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr21, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR22, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr22, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR23, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr23, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR24, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr24, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR25, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr25, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR26, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr26, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR27, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr27, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR28, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr28, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR29, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr29, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR30, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr30, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR31, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr31, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR32, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr32, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR33, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr33, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR34, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr34, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR35, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr35, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR36, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr36, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR37, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr37, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR38, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr38, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR39, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr39, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR40, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr40, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR41, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr41, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR42, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr42, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR43, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr43, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR44, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr44, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR45, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr45, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR46, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr46, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR47, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr47, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR48, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr48, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR49, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr49, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR50, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr50, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR51, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr51, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR52, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr52, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR53, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr53, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR54, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr54, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR55, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr55, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR56, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr56, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR57, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr57, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR58, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr58, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR59, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr59, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR60, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr60, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR61, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr61, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR62, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr62, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::PMPADDR63, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, pmpaddr63, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MCYCLE, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mcycle, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MINSTRET, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, minstret, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER3, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter3, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER4, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter4, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER5, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter5, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER6, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter6, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER7, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter7, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER8, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter8, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER9, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter9, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER10, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter10, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER11, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter11, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER12, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter12, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER13, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter13, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER14, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter14, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER15, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter15, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER16, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter16, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER17, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter17, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER18, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter18, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER19, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter19, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER20, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter20, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER21, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter21, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER22, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter22, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER23, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter23, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER24, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter24, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER25, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter25, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER26, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter26, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER27, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter27, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER28, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter28, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER29, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter29, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER30, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter30, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER31, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter31, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MCYCLEH, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mcycleh, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MINSTRETH, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, minstreth, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER3H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter3h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER4H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter4h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER5H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter5h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER6H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter6h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER7H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter7h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER8H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter8h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER9H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter9h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER10H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter10h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER11H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter11h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER12H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter12h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER13H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter13h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER14H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter14h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER15H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter15h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER16H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter16h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER17H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter17h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER18H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter18h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER19H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter19h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER20H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter20h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER21H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter21h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER22H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter22h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER23H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter23h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER24H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter24h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER25H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter25h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER26H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter26h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER27H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter27h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER28H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter28h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER29H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter29h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER30H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter30h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMCOUNTER31H, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmcounter31h, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MCOUNTINHIBIT, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mcountinhibit, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT3, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent3, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT4, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent4, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT5, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent5, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT6, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent6, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT7, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent7, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT8, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent8, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT9, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent9, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT10, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent10, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT11, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent11, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT12, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent12, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT13, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent13, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT14, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent14, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT15, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent15, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT16, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent16, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT17, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent17, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT18, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent18, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT19, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent19, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT20, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent20, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT21, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent21, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT22, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent22, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT23, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent23, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT24, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent24, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT25, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent25, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT26, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent26, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT27, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent27, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT28, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent28, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT29, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent29, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT30, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent30, x0\n");
let mut builder = Riscv64InstructionBuilder::new();
builder.csrrw(reg::X0, csr::MHPMEVENT31, reg::X0);
compare_instruction(builder.instructions()[0], "csrrw x0, mhpmevent31, x0\n");
}