extern crate alloc;
use crate::instructions::Instruction;
use crate::instructions::test_utils::make_r_type;
use crate::instructions::v::zve64x::widen_narrow::Zve64xWidenNarrowInstruction;
use crate::registers::general_purpose::Reg;
use crate::registers::vector::VReg;
use alloc::format;
const OP_V: u8 = 0b1010111;
const OPIVV: u8 = 0b000;
const OPMVV: u8 = 0b010;
const OPIVI: u8 = 0b011;
const OPIVX: u8 = 0b100;
const OPMVX: u8 = 0b110;
fn make_vop(funct6: u8, vs2: u8, vs1_or_rs1: u8, funct3: u8, vd: u8) -> u32 {
let funct7 = (funct6 << 1) | 1;
make_r_type(OP_V, vd, funct3, vs1_or_rs1, vs2, funct7)
}
fn make_vop_masked(funct6: u8, vs2: u8, vs1_or_rs1: u8, funct3: u8, vd: u8) -> u32 {
let funct7 = funct6 << 1;
make_r_type(OP_V, vd, funct3, vs1_or_rs1, vs2, funct7)
}
#[test]
fn test_vwaddu_vv() {
let inst = make_vop(0b110000, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwadduVv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vwaddu_vv_masked() {
let inst = make_vop_masked(0b110000, 4, 5, OPMVV, 8);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwadduVv {
vd: VReg::V8,
vs2: VReg::V4,
vs1: VReg::V5,
vm: false,
})
);
}
#[test]
fn test_vwaddu_vx() {
let inst = make_vop(0b110000, 2, 10, OPMVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwadduVx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::A0,
vm: true,
})
);
}
#[test]
fn test_vwadd_vv() {
let inst = make_vop(0b110001, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwaddVv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vwadd_vx() {
let inst = make_vop(0b110001, 2, 5, OPMVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwaddVx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::T0,
vm: true,
})
);
}
#[test]
fn test_vwsubu_vv() {
let inst = make_vop(0b110010, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwsubuVv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vwsubu_vx() {
let inst = make_vop(0b110010, 2, 10, OPMVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwsubuVx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::A0,
vm: true,
})
);
}
#[test]
fn test_vwsub_vv() {
let inst = make_vop(0b110011, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwsubVv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vwsub_vx() {
let inst = make_vop(0b110011, 2, 5, OPMVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwsubVx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::T0,
vm: true,
})
);
}
#[test]
fn test_vwaddu_wv() {
let inst = make_vop(0b110100, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwadduWv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vwaddu_wx() {
let inst = make_vop(0b110100, 2, 10, OPMVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwadduWx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::A0,
vm: true,
})
);
}
#[test]
fn test_vwadd_wv() {
let inst = make_vop(0b110101, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwaddWv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vwadd_wx() {
let inst = make_vop(0b110101, 2, 5, OPMVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwaddWx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::T0,
vm: true,
})
);
}
#[test]
fn test_vwsubu_wv() {
let inst = make_vop(0b110110, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwsubuWv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vwsubu_wx() {
let inst = make_vop(0b110110, 2, 10, OPMVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwsubuWx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::A0,
vm: true,
})
);
}
#[test]
fn test_vwsub_wv() {
let inst = make_vop(0b110111, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwsubWv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vwsub_wx() {
let inst = make_vop(0b110111, 2, 5, OPMVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwsubWx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::T0,
vm: true,
})
);
}
#[test]
fn test_vwsub_wx_masked() {
let inst = make_vop_masked(0b110111, 4, 11, OPMVX, 8);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwsubWx {
vd: VReg::V8,
vs2: VReg::V4,
rs1: Reg::A1,
vm: false,
})
);
}
#[test]
fn test_vnsrl_wv() {
let inst = make_vop(0b101100, 2, 3, OPIVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsrlWv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vnsrl_wx() {
let inst = make_vop(0b101100, 2, 10, OPIVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsrlWx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::A0,
vm: true,
})
);
}
#[test]
fn test_vnsrl_wi() {
let inst = make_vop(0b101100, 2, 3, OPIVI, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsrlWi {
vd: VReg::V1,
vs2: VReg::V2,
uimm: 3,
vm: true,
})
);
}
#[test]
fn test_vnsrl_wi_max_uimm() {
let inst = make_vop(0b101100, 4, 31, OPIVI, 8);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsrlWi {
vd: VReg::V8,
vs2: VReg::V4,
uimm: 31,
vm: true,
})
);
}
#[test]
fn test_vnsrl_wv_masked() {
let inst = make_vop_masked(0b101100, 2, 3, OPIVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsrlWv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: false,
})
);
}
#[test]
fn test_vnsra_wv() {
let inst = make_vop(0b101101, 2, 3, OPIVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsraWv {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vnsra_wx() {
let inst = make_vop(0b101101, 2, 10, OPIVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsraWx {
vd: VReg::V1,
vs2: VReg::V2,
rs1: Reg::A0,
vm: true,
})
);
}
#[test]
fn test_vnsra_wi() {
let inst = make_vop(0b101101, 2, 5, OPIVI, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsraWi {
vd: VReg::V1,
vs2: VReg::V2,
uimm: 5,
vm: true,
})
);
}
#[test]
fn test_vnsra_wi_masked() {
let inst = make_vop_masked(0b101101, 4, 7, OPIVI, 16);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsraWi {
vd: VReg::V16,
vs2: VReg::V4,
uimm: 7,
vm: false,
})
);
}
#[test]
fn test_vzext_vf2() {
let inst = make_vop(0b010010, 2, 0b00110, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VzextVf2 {
vd: VReg::V1,
vs2: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vzext_vf4() {
let inst = make_vop(0b010010, 4, 0b00100, OPMVV, 8);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VzextVf4 {
vd: VReg::V8,
vs2: VReg::V4,
vm: true,
})
);
}
#[test]
fn test_vzext_vf8() {
let inst = make_vop(0b010010, 2, 0b00010, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VzextVf8 {
vd: VReg::V1,
vs2: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vzext_vf2_masked() {
let inst = make_vop_masked(0b010010, 2, 0b00110, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VzextVf2 {
vd: VReg::V1,
vs2: VReg::V2,
vm: false,
})
);
}
#[test]
fn test_vsext_vf2() {
let inst = make_vop(0b010010, 2, 0b00111, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VsextVf2 {
vd: VReg::V1,
vs2: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vsext_vf4() {
let inst = make_vop(0b010010, 4, 0b00101, OPMVV, 8);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VsextVf4 {
vd: VReg::V8,
vs2: VReg::V4,
vm: true,
})
);
}
#[test]
fn test_vsext_vf8() {
let inst = make_vop(0b010010, 2, 0b00011, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VsextVf8 {
vd: VReg::V1,
vs2: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vsext_vf8_masked() {
let inst = make_vop_masked(0b010010, 16, 0b00011, OPMVV, 24);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VsextVf8 {
vd: VReg::V24,
vs2: VReg::V16,
vm: false,
})
);
}
#[test]
fn test_wrong_opcode() {
let inst = make_vop(0b110000, 2, 3, OPMVV, 1) & !0x7f | 0b0110011;
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_widening_add_wrong_funct3() {
let inst = make_vop(0b110000, 2, 3, OPIVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_narrowing_shift_wrong_funct3() {
let inst = make_vop(0b101100, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_extension_wrong_funct3() {
let inst = make_vop(0b010010, 2, 0b00110, OPIVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_extension_invalid_vs1() {
let inst = make_vop(0b010010, 2, 0b00000, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_extension_reserved_vs1() {
let inst = make_vop(0b010010, 2, 0b00001, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_unknown_funct6() {
let inst = make_vop(0b111111, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_vwaddu_vv_high_regs() {
let inst = make_vop(0b110000, 30, 31, OPMVV, 28);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VwadduVv {
vd: VReg::V28,
vs2: VReg::V30,
vs1: VReg::V31,
vm: true,
})
);
}
#[test]
fn test_vnsrl_wx_high_regs() {
let inst = make_vop(0b101100, 24, 31, OPIVX, 16);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xWidenNarrowInstruction::VnsrlWx {
vd: VReg::V16,
vs2: VReg::V24,
rs1: Reg::T6,
vm: true,
})
);
}
#[test]
fn test_display_vwaddu_vv_unmasked() {
let inst = make_vop(0b110000, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vwaddu.vv v1, v2, v3");
}
#[test]
fn test_display_vwaddu_vv_masked() {
let inst = make_vop_masked(0b110000, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vwaddu.vv v1, v2, v3, v0.t");
}
#[test]
fn test_display_vwadd_vx() {
let inst = make_vop(0b110001, 4, 10, OPMVX, 8);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vwadd.vx v8, v4, a0");
}
#[test]
fn test_display_vwsub_wv() {
let inst = make_vop(0b110111, 2, 3, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vwsub.wv v1, v2, v3");
}
#[test]
fn test_display_vnsrl_wi() {
let inst = make_vop(0b101100, 4, 3, OPIVI, 2);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vnsrl.wi v2, v4, 3");
}
#[test]
fn test_display_vnsra_wx_masked() {
let inst = make_vop_masked(0b101101, 2, 10, OPIVX, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vnsra.wx v1, v2, a0, v0.t");
}
#[test]
fn test_display_vzext_vf2() {
let inst = make_vop(0b010010, 2, 0b00110, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vzext.vf2 v1, v2");
}
#[test]
fn test_display_vsext_vf4_masked() {
let inst = make_vop_masked(0b010010, 4, 0b00101, OPMVV, 8);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vsext.vf4 v8, v4, v0.t");
}
#[test]
fn test_display_vzext_vf8() {
let inst = make_vop(0b010010, 2, 0b00010, OPMVV, 1);
let decoded = Zve64xWidenNarrowInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vzext.vf8 v1, v2");
}