extern crate alloc;
use crate::instructions::Instruction;
use crate::instructions::test_utils::make_r_type;
use crate::instructions::v::zve64x::reduction::Zve64xReductionInstruction;
use crate::registers::general_purpose::Reg;
use crate::registers::vector::VReg;
use alloc::format;
fn make_v_arith(funct6: u8, vm: bool, vs2: u8, vs1: u8, funct3: u8, vd: u8) -> u32 {
let funct7 = (funct6 << 1) | (vm as u8);
make_r_type(0b1010111, vd, funct3, vs1, vs2, funct7)
}
#[test]
fn test_vredsum() {
let inst = make_v_arith(0b000000, true, 2, 1, 0b010, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredsum {
vd: VReg::V3,
vs2: VReg::V2,
vs1: VReg::V1,
vm: true,
})
);
}
#[test]
fn test_vredand() {
let inst = make_v_arith(0b000001, true, 4, 5, 0b010, 6);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredand {
vd: VReg::V6,
vs2: VReg::V4,
vs1: VReg::V5,
vm: true,
})
);
}
#[test]
fn test_vredor() {
let inst = make_v_arith(0b000010, true, 8, 9, 0b010, 10);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredor {
vd: VReg::V10,
vs2: VReg::V8,
vs1: VReg::V9,
vm: true,
})
);
}
#[test]
fn test_vredxor() {
let inst = make_v_arith(0b000011, true, 12, 13, 0b010, 14);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredxor {
vd: VReg::V14,
vs2: VReg::V12,
vs1: VReg::V13,
vm: true,
})
);
}
#[test]
fn test_vredminu() {
let inst = make_v_arith(0b000100, true, 16, 17, 0b010, 18);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredminu {
vd: VReg::V18,
vs2: VReg::V16,
vs1: VReg::V17,
vm: true,
})
);
}
#[test]
fn test_vredmin() {
let inst = make_v_arith(0b000101, true, 20, 21, 0b010, 22);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredmin {
vd: VReg::V22,
vs2: VReg::V20,
vs1: VReg::V21,
vm: true,
})
);
}
#[test]
fn test_vredmaxu() {
let inst = make_v_arith(0b000110, true, 24, 25, 0b010, 26);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredmaxu {
vd: VReg::V26,
vs2: VReg::V24,
vs1: VReg::V25,
vm: true,
})
);
}
#[test]
fn test_vredmax() {
let inst = make_v_arith(0b000111, true, 28, 29, 0b010, 30);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredmax {
vd: VReg::V30,
vs2: VReg::V28,
vs1: VReg::V29,
vm: true,
})
);
}
#[test]
fn test_vwredsumu() {
let inst = make_v_arith(0b110000, true, 2, 1, 0b000, 4);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vwredsumu {
vd: VReg::V4,
vs2: VReg::V2,
vs1: VReg::V1,
vm: true,
})
);
}
#[test]
fn test_vwredsum() {
let inst = make_v_arith(0b110001, true, 8, 4, 0b000, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vwredsum {
vd: VReg::V12,
vs2: VReg::V8,
vs1: VReg::V4,
vm: true,
})
);
}
#[test]
fn test_vredsum_masked() {
let inst = make_v_arith(0b000000, false, 2, 1, 0b010, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredsum {
vd: VReg::V3,
vs2: VReg::V2,
vs1: VReg::V1,
vm: false,
})
);
}
#[test]
fn test_vredand_masked() {
let inst = make_v_arith(0b000001, false, 4, 5, 0b010, 6);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredand {
vd: VReg::V6,
vs2: VReg::V4,
vs1: VReg::V5,
vm: false,
})
);
}
#[test]
fn test_vwredsumu_masked() {
let inst = make_v_arith(0b110000, false, 8, 4, 0b000, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vwredsumu {
vd: VReg::V12,
vs2: VReg::V8,
vs1: VReg::V4,
vm: false,
})
);
}
#[test]
fn test_vwredsum_masked() {
let inst = make_v_arith(0b110001, false, 2, 1, 0b000, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vwredsum {
vd: VReg::V3,
vs2: VReg::V2,
vs1: VReg::V1,
vm: false,
})
);
}
#[test]
fn test_vredsum_v0() {
let inst = make_v_arith(0b000000, true, 0, 0, 0b010, 0);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredsum {
vd: VReg::V0,
vs2: VReg::V0,
vs1: VReg::V0,
vm: true,
})
);
}
#[test]
fn test_vredmax_v31() {
let inst = make_v_arith(0b000111, true, 31, 31, 0b010, 31);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(
decoded,
Some(Zve64xReductionInstruction::Vredmax {
vd: VReg::V31,
vs2: VReg::V31,
vs1: VReg::V31,
vm: true,
})
);
}
#[test]
fn test_wrong_opcode() {
let funct7 = 1;
let inst = make_r_type(0b0110011, 3, 0b010, 1, 2, funct7);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_wrong_funct3_for_single_width() {
let inst = make_v_arith(0b000000, true, 2, 1, 0b001, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_wrong_funct3_for_widening() {
let inst = make_v_arith(0b110000, true, 2, 1, 0b010, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_invalid_funct6_opmvv() {
let inst = make_v_arith(0b001000, true, 2, 1, 0b010, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_invalid_funct6_opivv() {
let inst = make_v_arith(0b110010, true, 2, 1, 0b000, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_funct6_boundary_above_single_width() {
let inst = make_v_arith(0b001000, true, 2, 1, 0b010, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst);
assert_eq!(decoded, None);
}
#[test]
fn test_display_vredsum_unmasked() {
let inst = make_v_arith(0b000000, true, 2, 1, 0b010, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vredsum.vs v3, v2, v1");
}
#[test]
fn test_display_vredsum_masked() {
let inst = make_v_arith(0b000000, false, 2, 1, 0b010, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vredsum.vs v3, v2, v1, v0.t");
}
#[test]
fn test_display_vredand() {
let inst = make_v_arith(0b000001, true, 8, 4, 0b010, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vredand.vs v12, v8, v4");
}
#[test]
fn test_display_vredor() {
let inst = make_v_arith(0b000010, true, 8, 4, 0b010, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vredor.vs v12, v8, v4");
}
#[test]
fn test_display_vredxor() {
let inst = make_v_arith(0b000011, true, 8, 4, 0b010, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vredxor.vs v12, v8, v4");
}
#[test]
fn test_display_vredminu() {
let inst = make_v_arith(0b000100, true, 8, 4, 0b010, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vredminu.vs v12, v8, v4");
}
#[test]
fn test_display_vredmin() {
let inst = make_v_arith(0b000101, true, 8, 4, 0b010, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vredmin.vs v12, v8, v4");
}
#[test]
fn test_display_vredmaxu() {
let inst = make_v_arith(0b000110, true, 8, 4, 0b010, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vredmaxu.vs v12, v8, v4");
}
#[test]
fn test_display_vredmax() {
let inst = make_v_arith(0b000111, true, 8, 4, 0b010, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vredmax.vs v12, v8, v4");
}
#[test]
fn test_display_vwredsumu_unmasked() {
let inst = make_v_arith(0b110000, true, 8, 4, 0b000, 12);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vwredsumu.vs v12, v8, v4");
}
#[test]
fn test_display_vwredsum_masked() {
let inst = make_v_arith(0b110001, false, 2, 1, 0b000, 3);
let decoded = Zve64xReductionInstruction::<Reg<u64>>::try_decode(inst).unwrap();
assert_eq!(format!("{}", decoded), "vwredsum.vs v3, v2, v1, v0.t");
}