use crate::RegisterFile;
use crate::rv64::test_utils::{execute, initialize_state};
use ab_riscv_primitives::prelude::*;
#[test]
fn test_clmul_simple() {
let mut state = initialize_state([Rv64ZbcInstruction::Clmul {
rd: Reg::A2,
rs1: Reg::A0,
rs2: Reg::A1,
}]);
state.regs.write(Reg::A0, 0b1010);
state.regs.write(Reg::A1, 0b1100);
execute(&mut state).unwrap();
assert_eq!(state.regs.read(Reg::A2), 0b1111000);
}
#[test]
fn test_clmul_zero() {
let mut state = initialize_state([Rv64ZbcInstruction::Clmul {
rd: Reg::A2,
rs1: Reg::A0,
rs2: Reg::A1,
}]);
state.regs.write(Reg::A0, 0xFFFF_FFFF_FFFF_FFFFu64);
state.regs.write(Reg::A1, 0);
execute(&mut state).unwrap();
assert_eq!(state.regs.read(Reg::A2), 0);
}
#[test]
fn test_clmul_identity() {
let mut state = initialize_state([Rv64ZbcInstruction::Clmul {
rd: Reg::A2,
rs1: Reg::A0,
rs2: Reg::A1,
}]);
state.regs.write(Reg::A0, 0x1234_5678_9ABC_DEF0u64);
state.regs.write(Reg::A1, 1);
execute(&mut state).unwrap();
assert_eq!(state.regs.read(Reg::A2), 0x1234_5678_9ABC_DEF0u64);
}
#[test]
fn test_clmulh_simple() {
let mut state = initialize_state([Rv64ZbcInstruction::Clmulh {
rd: Reg::A2,
rs1: Reg::A0,
rs2: Reg::A1,
}]);
state.regs.write(Reg::A0, 0xFFFF_FFFF_FFFF_FFFFu64);
state.regs.write(Reg::A1, 0xFFFF_FFFF_FFFF_FFFFu64);
execute(&mut state).unwrap();
assert_eq!(state.regs.read(Reg::A2), 0x5555_5555_5555_5555u64);
}
#[test]
fn test_clmulh_zero() {
let mut state = initialize_state([Rv64ZbcInstruction::Clmulh {
rd: Reg::A2,
rs1: Reg::A0,
rs2: Reg::A1,
}]);
state.regs.write(Reg::A0, 0xFFFF_FFFF_FFFF_FFFFu64);
state.regs.write(Reg::A1, 0);
execute(&mut state).unwrap();
assert_eq!(state.regs.read(Reg::A2), 0);
}
#[test]
fn test_clmulr_simple() {
let mut state = initialize_state([Rv64ZbcInstruction::Clmulr {
rd: Reg::A2,
rs1: Reg::A0,
rs2: Reg::A1,
}]);
state.regs.write(Reg::A0, 0b1010);
state.regs.write(Reg::A1, 0b1100);
execute(&mut state).unwrap();
assert_eq!(state.regs.read(Reg::A2), 0);
}
#[test]
fn test_clmulr_with_high_bits() {
let mut state = initialize_state([Rv64ZbcInstruction::Clmulr {
rd: Reg::A2,
rs1: Reg::A0,
rs2: Reg::A1,
}]);
state.regs.write(Reg::A0, 0x8000_0000_0000_0000u64);
state.regs.write(Reg::A1, 0x8000_0000_0000_0000u64);
execute(&mut state).unwrap();
assert_eq!(state.regs.read(Reg::A2), 0x8000_0000_0000_0000u64);
}
#[test]
fn test_clmulr_all_ones() {
let mut state = initialize_state([Rv64ZbcInstruction::Clmulr {
rd: Reg::A2,
rs1: Reg::A0,
rs2: Reg::A1,
}]);
state.regs.write(Reg::A0, 0xFFFF_FFFF_FFFF_FFFFu64);
state.regs.write(Reg::A1, 0xFFFF_FFFF_FFFF_FFFFu64);
execute(&mut state).unwrap();
assert_eq!(state.regs.read(Reg::A2), 0xAAAA_AAAA_AAAA_AAAAu64);
}
#[test]
fn test_clmul_combination() {
let mut state = initialize_state([
Rv64ZbcInstruction::Clmul {
rd: Reg::A2,
rs1: Reg::A0,
rs2: Reg::A1,
},
Rv64ZbcInstruction::Clmulh {
rd: Reg::A3,
rs1: Reg::A0,
rs2: Reg::A1,
},
]);
state.regs.write(Reg::A0, 0x1234_5678u64);
state.regs.write(Reg::A1, 0xABCD_EF01u64);
execute(&mut state).unwrap();
let low = state.regs.read(Reg::A2);
let high = state.regs.read(Reg::A3);
assert!(low != 0 || high != 0);
}