extern crate alloc;
use crate::instructions::Instruction;
use crate::instructions::test_utils::make_r_type;
use crate::instructions::v::zve64x::muldiv::Zve64xMulDivInstruction;
use crate::registers::general_purpose::Reg;
use crate::registers::vector::VReg;
use alloc::format;
const OP_V: u8 = 0b1010111;
const OPMVV: u8 = 0b010;
const OPMVX: u8 = 0b110;
const fn funct7(funct6: u8, vm: bool) -> u8 {
(funct6 << 1) | (vm as u8)
}
#[test]
fn test_vmul_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b100101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulVv {
vd: VReg::V1,
vs2: VReg::V3,
vs1: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vmul_vv_masked() {
let inst = make_r_type(OP_V, 4, OPMVV, 5, 6, funct7(0b100101, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulVv {
vd: VReg::V4,
vs2: VReg::V6,
vs1: VReg::V5,
vm: false,
})
);
}
#[test]
fn test_vmul_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b100101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulVx {
vd: VReg::V1,
vs2: VReg::V3,
rs1: Reg::Sp,
vm: true,
})
);
}
#[test]
fn test_vmulh_vv() {
let inst = make_r_type(OP_V, 8, OPMVV, 9, 10, funct7(0b100111, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulhVv {
vd: VReg::V8,
vs2: VReg::V10,
vs1: VReg::V9,
vm: true,
})
);
}
#[test]
fn test_vmulh_vx() {
let inst = make_r_type(OP_V, 8, OPMVX, 10, 12, funct7(0b100111, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulhVx {
vd: VReg::V8,
vs2: VReg::V12,
rs1: Reg::A0,
vm: false,
})
);
}
#[test]
fn test_vmulhu_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b100100, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulhuVv {
vd: VReg::V1,
vs2: VReg::V3,
vs1: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vmulhu_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b100100, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulhuVx {
vd: VReg::V1,
vs2: VReg::V3,
rs1: Reg::Sp,
vm: true,
})
);
}
#[test]
fn test_vmulhsu_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b100110, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulhsuVv {
vd: VReg::V1,
vs2: VReg::V3,
vs1: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vmulhsu_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b100110, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulhsuVx {
vd: VReg::V1,
vs2: VReg::V3,
rs1: Reg::Sp,
vm: false,
})
);
}
#[test]
fn test_vdivu_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b100000, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VdivuVv {
vd: VReg::V1,
vs2: VReg::V3,
vs1: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vdivu_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b100000, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VdivuVx {
vd: VReg::V1,
vs2: VReg::V3,
rs1: Reg::Sp,
vm: true,
})
);
}
#[test]
fn test_vdiv_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b100001, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VdivVv {
vd: VReg::V1,
vs2: VReg::V3,
vs1: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vdiv_vx_masked() {
let inst = make_r_type(OP_V, 16, OPMVX, 17, 18, funct7(0b100001, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VdivVx {
vd: VReg::V16,
vs2: VReg::V18,
rs1: Reg::A7,
vm: false,
})
);
}
#[test]
fn test_vremu_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b100010, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VremuVv {
vd: VReg::V1,
vs2: VReg::V3,
vs1: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vremu_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b100010, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VremuVx {
vd: VReg::V1,
vs2: VReg::V3,
rs1: Reg::Sp,
vm: true,
})
);
}
#[test]
fn test_vrem_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b100011, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VremVv {
vd: VReg::V1,
vs2: VReg::V3,
vs1: VReg::V2,
vm: true,
})
);
}
#[test]
fn test_vrem_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b100011, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VremVx {
vd: VReg::V1,
vs2: VReg::V3,
rs1: Reg::Sp,
vm: true,
})
);
}
#[test]
fn test_vwmulu_vv() {
let inst = make_r_type(OP_V, 2, OPMVV, 4, 6, funct7(0b111000, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmuluVv {
vd: VReg::V2,
vs2: VReg::V6,
vs1: VReg::V4,
vm: true,
})
);
}
#[test]
fn test_vwmulu_vx() {
let inst = make_r_type(OP_V, 2, OPMVX, 5, 6, funct7(0b111000, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmuluVx {
vd: VReg::V2,
vs2: VReg::V6,
rs1: Reg::T0,
vm: true,
})
);
}
#[test]
fn test_vwmulsu_vv() {
let inst = make_r_type(OP_V, 2, OPMVV, 4, 6, funct7(0b111010, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmulsuVv {
vd: VReg::V2,
vs2: VReg::V6,
vs1: VReg::V4,
vm: true,
})
);
}
#[test]
fn test_vwmulsu_vx() {
let inst = make_r_type(OP_V, 2, OPMVX, 5, 6, funct7(0b111010, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmulsuVx {
vd: VReg::V2,
vs2: VReg::V6,
rs1: Reg::T0,
vm: false,
})
);
}
#[test]
fn test_vwmul_vv() {
let inst = make_r_type(OP_V, 2, OPMVV, 4, 6, funct7(0b111011, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmulVv {
vd: VReg::V2,
vs2: VReg::V6,
vs1: VReg::V4,
vm: true,
})
);
}
#[test]
fn test_vwmul_vx() {
let inst = make_r_type(OP_V, 2, OPMVX, 5, 6, funct7(0b111011, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmulVx {
vd: VReg::V2,
vs2: VReg::V6,
rs1: Reg::T0,
vm: true,
})
);
}
#[test]
fn test_vmacc_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b101101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmaccVv {
vd: VReg::V1,
vs1: VReg::V2,
vs2: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vmacc_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 10, 3, funct7(0b101101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmaccVx {
vd: VReg::V1,
rs1: Reg::A0,
vs2: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vnmsac_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b101111, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VnmsacVv {
vd: VReg::V1,
vs1: VReg::V2,
vs2: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vnmsac_vx_masked() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b101111, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VnmsacVx {
vd: VReg::V1,
rs1: Reg::Sp,
vs2: VReg::V3,
vm: false,
})
);
}
#[test]
fn test_vmadd_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b101001, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmaddVv {
vd: VReg::V1,
vs1: VReg::V2,
vs2: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vmadd_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b101001, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmaddVx {
vd: VReg::V1,
rs1: Reg::Sp,
vs2: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vnmsub_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b101011, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VnmsubVv {
vd: VReg::V1,
vs1: VReg::V2,
vs2: VReg::V3,
vm: true,
})
);
}
#[test]
fn test_vnmsub_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b101011, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VnmsubVx {
vd: VReg::V1,
rs1: Reg::Sp,
vs2: VReg::V3,
vm: false,
})
);
}
#[test]
fn test_vwmaccu_vv() {
let inst = make_r_type(OP_V, 2, OPMVV, 4, 8, funct7(0b111100, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmaccuVv {
vd: VReg::V2,
vs1: VReg::V4,
vs2: VReg::V8,
vm: true,
})
);
}
#[test]
fn test_vwmaccu_vx() {
let inst = make_r_type(OP_V, 2, OPMVX, 10, 8, funct7(0b111100, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmaccuVx {
vd: VReg::V2,
rs1: Reg::A0,
vs2: VReg::V8,
vm: true,
})
);
}
#[test]
fn test_vwmacc_vv() {
let inst = make_r_type(OP_V, 2, OPMVV, 4, 8, funct7(0b111101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmaccVv {
vd: VReg::V2,
vs1: VReg::V4,
vs2: VReg::V8,
vm: true,
})
);
}
#[test]
fn test_vwmacc_vx() {
let inst = make_r_type(OP_V, 2, OPMVX, 10, 8, funct7(0b111101, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmaccVx {
vd: VReg::V2,
rs1: Reg::A0,
vs2: VReg::V8,
vm: false,
})
);
}
#[test]
fn test_vwmaccsu_vv() {
let inst = make_r_type(OP_V, 2, OPMVV, 4, 8, funct7(0b111111, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmaccsuVv {
vd: VReg::V2,
vs1: VReg::V4,
vs2: VReg::V8,
vm: true,
})
);
}
#[test]
fn test_vwmaccsu_vx() {
let inst = make_r_type(OP_V, 2, OPMVX, 10, 8, funct7(0b111111, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmaccsuVx {
vd: VReg::V2,
rs1: Reg::A0,
vs2: VReg::V8,
vm: true,
})
);
}
#[test]
fn test_vwmaccus_vx() {
let inst = make_r_type(OP_V, 2, OPMVX, 10, 8, funct7(0b111110, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VwmaccusVx {
vd: VReg::V2,
rs1: Reg::A0,
vs2: VReg::V8,
vm: true,
})
);
}
#[test]
fn test_vwmaccus_vv_does_not_exist() {
let inst = make_r_type(OP_V, 2, OPMVV, 4, 8, funct7(0b111110, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_vmul_vv_high_regs() {
let inst = make_r_type(OP_V, 31, OPMVV, 30, 29, funct7(0b100101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VmulVv {
vd: VReg::V31,
vs2: VReg::V29,
vs1: VReg::V30,
vm: true,
})
);
}
#[test]
fn test_vdiv_vx_high_regs() {
let inst = make_r_type(OP_V, 31, OPMVX, 31, 31, funct7(0b100001, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xMulDivInstruction::VdivVx {
vd: VReg::V31,
vs2: VReg::V31,
rs1: Reg::T6,
vm: true,
})
);
}
#[test]
fn test_wrong_opcode() {
let inst = make_r_type(0b0110011, 1, OPMVV, 2, 3, funct7(0b100101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_wrong_funct3() {
let inst = make_r_type(OP_V, 1, 0b000, 2, 3, funct7(0b100101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_invalid_funct6_opmvv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b101000, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_invalid_funct6_opmvx() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b111001, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_display_vmul_vv_unmasked() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b100101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{decoded}"), "vmul.vv v1, v3, v2");
}
#[test]
fn test_display_vmul_vv_masked() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b100101, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{decoded}"), "vmul.vv v1, v3, v2, v0.t");
}
#[test]
fn test_display_vmul_vx() {
let inst = make_r_type(OP_V, 1, OPMVX, 10, 3, funct7(0b100101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{decoded}"), "vmul.vx v1, v3, a0");
}
#[test]
fn test_display_vdivu_vv() {
let inst = make_r_type(OP_V, 8, OPMVV, 9, 10, funct7(0b100000, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{decoded}"), "vdivu.vv v8, v10, v9");
}
#[test]
fn test_display_vwmul_vv() {
let inst = make_r_type(OP_V, 2, OPMVV, 4, 6, funct7(0b111011, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{decoded}"), "vwmul.vv v2, v6, v4");
}
#[test]
fn test_display_vmacc_vv() {
let inst = make_r_type(OP_V, 1, OPMVV, 2, 3, funct7(0b101101, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{decoded}"), "vmacc.vv v1, v2, v3");
}
#[test]
fn test_display_vmacc_vx_masked() {
let inst = make_r_type(OP_V, 1, OPMVX, 10, 3, funct7(0b101101, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{decoded}"), "vmacc.vx v1, a0, v3, v0.t");
}
#[test]
fn test_display_vwmaccus_vx() {
let inst = make_r_type(OP_V, 2, OPMVX, 10, 8, funct7(0b111110, true));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{decoded}"), "vwmaccus.vx v2, a0, v8");
}
#[test]
fn test_display_vnmsub_vx_masked() {
let inst = make_r_type(OP_V, 1, OPMVX, 2, 3, funct7(0b101011, false));
let decoded = Zve64xMulDivInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{decoded}"), "vnmsub.vx v1, sp, v3, v0.t");
}