extern crate alloc;
use crate::instructions::Instruction;
use crate::instructions::test_utils::make_r_type;
use crate::instructions::v::zve64x::mask::Zve64xMaskInstruction;
use crate::registers::general_purpose::Reg;
use crate::registers::vector::VReg;
use alloc::format;
fn make_vop(funct6: u8, vm: u8, vs2: u8, vs1: u8, funct3: u8, vd: u8) -> u32 {
let funct7 = (funct6 << 1) | (vm & 1);
make_r_type(0b1010111, vd, funct3, vs1, vs2, funct7)
}
#[test]
fn test_vmandn() {
let inst = make_vop(0b011000, 1, 2, 3, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmandn {
vd: VReg::V1,
vs2: VReg::V2,
vs1: VReg::V3,
})
);
}
#[test]
fn test_vmand() {
let inst = make_vop(0b011001, 1, 4, 5, 0b010, 6);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmand {
vd: VReg::V6,
vs2: VReg::V4,
vs1: VReg::V5,
})
);
}
#[test]
fn test_vmor() {
let inst = make_vop(0b011010, 1, 8, 9, 0b010, 10);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmor {
vd: VReg::V10,
vs2: VReg::V8,
vs1: VReg::V9,
})
);
}
#[test]
fn test_vmxor() {
let inst = make_vop(0b011011, 1, 12, 13, 0b010, 14);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmxor {
vd: VReg::V14,
vs2: VReg::V12,
vs1: VReg::V13,
})
);
}
#[test]
fn test_vmorn() {
let inst = make_vop(0b011100, 1, 16, 17, 0b010, 18);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmorn {
vd: VReg::V18,
vs2: VReg::V16,
vs1: VReg::V17,
})
);
}
#[test]
fn test_vmnand() {
let inst = make_vop(0b011101, 1, 20, 21, 0b010, 22);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmnand {
vd: VReg::V22,
vs2: VReg::V20,
vs1: VReg::V21,
})
);
}
#[test]
fn test_vmnor() {
let inst = make_vop(0b011110, 1, 24, 25, 0b010, 26);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmnor {
vd: VReg::V26,
vs2: VReg::V24,
vs1: VReg::V25,
})
);
}
#[test]
fn test_vmxnor() {
let inst = make_vop(0b011111, 1, 28, 29, 0b010, 30);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmxnor {
vd: VReg::V30,
vs2: VReg::V28,
vs1: VReg::V29,
})
);
}
#[test]
fn test_vmand_v0() {
let inst = make_vop(0b011001, 1, 0, 1, 0b010, 2);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmand {
vd: VReg::V2,
vs2: VReg::V0,
vs1: VReg::V1,
})
);
}
#[test]
fn test_mask_logical_rejects_vm0() {
let inst = make_vop(0b011001, 0, 2, 3, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_vcpop_unmasked() {
let inst = make_vop(0b010000, 1, 4, 0b10000, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vcpop {
rd: Reg::Ra,
vs2: VReg::V4,
vm: true,
})
);
}
#[test]
fn test_vcpop_masked() {
let inst = make_vop(0b010000, 0, 8, 0b10000, 0b010, 10);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vcpop {
rd: Reg::A0,
vs2: VReg::V8,
vm: false,
})
);
}
#[test]
fn test_vfirst_unmasked() {
let inst = make_vop(0b010000, 1, 5, 0b10001, 0b010, 2);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vfirst {
rd: Reg::Sp,
vs2: VReg::V5,
vm: true,
})
);
}
#[test]
fn test_vfirst_masked() {
let inst = make_vop(0b010000, 0, 12, 0b10001, 0b010, 5);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vfirst {
rd: Reg::T0,
vs2: VReg::V12,
vm: false,
})
);
}
#[test]
fn test_vmsbf_unmasked() {
let inst = make_vop(0b010100, 1, 3, 0b00001, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmsbf {
vd: VReg::V1,
vs2: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vmsbf_masked() {
let inst = make_vop(0b010100, 0, 7, 0b00001, 0b010, 2);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmsbf {
vd: VReg::V2,
vs2: VReg::V7,
vm: false,
})
);
}
#[test]
fn test_vmsof_unmasked() {
let inst = make_vop(0b010100, 1, 6, 0b00010, 0b010, 4);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmsof {
vd: VReg::V4,
vs2: VReg::V6,
vm: true,
})
);
}
#[test]
fn test_vmsof_masked() {
let inst = make_vop(0b010100, 0, 10, 0b00010, 0b010, 8);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmsof {
vd: VReg::V8,
vs2: VReg::V10,
vm: false,
})
);
}
#[test]
fn test_vmsif_unmasked() {
let inst = make_vop(0b010100, 1, 9, 0b00011, 0b010, 5);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmsif {
vd: VReg::V5,
vs2: VReg::V9,
vm: true,
})
);
}
#[test]
fn test_vmsif_masked() {
let inst = make_vop(0b010100, 0, 15, 0b00011, 0b010, 11);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmsif {
vd: VReg::V11,
vs2: VReg::V15,
vm: false,
})
);
}
#[test]
fn test_viota_unmasked() {
let inst = make_vop(0b010100, 1, 2, 0b10000, 0b010, 4);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Viota {
vd: VReg::V4,
vs2: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_viota_masked() {
let inst = make_vop(0b010100, 0, 6, 0b10000, 0b010, 8);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Viota {
vd: VReg::V8,
vs2: VReg::V6,
vm: false,
})
);
}
#[test]
fn test_vid_unmasked() {
let inst = make_vop(0b010100, 1, 0, 0b10001, 0b010, 3);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vid {
vd: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vid_masked() {
let inst = make_vop(0b010100, 0, 0, 0b10001, 0b010, 16);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vid {
vd: VReg::V16,
vm: false,
})
);
}
#[test]
fn test_wrong_opcode() {
let funct7 = (0b011001u8 << 1) | 1;
let inst = make_r_type(0b0110011, 1, 0b010, 2, 3, funct7);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_wrong_funct3_for_mask_logical() {
let inst = make_vop(0b011001, 1, 2, 3, 0b000, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_wrong_funct3_opivx() {
let inst = make_vop(0b010000, 1, 4, 0b10000, 0b100, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_vwxunary0_invalid_vs1() {
let inst = make_vop(0b010000, 1, 4, 0b00001, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_vmunary0_invalid_vs1() {
let inst = make_vop(0b010100, 1, 4, 0b00000, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_vmunary0_invalid_vs1_gap() {
let inst = make_vop(0b010100, 1, 4, 0b01000, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_unrelated_funct6() {
let inst = make_vop(0b000000, 1, 2, 3, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_display_vmand() {
let inst = make_vop(0b011001, 1, 2, 3, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vmand.mm v1, v2, v3");
}
#[test]
fn test_display_vmandn() {
let inst = make_vop(0b011000, 1, 4, 5, 0b010, 6);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vmandn.mm v6, v4, v5");
}
#[test]
fn test_display_vmxnor() {
let inst = make_vop(0b011111, 1, 0, 0, 0b010, 0);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vmxnor.mm v0, v0, v0");
}
#[test]
fn test_display_vcpop_unmasked() {
let inst = make_vop(0b010000, 1, 4, 0b10000, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vcpop.m ra, v4");
}
#[test]
fn test_display_vcpop_masked() {
let inst = make_vop(0b010000, 0, 4, 0b10000, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vcpop.m ra, v4, v0.t");
}
#[test]
fn test_display_vfirst_unmasked() {
let inst = make_vop(0b010000, 1, 8, 0b10001, 0b010, 10);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vfirst.m a0, v8");
}
#[test]
fn test_display_vmsbf_unmasked() {
let inst = make_vop(0b010100, 1, 3, 0b00001, 0b010, 1);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vmsbf.m v1, v3");
}
#[test]
fn test_display_vmsof_masked() {
let inst = make_vop(0b010100, 0, 6, 0b00010, 0b010, 4);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vmsof.m v4, v6, v0.t");
}
#[test]
fn test_display_vmsif_unmasked() {
let inst = make_vop(0b010100, 1, 9, 0b00011, 0b010, 5);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vmsif.m v5, v9");
}
#[test]
fn test_display_viota_masked() {
let inst = make_vop(0b010100, 0, 2, 0b10000, 0b010, 4);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "viota.m v4, v2, v0.t");
}
#[test]
fn test_display_vid_unmasked() {
let inst = make_vop(0b010100, 1, 0, 0b10001, 0b010, 3);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vid.v v3");
}
#[test]
fn test_display_vid_masked() {
let inst = make_vop(0b010100, 0, 0, 0b10001, 0b010, 16);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vid.v v16, v0.t");
}
#[test]
fn test_vmand_v31() {
let inst = make_vop(0b011001, 1, 31, 31, 0b010, 31);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vmand {
vd: VReg::V31,
vs2: VReg::V31,
vs1: VReg::V31,
})
);
}
#[test]
fn test_vcpop_rd_zero() {
let inst = make_vop(0b010000, 1, 4, 0b10000, 0b010, 0);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vcpop {
rd: Reg::Zero,
vs2: VReg::V4,
vm: true,
})
);
}
#[test]
fn test_vcpop_high_rd() {
let inst = make_vop(0b010000, 1, 31, 0b10000, 0b010, 31);
let decoded = Zve64xMaskInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMaskInstruction::Vcpop {
rd: Reg::T6,
vs2: VReg::V31,
vm: true,
})
);
}