From d209a53ceceddb0f44c2ce42d7fc9584cd795e30 Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 29 Jun 2025 15:50:11 +0900 Subject: [PATCH 1/9] [add] add `test_32`, `test_32_in_rv32` and `test_32_in_rv64` --- src/decode/inst_32.rs | 111 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/decode/inst_32.rs b/src/decode/inst_32.rs index 8719f95..2c91b9f 100644 --- a/src/decode/inst_32.rs +++ b/src/decode/inst_32.rs @@ -180,3 +180,114 @@ impl DecodeUtil for u32 { inst } } + +#[cfg(test)] +pub fn test_32( + isa: Isa, + location: &std::panic::Location, + inst_32: u32, + op: OpcodeKind, + rd: Option, + rs1: Option, + rs2: Option, + imm: Option, +) { + let op_32 = inst_32.parse_opcode(isa).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to decode {inst_32:032b} ({}: line {})", + location.file(), + location.line() + ); + }); + assert_eq!( + op_32, + op, + "Opecode does not match: {op_32} != {op} ({}: line {})", + location.file(), + location.line() + ); + assert_eq!( + inst_32.parse_rd(&op_32).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to parse rd in {op}({inst_32:032b}) ({}: line {})", + location.file(), + location.line() + ); + }), + rd, + "rd does not match: {:x?} != {rd:x?} ({}: line {})", + inst_32.parse_rd(&op_32), + location.file(), + location.line() + ); + assert_eq!( + inst_32.parse_rs1(&op_32).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to parse rs1 in {op}({inst_32:032b}) ({}: line {})", + location.file(), + location.line() + ); + }), + rs1, + "rs1 does not match: {:x?} != {rs1:x?} ({}: line {})", + inst_32.parse_rs1(&op_32), + location.file(), + location.line() + ); + assert_eq!( + inst_32.parse_rs2(&op_32).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to parse rs2 in {op}({inst_32:032b}) ({}: line {})", + location.file(), + location.line() + ); + }), + rs2, + "rs2 does not match: {:x?} != {rs2:x?} ({}: line {})", + inst_32.parse_rs2(&op_32), + location.file(), + location.line() + ); + assert_eq!( + inst_32.parse_imm(&op_32, isa).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to parse imm in {op}({inst_32:032b}) ({}: line {})", + location.file(), + location.line() + ); + }), + imm, + "imm does not match: {:x?} != {imm:x?} ({}: line {})", + inst_32.parse_imm(&op_32, isa), + location.file(), + location.line() + ); +} + +#[cfg(test)] +#[track_caller] +pub fn test_32_in_rv32( + inst_32: u32, + op: OpcodeKind, + rd: Option, + rs1: Option, + rs2: Option, + imm: Option, +) { + let location = std::panic::Location::caller(); + test_32(Isa::Rv32, location, inst_32, op, rd, rs1, rs2, imm); +} + +#[cfg(test)] +#[track_caller] +pub fn test_32_in_rv64( + inst_32: u32, + op: OpcodeKind, + rd: Option, + rs1: Option, + rs2: Option, + imm: Option, +) { + let location = std::panic::Location::caller(); + test_32(Isa::Rv64, location, inst_32, op, rd, rs1, rs2, imm); +} From 49a0c2d139a27051c40d90ac201be58a1432cc70 Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 29 Jun 2025 15:56:02 +0900 Subject: [PATCH 2/9] [fix] replace `test_32` closure with `test_32_in_rv64` function --- src/decode/a_extension.rs | 23 ++++------------ src/decode/base_i.rs | 45 ++++++++++++-------------------- src/decode/m_extension.rs | 23 ++++------------ src/decode/priv_extension.rs | 21 +++------------ src/decode/zicboz_extension.rs | 21 +++------------ src/decode/zicfiss_extension.rs | 31 +++++++--------------- src/decode/zicntr_extension.rs | 19 +++----------- src/decode/zicsr_extension.rs | 23 ++++------------ src/decode/zifencei_extension.rs | 19 +++----------- 9 files changed, 54 insertions(+), 171 deletions(-) diff --git a/src/decode/a_extension.rs b/src/decode/a_extension.rs index 2ac786b..63468f1 100644 --- a/src/decode/a_extension.rs +++ b/src/decode/a_extension.rs @@ -170,24 +170,11 @@ mod test_a { #[test] #[allow(overflowing_literals)] fn a_decode_test() { + use crate::decode::inst_32::test_32_in_rv64; use crate::instruction::a_extension::AOpcode; - use crate::{Decode, Isa, OpcodeKind}; + use crate::OpcodeKind; - let test_32 = |inst_32: u32, - op: OpcodeKind, - rd: Option, - rs1: Option, - rs2: Option, - imm: Option| { - let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); - assert!(matches!(&op_32, op)); - assert_eq!(inst_32.parse_rd(&op_32).unwrap(), rd); - assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), rs1); - assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), rs2); - assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), imm); - }; - - test_32( + test_32_in_rv64( 0x04d7_27af, OpcodeKind::A(AOpcode::AMOADD_W), Some(15), @@ -195,7 +182,7 @@ mod test_a { Some(13), Some(2), ); - test_32( + test_32_in_rv64( 0x1007b62f, OpcodeKind::A(AOpcode::LR_D), Some(12), @@ -203,7 +190,7 @@ mod test_a { None, Some(0), ); - test_32( + test_32_in_rv64( 0x60f6302f, OpcodeKind::A(AOpcode::AMOAND_D), Some(0), diff --git a/src/decode/base_i.rs b/src/decode/base_i.rs index eb6ffd4..d811f8f 100644 --- a/src/decode/base_i.rs +++ b/src/decode/base_i.rs @@ -343,24 +343,11 @@ mod test_basei { #[test] #[allow(overflowing_literals)] fn basei_decode_test() { + use crate::decode::inst_32::test_32_in_rv64; use crate::instruction::base_i::BaseIOpcode; - use crate::{Decode, Isa, OpcodeKind}; + use crate::OpcodeKind; - let test_32 = |inst_32: u32, - op: OpcodeKind, - rd: Option, - rs1: Option, - rs2: Option, - imm: Option| { - let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); - assert!(matches!(&op_32, op)); - assert_eq!(inst_32.parse_rd(&op_32).unwrap(), rd); - assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), rs1); - assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), rs2); - assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), imm); - }; - - test_32( + test_32_in_rv64( 0b1000_0000_0000_0000_0000_0000_1011_0111, OpcodeKind::BaseI(BaseIOpcode::LUI), Some(1), @@ -368,7 +355,7 @@ mod test_basei { None, Some(0x8000_0000), ); - test_32( + test_32_in_rv64( 0b0000_0000_0000_0000_0000_0010_1001_0111, OpcodeKind::BaseI(BaseIOpcode::AUIPC), Some(5), @@ -376,7 +363,7 @@ mod test_basei { None, Some(0), ); - test_32( + test_32_in_rv64( 0b1111_1111_1001_1111_1111_0000_0110_1111, OpcodeKind::BaseI(BaseIOpcode::JAL), Some(0), @@ -384,7 +371,7 @@ mod test_basei { None, Some(-8), ); - test_32( + test_32_in_rv64( 0b1111_1110_0010_0000_1000_1110_1010_0011, OpcodeKind::BaseI(BaseIOpcode::SB), None, @@ -392,7 +379,7 @@ mod test_basei { Some(2), Some(-3), ); - test_32( + test_32_in_rv64( 0b1110_1110_1100_0010_1000_0010_1001_0011, OpcodeKind::BaseI(BaseIOpcode::ADDI), Some(5), @@ -400,7 +387,7 @@ mod test_basei { None, Some(-276), ); - test_32( + test_32_in_rv64( 0b0000_0000_0000_0000_0000_0000_0111_0011, OpcodeKind::BaseI(BaseIOpcode::ECALL), None, @@ -408,7 +395,7 @@ mod test_basei { None, None, ); - test_32( + test_32_in_rv64( 0b0000_0000_0000_0101_0100_1100_0110_0011, OpcodeKind::BaseI(BaseIOpcode::BLT), None, @@ -416,7 +403,7 @@ mod test_basei { Some(0), Some(24), ); - test_32( + test_32_in_rv64( 0x0010_0513, OpcodeKind::BaseI(BaseIOpcode::ADDI), Some(10), @@ -424,7 +411,7 @@ mod test_basei { None, Some(1), ); - test_32( + test_32_in_rv64( 0x4170_04b3, OpcodeKind::BaseI(BaseIOpcode::SUB), Some(9), @@ -432,7 +419,7 @@ mod test_basei { Some(23), None, ); - test_32( + test_32_in_rv64( 0x3307_3983, OpcodeKind::BaseI(BaseIOpcode::LD), Some(19), @@ -440,7 +427,7 @@ mod test_basei { None, Some(816), ); - test_32( + test_32_in_rv64( 0x10ec_eb63, OpcodeKind::BaseI(BaseIOpcode::BLTU), None, @@ -448,7 +435,7 @@ mod test_basei { Some(14), Some(278), ); - test_32( + test_32_in_rv64( 0x31e1_60ef, OpcodeKind::BaseI(BaseIOpcode::JAL), Some(1), @@ -456,7 +443,7 @@ mod test_basei { None, Some(90910), ); - test_32( + test_32_in_rv64( 0x0019_4913, OpcodeKind::BaseI(BaseIOpcode::XORI), Some(18), @@ -464,7 +451,7 @@ mod test_basei { None, Some(1), ); - test_32( + test_32_in_rv64( 0x00a9_3933, OpcodeKind::BaseI(BaseIOpcode::SLTU), Some(18), diff --git a/src/decode/m_extension.rs b/src/decode/m_extension.rs index 5a90809..322f554 100644 --- a/src/decode/m_extension.rs +++ b/src/decode/m_extension.rs @@ -106,24 +106,11 @@ mod test_m { #[test] #[allow(overflowing_literals)] fn m_decode_test() { + use crate::decode::inst_32::test_32_in_rv64; use crate::instruction::m_extension::MOpcode; - use crate::{Decode, Isa, OpcodeKind}; + use crate::OpcodeKind; - let test_32 = |inst_32: u32, - op: OpcodeKind, - rd: Option, - rs1: Option, - rs2: Option, - imm: Option| { - let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); - assert!(matches!(&op_32, op)); - assert_eq!(inst_32.parse_rd(&op_32).unwrap(), rd); - assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), rs1); - assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), rs2); - assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), imm); - }; - - test_32( + test_32_in_rv64( 0x02d706b3, OpcodeKind::M(MOpcode::MUL), Some(13), @@ -131,7 +118,7 @@ mod test_m { Some(13), None, ); - test_32( + test_32_in_rv64( 0x0289_7933, OpcodeKind::M(MOpcode::REMU), Some(18), @@ -139,7 +126,7 @@ mod test_m { Some(8), None, ); - test_32( + test_32_in_rv64( 0x0289_5933, OpcodeKind::M(MOpcode::DIVU), Some(18), diff --git a/src/decode/priv_extension.rs b/src/decode/priv_extension.rs index b06fc24..5d18af3 100644 --- a/src/decode/priv_extension.rs +++ b/src/decode/priv_extension.rs @@ -53,24 +53,11 @@ mod test_priv { #[test] #[allow(overflowing_literals)] fn priv_decode_test() { + use crate::decode::inst_32::test_32_in_rv64; use crate::instruction::priv_extension::PrivOpcode; - use crate::{Decode, Isa, OpcodeKind}; + use crate::OpcodeKind; - let test_32 = |inst_32: u32, - op: OpcodeKind, - rd: Option, - rs1: Option, - rs2: Option, - imm: Option| { - let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); - assert!(matches!(&op_32, op)); - assert_eq!(inst_32.parse_rd(&op_32).unwrap(), rd); - assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), rs1); - assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), rs2); - assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), imm); - }; - - test_32( + test_32_in_rv64( 0x10200073, OpcodeKind::Priv(PrivOpcode::SRET), None, @@ -78,7 +65,7 @@ mod test_priv { None, None, ); - test_32( + test_32_in_rv64( 0x10500073, OpcodeKind::Priv(PrivOpcode::WFI), None, diff --git a/src/decode/zicboz_extension.rs b/src/decode/zicboz_extension.rs index 8f115f3..abe7a87 100644 --- a/src/decode/zicboz_extension.rs +++ b/src/decode/zicboz_extension.rs @@ -53,24 +53,11 @@ mod test_zicboz { #[test] #[allow(overflowing_literals)] fn zicboz_decode_test() { + use crate::decode::inst_32::test_32_in_rv64; use crate::instruction::zicboz_extension::ZicbozOpcode; - use crate::{Decode, Isa, OpcodeKind}; + use crate::OpcodeKind; - let test_32 = |inst_32: u32, - op: OpcodeKind, - rd: Option, - rs1: Option, - rs2: Option, - imm: Option| { - let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); - assert!(matches!(&op_32, op)); - assert_eq!(inst_32.parse_rd(&op_32).unwrap(), rd); - assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), rs1); - assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), rs2); - assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), imm); - }; - - test_32( + test_32_in_rv64( 0b0000_0000_0100_1010_1010_0000_0000_1111, OpcodeKind::Zicboz(ZicbozOpcode::CBO_ZERO), None, @@ -79,7 +66,7 @@ mod test_zicboz { None, ); - test_32( + test_32_in_rv64( 0b0000_0000_0100_1000_0010_0000_0000_1111, OpcodeKind::Zicboz(ZicbozOpcode::CBO_ZERO), None, diff --git a/src/decode/zicfiss_extension.rs b/src/decode/zicfiss_extension.rs index 63bc513..fab2de4 100644 --- a/src/decode/zicfiss_extension.rs +++ b/src/decode/zicfiss_extension.rs @@ -123,24 +123,11 @@ mod test_zicfiss { #[test] #[allow(overflowing_literals)] fn zicfiss_32bit_decode_test() { + use crate::decode::inst_32::test_32_in_rv64; use crate::instruction::zicfiss_extension::ZicfissOpcode; - use crate::{Decode, Isa, OpcodeKind}; - - let test_32 = |inst_32: u32, - expected_op: OpcodeKind, - expected_rd: Option, - expected_rs1: Option, - expected_rs2: Option, - expected_imm: Option| { - let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); - assert_eq!(op_32, expected_op); - assert_eq!(inst_32.parse_rd(&op_32).unwrap(), expected_rd); - assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), expected_rs1); - assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), expected_rs2); - assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), expected_imm); - }; + use crate::OpcodeKind; - test_32( + test_32_in_rv64( 0b1100_1110_0101_0000_0100_0000_0111_0011, OpcodeKind::Zicfiss(ZicfissOpcode::SSPUSH), Some(0), @@ -149,7 +136,7 @@ mod test_zicfiss { None, ); - test_32( + test_32_in_rv64( 0b1100_1110_0001_0000_0100_0000_0111_0011, OpcodeKind::Zicfiss(ZicfissOpcode::SSPUSH), Some(0), @@ -158,7 +145,7 @@ mod test_zicfiss { None, ); - test_32( + test_32_in_rv64( 0b1100_1101_1100_0000_1100_0000_0111_0011, OpcodeKind::Zicfiss(ZicfissOpcode::SSPOPCHK), Some(0), @@ -167,7 +154,7 @@ mod test_zicfiss { None, ); - test_32( + test_32_in_rv64( 0b1100_1101_1100_0010_1100_0000_0111_0011, OpcodeKind::Zicfiss(ZicfissOpcode::SSPOPCHK), Some(0), @@ -176,7 +163,7 @@ mod test_zicfiss { None, ); - test_32( + test_32_in_rv64( 0b0100_1000_1100_0010_1010_0001_1010_1111, OpcodeKind::Zicfiss(ZicfissOpcode::SSAMOSWAP_W), Some(3), @@ -185,7 +172,7 @@ mod test_zicfiss { None, ); - test_32( + test_32_in_rv64( 0b0100_1000_1100_0111_0011_0001_1010_1111, OpcodeKind::Zicfiss(ZicfissOpcode::SSAMOSWAP_D), Some(3), @@ -194,7 +181,7 @@ mod test_zicfiss { None, ); - test_32( + test_32_in_rv64( 0xcdc0c073, OpcodeKind::Zicfiss(ZicfissOpcode::SSPOPCHK), Some(0), diff --git a/src/decode/zicntr_extension.rs b/src/decode/zicntr_extension.rs index dde7840..afdbcc8 100644 --- a/src/decode/zicntr_extension.rs +++ b/src/decode/zicntr_extension.rs @@ -80,24 +80,11 @@ mod test_zicntr { #[test] #[allow(overflowing_literals)] fn zicntr_decode_test() { + use crate::decode::inst_32::test_32_in_rv64; use crate::instruction::zicntr_extension::ZicntrOpcode; - use crate::{Decode, Isa, OpcodeKind}; + use crate::OpcodeKind; - let test_32 = |inst_32: u32, - op: OpcodeKind, - rd: Option, - rs1: Option, - rs2: Option, - imm: Option| { - let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); - assert!(matches!(&op_32, op)); - assert_eq!(inst_32.parse_rd(&op_32).unwrap(), rd); - assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), rs1); - assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), rs2); - assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), imm); - }; - - test_32( + test_32_in_rv64( 0b1100_0000_0001_0000_0010_0111_1111_0011, OpcodeKind::Zicntr(ZicntrOpcode::RDTIME), Some(15), diff --git a/src/decode/zicsr_extension.rs b/src/decode/zicsr_extension.rs index aa6ff6a..7a0035c 100644 --- a/src/decode/zicsr_extension.rs +++ b/src/decode/zicsr_extension.rs @@ -74,24 +74,11 @@ mod test_zicsr { #[test] #[allow(overflowing_literals)] fn zicsr_decode_test() { + use crate::decode::inst_32::test_32_in_rv64; use crate::instruction::zicsr_extension::ZicsrOpcode; - use crate::{Decode, Isa, OpcodeKind}; + use crate::OpcodeKind; - let test_32 = |inst_32: u32, - op: OpcodeKind, - rd: Option, - rs1: Option, - rs2: Option, - imm: Option| { - let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); - assert!(matches!(&op_32, op)); - assert_eq!(inst_32.parse_rd(&op_32).unwrap(), rd); - assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), rs1); - assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), rs2); - assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), imm); - }; - - test_32( + test_32_in_rv64( 0b0001_0000_0000_1000_0011_0000_0111_0011, OpcodeKind::Zicsr(ZicsrOpcode::CSRRC), Some(0), // rd @@ -99,7 +86,7 @@ mod test_zicsr { Some(0x100), // csr None, ); - test_32( + test_32_in_rv64( 0b0001_0000_0000_1000_0010_0000_0111_0011, OpcodeKind::Zicsr(ZicsrOpcode::CSRRS), Some(0), // rd @@ -107,7 +94,7 @@ mod test_zicsr { Some(0x100), // csr None, ); - test_32( + test_32_in_rv64( 0b0001_0000_0000_0001_0110_0000_0111_0011, OpcodeKind::Zicsr(ZicsrOpcode::CSRRSI), Some(0), // rd diff --git a/src/decode/zifencei_extension.rs b/src/decode/zifencei_extension.rs index 3569c83..91807bb 100644 --- a/src/decode/zifencei_extension.rs +++ b/src/decode/zifencei_extension.rs @@ -51,24 +51,11 @@ mod test_zifenci { #[test] #[allow(overflowing_literals)] fn zifenci_decode_test() { + use crate::decode::inst_32::test_32_in_rv64; use crate::instruction::zifencei_extension::ZifenceiOpcode; - use crate::{Decode, Isa, OpcodeKind}; + use crate::OpcodeKind; - let test_32 = |inst_32: u32, - op: OpcodeKind, - rd: Option, - rs1: Option, - rs2: Option, - imm: Option| { - let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap(); - assert!(matches!(&op_32, op)); - assert_eq!(inst_32.parse_rd(&op_32).unwrap(), rd); - assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), rs1); - assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), rs2); - assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), imm); - }; - - test_32( + test_32_in_rv64( 0b0000_0011_0011_0000_0000_0000_0000_1111, OpcodeKind::Zifencei(ZifenceiOpcode::FENCE), Some(0), From 896cfad088684599c7c4321bb16005df2cc1340a Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 29 Jun 2025 16:03:29 +0900 Subject: [PATCH 3/9] [add] add `test_16`, `test_16_in_rv32` and `test_16_in_rv64` --- src/decode/inst_16.rs | 111 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/decode/inst_16.rs b/src/decode/inst_16.rs index 55f009b..7d16207 100644 --- a/src/decode/inst_16.rs +++ b/src/decode/inst_16.rs @@ -95,3 +95,114 @@ impl DecodeUtil for u16 { inst } } + +#[cfg(test)] +pub fn test_16( + isa: Isa, + location: &std::panic::Location, + inst_16: u16, + op: OpcodeKind, + rd: Option, + rs1: Option, + rs2: Option, + imm: Option, +) { + let op_16 = inst_16.parse_opcode(isa).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to decode {inst_16:016b} ({}: line {})", + location.file(), + location.line() + ); + }); + assert_eq!( + op_16, + op, + "Opecode does not match: {op_16} != {op} ({}: line {})", + location.file(), + location.line() + ); + assert_eq!( + inst_16.parse_rd(&op_16).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to parse rd in {op}({inst_16:016b}) ({}: line {})", + location.file(), + location.line() + ); + }), + rd, + "rd does not match: {:x?} != {rd:x?} ({}: line {})", + inst_16.parse_rd(&op_16), + location.file(), + location.line() + ); + assert_eq!( + inst_16.parse_rs1(&op_16).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to parse rs1 in {op}({inst_16:016b}) ({}: line {})", + location.file(), + location.line() + ); + }), + rs1, + "rs1 does not match: {:x?} != {rs1:x?} ({}: line {})", + inst_16.parse_rs1(&op_16), + location.file(), + location.line() + ); + assert_eq!( + inst_16.parse_rs2(&op_16).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to parse rs2 in {op}({inst_16:016b}) ({}: line {})", + location.file(), + location.line() + ); + }), + rs2, + "rs2 does not match: {:x?} != {rs2:x?} ({}: line {})", + inst_16.parse_rs2(&op_16), + location.file(), + location.line() + ); + assert_eq!( + inst_16.parse_imm(&op_16, isa).unwrap_or_else(|e| { + panic!( + "{e:?}: failed to parse imm in {op}({inst_16:016b}) ({}: line {})", + location.file(), + location.line() + ); + }), + imm, + "imm does not match: {:x?} != {imm:x?} ({}: line {})", + inst_16.parse_imm(&op_16, isa), + location.file(), + location.line() + ); +} + +#[cfg(test)] +#[track_caller] +pub fn test_16_in_rv16( + inst_16: u16, + op: OpcodeKind, + rd: Option, + rs1: Option, + rs2: Option, + imm: Option, +) { + let location = std::panic::Location::caller(); + test_16(Isa::Rv32, location, inst_16, op, rd, rs1, rs2, imm); +} + +#[cfg(test)] +#[track_caller] +pub fn test_16_in_rv64( + inst_16: u16, + op: OpcodeKind, + rd: Option, + rs1: Option, + rs2: Option, + imm: Option, +) { + let location = std::panic::Location::caller(); + test_16(Isa::Rv64, location, inst_16, op, rd, rs1, rs2, imm); +} From ef1370dd7e14f8ff05b48ba3d106ecbc281e183e Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 29 Jun 2025 16:04:49 +0900 Subject: [PATCH 4/9] [fix] replace `test_16` closure with `test_16_in_rv64` function --- src/decode/c_extension.rs | 40 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/src/decode/c_extension.rs b/src/decode/c_extension.rs index 4735ca6..505da7a 100644 --- a/src/decode/c_extension.rs +++ b/src/decode/c_extension.rs @@ -268,23 +268,11 @@ pub mod bit_16 { mod test_c { #[test] fn c_decode_test() { + use crate::decode::inst_16::test_16_in_rv64; use crate::instruction::c_extension::COpcode; - use crate::{Decode, Isa, OpcodeKind}; - let test_16 = |inst_16: u16, - op: OpcodeKind, - rd: Option, - rs1: Option, - rs2: Option, - imm: Option| { - let op_16 = inst_16.parse_opcode(Isa::Rv64).unwrap(); - assert!(matches!(&op_16, op)); - assert_eq!(inst_16.parse_rd(&op_16).unwrap(), rd); - assert_eq!(inst_16.parse_rs1(&op_16).unwrap(), rs1); - assert_eq!(inst_16.parse_rs2(&op_16).unwrap(), rs2); - assert_eq!(inst_16.parse_imm(&op_16, Isa::Rv64).unwrap(), imm); - }; + use crate::OpcodeKind; - test_16( + test_16_in_rv64( 0b0000_0000_0000_0001, OpcodeKind::C(COpcode::NOP), None, @@ -292,7 +280,7 @@ mod test_c { None, Some(0), ); - test_16( + test_16_in_rv64( 0b0110_0011_1000_0001, OpcodeKind::C(COpcode::LUI), Some(7), @@ -300,7 +288,7 @@ mod test_c { None, Some(0), ); - test_16( + test_16_in_rv64( 0b1000_0010_1100_0001, OpcodeKind::C(COpcode::SRAI), Some(13), @@ -308,7 +296,7 @@ mod test_c { None, Some(16), ); - test_16( + test_16_in_rv64( 0x4521, OpcodeKind::C(COpcode::LI), Some(10), @@ -316,7 +304,7 @@ mod test_c { None, Some(8), ); - test_16( + test_16_in_rv64( 0xb5e5, OpcodeKind::C(COpcode::J), None, @@ -324,7 +312,7 @@ mod test_c { None, Some(-280), ); - test_16( + test_16_in_rv64( 0x6105, OpcodeKind::C(COpcode::ADDI), Some(2), @@ -332,7 +320,7 @@ mod test_c { None, Some(32), ); - test_16( + test_16_in_rv64( 0x8082, OpcodeKind::C(COpcode::JR), None, @@ -340,7 +328,7 @@ mod test_c { Some(0), None, ); - test_16( + test_16_in_rv64( 0xe29d, OpcodeKind::C(COpcode::BNEZ), None, @@ -348,7 +336,7 @@ mod test_c { None, Some(38), ); - test_16( + test_16_in_rv64( 0xc05c, OpcodeKind::C(COpcode::SW), None, @@ -356,7 +344,7 @@ mod test_c { Some(15), Some(4), ); - test_16( + test_16_in_rv64( 0x9002, OpcodeKind::C(COpcode::EBREAK), None, @@ -364,7 +352,7 @@ mod test_c { None, None, ); - test_16( + test_16_in_rv64( 0x880a, OpcodeKind::C(COpcode::MV), Some(16), @@ -372,7 +360,7 @@ mod test_c { Some(2), None, ); - test_16( + test_16_in_rv64( 0x8585, OpcodeKind::C(COpcode::SRAI), Some(11), From 66c83bc147043228b16631d89f00de94f9df88cf Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 29 Jun 2025 16:34:46 +0900 Subject: [PATCH 5/9] [fix] correct wrong test cases --- src/decode/c_extension.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/decode/c_extension.rs b/src/decode/c_extension.rs index 505da7a..5b59a6b 100644 --- a/src/decode/c_extension.rs +++ b/src/decode/c_extension.rs @@ -290,7 +290,7 @@ mod test_c { ); test_16_in_rv64( 0b1000_0010_1100_0001, - OpcodeKind::C(COpcode::SRAI), + OpcodeKind::C(COpcode::SRLI), Some(13), Some(13), None, @@ -314,7 +314,7 @@ mod test_c { ); test_16_in_rv64( 0x6105, - OpcodeKind::C(COpcode::ADDI), + OpcodeKind::C(COpcode::ADDI16SP), Some(2), Some(2), None, From df98a2e7481c2efca061c848880c85e7e9fc343e Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 29 Jun 2025 16:48:19 +0900 Subject: [PATCH 6/9] [add] add testcase for U, J, B-type imm --- src/decode/base_i.rs | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/decode/base_i.rs b/src/decode/base_i.rs index d811f8f..070a773 100644 --- a/src/decode/base_i.rs +++ b/src/decode/base_i.rs @@ -348,28 +348,52 @@ mod test_basei { use crate::OpcodeKind; test_32_in_rv64( - 0b1000_0000_0000_0000_0000_0000_1011_0111, + 0xfdead737, OpcodeKind::BaseI(BaseIOpcode::LUI), - Some(1), + Some(14), None, None, - Some(0x8000_0000), + Some(0xfdead), ); test_32_in_rv64( - 0b0000_0000_0000_0000_0000_0010_1001_0111, + 0x1597, OpcodeKind::BaseI(BaseIOpcode::AUIPC), - Some(5), + Some(11), None, None, - Some(0), + Some(0x1), + ); + test_32_in_rv64( + 0x013f9517, + OpcodeKind::BaseI(BaseIOpcode::AUIPC), + Some(10), + None, + None, + Some(0x13f9), + ); + test_32_in_rv64( + 0x009bc097, + OpcodeKind::BaseI(BaseIOpcode::AUIPC), + Some(1), + None, + None, + Some(0x9bc), ); test_32_in_rv64( - 0b1111_1111_1001_1111_1111_0000_0110_1111, + 0x9d3ff0ef, OpcodeKind::BaseI(BaseIOpcode::JAL), - Some(0), + Some(1), None, None, - Some(-8), + Some(-1582), + ); + test_32_in_rv64( + 0x02e78263, + OpcodeKind::BaseI(BaseIOpcode::BEQ), + None, + Some(15), + Some(14), + Some(36), ); test_32_in_rv64( 0b1111_1110_0010_0000_1000_1110_1010_0011, From 814ac3bb02b9f8157f93379263c4bb675e3a224f Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 29 Jun 2025 16:51:57 +0900 Subject: [PATCH 7/9] [!][fix] fix decoding immediate in U-type --- src/decode/base_i.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/decode/base_i.rs b/src/decode/base_i.rs index 070a773..6be5892 100644 --- a/src/decode/base_i.rs +++ b/src/decode/base_i.rs @@ -273,7 +273,7 @@ pub mod bit_32 { #[allow(clippy::cast_possible_wrap)] #[allow(non_snake_case)] pub fn parse_imm(inst: u32, opkind: &BaseIOpcode, isa: Isa) -> Option { - let U_type = || (inst.slice(31, 12) << 12) as i32; + let U_type = || inst.slice(31, 12) as i32; let I_type = || { let imm32 = inst.slice(31, 20) as i32; inst.to_signed_nbit(imm32, 12) From a296d047255d1b996dfef8df87e2bd23bf30730f Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 29 Jun 2025 17:00:09 +0900 Subject: [PATCH 8/9] [refactor] allow unused function `test_(16|32)_in_rv32` --- src/decode/inst_16.rs | 4 ++-- src/decode/inst_32.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/decode/inst_16.rs b/src/decode/inst_16.rs index 7d16207..e49bc0e 100644 --- a/src/decode/inst_16.rs +++ b/src/decode/inst_16.rs @@ -178,10 +178,10 @@ pub fn test_16( location.line() ); } - #[cfg(test)] #[track_caller] -pub fn test_16_in_rv16( +#[allow(dead_code)] +pub fn test_16_in_rv32( inst_16: u16, op: OpcodeKind, rd: Option, diff --git a/src/decode/inst_32.rs b/src/decode/inst_32.rs index 2c91b9f..c176267 100644 --- a/src/decode/inst_32.rs +++ b/src/decode/inst_32.rs @@ -266,6 +266,7 @@ pub fn test_32( #[cfg(test)] #[track_caller] +#[allow(dead_code)] pub fn test_32_in_rv32( inst_32: u32, op: OpcodeKind, From 7a3714b6e6f8c033614a71bbd1dc590f8f624b3b Mon Sep 17 00:00:00 2001 From: Alingof Date: Sun, 29 Jun 2025 17:19:15 +0900 Subject: [PATCH 9/9] [update] update package version (v1.3.1 -> v1.3.2) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c181ae4..49cb53f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "raki" -version = "1.3.1" +version = "1.3.2" edition = "2021" authors = ["Norimasa Takana "] repository = "https://github.com/Alignof/raki"