#![expect(clippy::identity_op, reason = "Test readability")]
#![expect(clippy::unusual_byte_groupings, reason = "Test readability")]
use crate::instructions::Instruction;
use crate::instructions::rv32::c::zca::Rv32ZcaInstruction;
use crate::registers::general_purpose::{EReg, Reg};
const fn make_addi4spn(rd_prime: u16, nzuimm: u16) -> u16 {
let imm5_4 = (nzuimm >> 4) & 0b11;
let imm9_6 = (nzuimm >> 6) & 0xf;
let imm2 = (nzuimm >> 2) & 1;
let imm3 = (nzuimm >> 3) & 1;
(imm5_4 << 11) | (imm9_6 << 7) | (imm2 << 6) | (imm3 << 5) | (rd_prime << 2)
}
const fn make_cl_cs(
funct3: u16,
rs1p: u16,
imm6_bits: u16,
bit6: u16,
bit5: u16,
rd_rs2p: u16,
) -> u16 {
(funct3 << 13) | (imm6_bits << 10) | (rs1p << 7) | (bit6 << 6) | (bit5 << 5) | (rd_rs2p << 2)
}
const fn make_ci_q01(funct3: u16, rd: u16, imm6: u16) -> u16 {
let imm5 = (imm6 >> 5) & 1;
let imm4_0 = imm6 & 0x1f;
(funct3 << 13) | (imm5 << 12) | (rd << 7) | (imm4_0 << 2) | 0b01
}
const fn make_cj(funct3: u16, imm: i16) -> u16 {
let imm = imm.cast_unsigned();
let imm11 = (imm >> 11) & 1;
let imm4 = (imm >> 4) & 1;
let imm9_8 = (imm >> 8) & 0b11;
let imm10 = (imm >> 10) & 1;
let imm6 = (imm >> 6) & 1;
let imm7 = (imm >> 7) & 1;
let imm3_1 = (imm >> 1) & 0b111;
let imm5 = (imm >> 5) & 1;
(funct3 << 13)
| (imm11 << 12)
| (imm4 << 11)
| (imm9_8 << 9)
| (imm10 << 8)
| (imm6 << 7)
| (imm7 << 6)
| (imm3_1 << 3)
| (imm5 << 2)
| 0b01
}
const fn make_cb_branch(funct3: u16, rs1p: u16, imm: i16) -> u16 {
let imm = imm.cast_unsigned();
let imm8 = (imm >> 8) & 1;
let imm4_3 = (imm >> 3) & 0b11;
let imm7_6 = (imm >> 6) & 0b11;
let imm2_1 = (imm >> 1) & 0b11;
let imm5 = (imm >> 5) & 1;
(funct3 << 13)
| (imm8 << 12)
| (imm4_3 << 10)
| (rs1p << 7)
| (imm7_6 << 5)
| (imm5 << 2)
| (imm2_1 << 3)
| 0b01
}
const fn make_ca_arith(bit12: u16, rd_prime: u16, funct2b: u16, rs2_prime: u16) -> u16 {
(0b100 << 13)
| (bit12 << 12)
| (0b11 << 10)
| (rd_prime << 7)
| (funct2b << 5)
| (rs2_prime << 2)
| 0b01
}
const fn make_cr_q10(funct3: u16, bit12: u16, rs1: u16, rs2: u16) -> u16 {
(funct3 << 13) | (bit12 << 12) | (rs1 << 7) | (rs2 << 2) | 0b10
}
const fn make_swsp(rs2: u16, uimm: u8) -> u16 {
let uimm52 = ((uimm >> 2) & 0xf) as u16;
let uimm76 = ((uimm >> 6) & 0b11) as u16;
(0b110 << 13) | (uimm52 << 9) | (uimm76 << 7) | (rs2 << 2) | 0b10
}
#[test]
fn test_caddi4spn_basic() {
let inst = make_addi4spn(0, 4);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAddi4spn {
rd: Reg::S0,
nzuimm: 4
}
);
}
#[test]
fn test_caddi4spn_large_uimm() {
let inst = make_addi4spn(1, 1020);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAddi4spn {
rd: Reg::S1,
nzuimm: 1020
}
);
}
#[test]
fn test_caddi4spn_nzuimm0_nonzero_rd_reserved() {
let inst = 0x0004;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_clw_basic() {
let inst = make_cl_cs(0b010, 1, 0b000, 1, 0, 0);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLw {
rd: Reg::S0,
rs1: Reg::S1,
uimm: 4
}
);
}
#[test]
fn test_clw_max_uimm() {
let inst = make_cl_cs(0b010, 0, 0b111, 1, 1, 0);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLw {
rd: Reg::S0,
rs1: Reg::S0,
uimm: 124
}
);
}
#[test]
fn test_csw_basic() {
let inst = make_cl_cs(0b110, 0, 0b001, 0, 0, 1);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSw {
rs1: Reg::S0,
rs2: Reg::S1,
uimm: 8
}
);
}
#[test]
fn test_csw_max_uimm() {
let inst = make_cl_cs(0b110, 0, 0b111, 1, 1, 1);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSw {
rs1: Reg::S0,
rs2: Reg::S1,
uimm: 124
}
);
}
#[test]
fn test_q00_funct3_001_reserved() {
let inst = (0b001 << 13) | 0b00;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_q00_funct3_011_reserved_in_rv32() {
let inst = make_cl_cs(0b011, 0, 0b000, 0, 0, 0);
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).is_none());
}
#[test]
fn test_q00_funct3_100_reserved() {
let inst = (0b100 << 13) | 0b00;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_q00_funct3_111_reserved_in_rv32() {
let inst = make_cl_cs(0b111, 0, 0b000, 0, 0, 0);
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).is_none());
}
#[test]
fn test_cnop() {
let inst = 0b000_0_00000_00000_01;
assert_eq!(
Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap(),
Rv32ZcaInstruction::CNop
);
}
#[test]
fn test_caddi_positive() {
let inst = make_ci_q01(0b000, 10, 7);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAddi {
rd: Reg::A0,
nzimm: 7
}
);
}
#[test]
fn test_caddi_negative() {
let inst = make_ci_q01(0b000, 10, 0b111111);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAddi {
rd: Reg::A0,
nzimm: -1
}
);
}
#[test]
fn test_caddi_most_negative() {
let inst = make_ci_q01(0b000, 10, 0b100000);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAddi {
rd: Reg::A0,
nzimm: -32
}
);
}
#[test]
fn test_caddi_hint_rd0() {
let inst = make_ci_q01(0b000, 0, 5);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAddi {
rd: Reg::Zero,
nzimm: 5
}
);
}
#[test]
fn test_cjal_positive() {
let inst = make_cj(0b001, 256);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CJal { imm: 256 });
}
#[test]
fn test_cjal_negative() {
let inst = make_cj(0b001, -128);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CJal { imm: -128 });
}
#[test]
fn test_caddiw_does_not_exist_in_rv32() {
let inst = make_cj(0b001, 4);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert!(matches!(decoded, Rv32ZcaInstruction::CJal { .. }));
}
#[test]
fn test_cli() {
let inst = make_ci_q01(0b010, 10, 5);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLi {
rd: Reg::A0,
imm: 5
}
);
}
#[test]
fn test_cli_negative() {
let inst = make_ci_q01(0b010, 10, 0b111000);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLi {
rd: Reg::A0,
imm: -8
}
);
}
#[test]
fn test_cli_most_negative() {
let inst = make_ci_q01(0b010, 10, 0b100000);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLi {
rd: Reg::A0,
imm: -32
}
);
}
#[test]
fn test_cli_hint_rd0() {
let inst = make_ci_q01(0b010, 0, 3);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLi {
rd: Reg::Zero,
imm: 3
}
);
}
#[test]
fn test_caddi16sp() {
let inst = (0b011 << 13) | (0 << 12) | (2 << 7) | (1 << 6) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CAddi16sp { nzimm: 16 });
}
#[test]
fn test_caddi16sp_negative() {
let inst =
(0b011 << 13) | (1 << 12) | (2 << 7) | (1 << 6) | (1 << 5) | (0b11 << 3) | (1 << 2) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CAddi16sp { nzimm: -16 });
}
#[test]
fn test_caddi16sp_reserved_zero() {
let inst = (0b011 << 13) | (2 << 7) | 0b01;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_clui() {
let inst = (0b011 << 13) | (0 << 12) | (10 << 7) | (1 << 2) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLui {
rd: Reg::A0,
nzimm: 0x1000
}
);
}
#[test]
fn test_clui_negative() {
let inst = (0b011 << 13) | (1 << 12) | (10 << 7) | (0b11111 << 2) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLui {
rd: Reg::A0,
nzimm: -4096
}
);
}
#[test]
fn test_clui_reserved_zero() {
let inst = (0b011 << 13) | (0 << 12) | (10 << 7) | (0 << 2) | 0b01;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_csrli_basic() {
let inst = (0b100 << 13) | (0 << 12) | (0b00 << 10) | (0 << 7) | (4 << 2) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSrli {
rd: Reg::S0,
shamt: 4
}
);
}
#[test]
fn test_csrli_hint_shamt0() {
let inst = (0b100 << 13) | (0 << 12) | (0b00 << 10) | (0 << 7) | (0 << 2) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSrli {
rd: Reg::S0,
shamt: 0
}
);
}
#[test]
fn test_csrli_shamt5_reserved_in_rv32() {
let inst = (0b100 << 13) | (1 << 12) | (0b00 << 10) | (0 << 7) | (4 << 2) | 0b01;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_csrai_basic() {
let inst = (0b100 << 13) | (0 << 12) | (0b01 << 10) | (0 << 7) | (8 << 2) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSrai {
rd: Reg::S0,
shamt: 8
}
);
}
#[test]
fn test_csrai_hint_shamt0() {
let inst = (0b100 << 13) | (0 << 12) | (0b01 << 10) | (0 << 7) | (0 << 2) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSrai {
rd: Reg::S0,
shamt: 0
}
);
}
#[test]
fn test_csrai_shamt5_reserved_in_rv32() {
let inst = (0b100 << 13) | (1 << 12) | (0b01 << 10) | (0 << 7) | (4 << 2) | 0b01;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_candi() {
let inst = (0b100 << 13) | (1 << 12) | (0b10 << 10) | (0 << 7) | (0b11111 << 2) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAndi {
rd: Reg::S0,
imm: -1
}
);
}
#[test]
fn test_candi_most_negative() {
let inst = (0b100 << 13) | (1 << 12) | (0b10 << 10) | (0 << 7) | (0b00000 << 2) | 0b01;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAndi {
rd: Reg::S0,
imm: -32
}
);
}
#[test]
fn test_csub() {
let inst = make_ca_arith(0, 0, 0b00, 1);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSub {
rd: Reg::S0,
rs2: Reg::S1
}
);
}
#[test]
fn test_cxor() {
let inst = make_ca_arith(0, 0, 0b01, 1);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CXor {
rd: Reg::S0,
rs2: Reg::S1
}
);
}
#[test]
fn test_cor() {
let inst = make_ca_arith(0, 0, 0b10, 1);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::COr {
rd: Reg::S0,
rs2: Reg::S1
}
);
}
#[test]
fn test_cand() {
let inst = make_ca_arith(0, 0, 0b11, 1);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAnd {
rd: Reg::S0,
rs2: Reg::S1
}
);
}
#[test]
fn test_csubw_reserved_in_rv32() {
let inst = make_ca_arith(1, 0, 0b00, 1);
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).is_none());
}
#[test]
fn test_caddw_reserved_in_rv32() {
let inst = make_ca_arith(1, 0, 0b01, 1);
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).is_none());
}
#[test]
fn test_cj_positive() {
let inst = make_cj(0b101, 256);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CJ { imm: 256 });
}
#[test]
fn test_cj_negative() {
let inst = make_cj(0b101, -64);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CJ { imm: -64 });
}
#[test]
fn test_cbeqz_positive() {
let inst = make_cb_branch(0b110, 0, 8);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CBeqz {
rs1: Reg::S0,
imm: 8
}
);
}
#[test]
fn test_cbeqz_negative() {
let inst = make_cb_branch(0b110, 0, -8);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CBeqz {
rs1: Reg::S0,
imm: -8
}
);
}
#[test]
fn test_cbnez_positive() {
let inst = make_cb_branch(0b111, 1, 16);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CBnez {
rs1: Reg::S1,
imm: 16
}
);
}
#[test]
fn test_cslli_basic() {
let inst = (0b000 << 13) | (0 << 12) | (10 << 7) | (3 << 2) | 0b10;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSlli {
rd: Reg::A0,
shamt: 3
}
);
}
#[test]
fn test_cslli_hint_shamt0() {
let inst = (0b000 << 13) | (0 << 12) | (10 << 7) | (0 << 2) | 0b10;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSlli {
rd: Reg::A0,
shamt: 0
}
);
}
#[test]
fn test_cslli_hint_rd0() {
let inst = (0b000 << 13) | (0 << 12) | (0 << 7) | (3 << 2) | 0b10;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSlli {
rd: Reg::Zero,
shamt: 3
}
);
}
#[test]
fn test_cslli_shamt5_reserved_in_rv32() {
let inst = (0b000 << 13) | (1 << 12) | (10 << 7) | (3 << 2) | 0b10;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_clwsp_basic() {
let inst = (0b010 << 13) | (0 << 12) | (10 << 7) | (0b001 << 4) | (0 << 2) | 0b10;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLwsp {
rd: Reg::A0,
uimm: 4
}
);
}
#[test]
fn test_clwsp_max_uimm() {
let inst = (0b010 << 13) | (1 << 12) | (10 << 7) | (0b111 << 4) | (0b11 << 2) | 0b10;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLwsp {
rd: Reg::A0,
uimm: 252
}
);
}
#[test]
fn test_clwsp_reserved_rd0() {
let inst = (0b010 << 13) | (0 << 12) | (0 << 7) | (1 << 4) | 0b10;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_q10_funct3_001_reserved() {
let inst = (0b001 << 13) | (0 << 12) | (10 << 7) | (1 << 4) | 0b10;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_q10_funct3_011_reserved() {
let inst = (0b011 << 13) | (0 << 12) | (10 << 7) | (1 << 4) | 0b10;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_cjr() {
let inst = make_cr_q10(0b100, 0, 10, 0);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CJr { rs1: Reg::A0 });
}
#[test]
fn test_cjr_reserved_rs1_0() {
let inst = make_cr_q10(0b100, 0, 0, 0);
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).is_none());
}
#[test]
fn test_cmv() {
let inst = make_cr_q10(0b100, 0, 10, 11);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CMv {
rd: Reg::A0,
rs2: Reg::A1
}
);
}
#[test]
fn test_cmv_hint_rd0() {
let inst = make_cr_q10(0b100, 0, 0, 11);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CMv {
rd: Reg::Zero,
rs2: Reg::A1
}
);
}
#[test]
fn test_cmv_rs2_0_decodes_as_cjr() {
let inst = make_cr_q10(0b100, 0, 10, 0);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert!(matches!(decoded, Rv32ZcaInstruction::CJr { .. }));
}
#[test]
fn test_cebreak() {
let inst = make_cr_q10(0b100, 1, 0, 0);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CEbreak);
}
#[test]
fn test_cjalr() {
let inst = make_cr_q10(0b100, 1, 10, 0);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CJalr { rs1: Reg::A0 });
}
#[test]
fn test_cadd() {
let inst = make_cr_q10(0b100, 1, 10, 11);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAdd {
rd: Reg::A0,
rs2: Reg::A1
}
);
}
#[test]
fn test_cadd_hint_rd0() {
let inst = make_cr_q10(0b100, 1, 0, 11);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CAdd {
rd: Reg::Zero,
rs2: Reg::A1
}
);
}
#[test]
fn test_cswsp_basic() {
let inst = make_swsp(10, 4);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSwsp {
rs2: Reg::A0,
uimm: 4
}
);
}
#[test]
fn test_cswsp_max_uimm() {
let inst = make_swsp(10, 252);
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CSwsp {
rs2: Reg::A0,
uimm: 252
}
);
}
#[test]
fn test_q10_funct3_111_reserved() {
let inst = (0b111 << 13) | (0 << 12) | (10 << 7) | 0b10;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_cunimp() {
let inst = 0;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CUnimp);
}
#[test]
fn test_cunimp_ignores_upper_16_bits() {
let inst = 0xABCD_0000;
let decoded = Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).unwrap();
assert_eq!(decoded, Rv32ZcaInstruction::CUnimp);
}
#[test]
fn test_quadrant_11_invalid() {
let inst = 0x00000033;
assert!(Rv32ZcaInstruction::<Reg<u32>>::try_decode(inst).is_none());
}
#[test]
fn test_ereg_clw_valid() {
let inst = make_cl_cs(0b010, 0, 0b000, 1, 0, 0);
let decoded = Rv32ZcaInstruction::<EReg<u32>>::try_decode(u32::from(inst)).unwrap();
assert_eq!(
decoded,
Rv32ZcaInstruction::CLw {
rd: EReg::S0,
rs1: EReg::S0,
uimm: 4
}
);
}
#[test]
fn test_ereg_cslli_invalid_high_reg() {
let inst = (0b000 << 13) | (0 << 12) | (16 << 7) | (3 << 2) | 0b10;
assert!(Rv32ZcaInstruction::<EReg<u32>>::try_decode(inst).is_none());
}