use crate::*;
#[test]
fn test_rol_all_counts_8bit() {
for count in 0..=8 {
let code = [0xc0, 0xc0, count, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0xAB; emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = match count {
0 => 0xAB,
1 => 0x57, 2 => 0xAE, 3 => 0x5D, 4 => 0xBA, 5 => 0x75, 6 => 0xEA, 7 => 0xD5, 8 => 0xAB, _ => unreachable!(),
};
assert_eq!(emu.regs().rax & 0xFF, expected, "ROL AL by {} failed", count);
}
}
#[test]
fn test_ror_all_counts_8bit() {
for count in 0..=8 {
let code = [0xc0, 0xc8, count, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0xAB; emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = match count {
0 => 0xAB,
1 => 0xD5, 2 => 0xEA, 3 => 0x75, 4 => 0xBA, 5 => 0x5D, 6 => 0xAE, 7 => 0x57, 8 => 0xAB, _ => unreachable!(),
};
assert_eq!(emu.regs().rax & 0xFF, expected, "ROR AL by {} failed", count);
}
}
#[test]
fn test_rol_all_counts_16bit() {
for count in [0, 1, 4, 8, 12, 15, 16].iter() {
let code = [0x66, 0xc1, 0xc0, *count, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0x1234;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let result = emu.regs().rax & 0xFFFF;
if *count == 0 {
assert_eq!(result, 0x1234, "ROL AX by 0");
} else if *count == 16 {
assert_eq!(result, 0x1234, "ROL AX by 16 (full rotation)");
}
}
}
#[test]
fn test_ror_all_counts_16bit() {
for count in [0, 1, 4, 8, 12, 15, 16].iter() {
let code = [0x66, 0xc1, 0xc8, *count, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0x1234;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let result = emu.regs().rax & 0xFFFF;
if *count == 0 {
assert_eq!(result, 0x1234, "ROR AX by 0");
} else if *count == 16 {
assert_eq!(result, 0x1234, "ROR AX by 16 (full rotation)");
}
}
}
#[test]
fn test_rol_boundary_8bit() {
let test_values = [0x00, 0xFF, 0x01, 0x80];
for &value in &test_values {
let code = [0xc0, 0xc0, 0x01, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = value;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = ((value << 1) | (value >> 7)) & 0xFF;
assert_eq!(emu.regs().rax & 0xFF, expected, "ROL 0x{:02X} by 1", value);
}
}
#[test]
fn test_ror_boundary_8bit() {
let test_values = [0x00, 0xFF, 0x01, 0x80];
for &value in &test_values {
let code = [0xc0, 0xc8, 0x01, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = value;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = ((value >> 1) | (value << 7)) & 0xFF;
assert_eq!(emu.regs().rax & 0xFF, expected, "ROR 0x{:02X} by 1", value);
}
}
#[test]
fn test_rol_boundary_32bit() {
let test_values = [0x00000000, 0xFFFFFFFF, 0x00000001, 0x80000000];
for &value in &test_values {
let code = [0xc1, 0xc0, 0x01, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = value;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = ((value << 1) | (value >> 31)) & 0xFFFFFFFF;
assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "ROL 0x{:08X} by 1", value);
}
}
#[test]
fn test_ror_boundary_32bit() {
let test_values = [0x00000000, 0xFFFFFFFF, 0x00000001, 0x80000000];
for &value in &test_values {
let code = [0xc1, 0xc8, 0x01, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = value;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = ((value >> 1) | (value << 31)) & 0xFFFFFFFF;
assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "ROR 0x{:08X} by 1", value);
}
}
#[test]
fn test_rol_boundary_64bit() {
let test_values = [
0x0000000000000000,
0xFFFFFFFFFFFFFFFF,
0x0000000000000001,
0x8000000000000000,
];
for &value in &test_values {
let code = [0x48, 0xc1, 0xc0, 0x01, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = value;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = (value << 1) | (value >> 63);
assert_eq!(emu.regs().rax, expected, "ROL 0x{:016X} by 1", value);
}
}
#[test]
fn test_ror_boundary_64bit() {
let test_values = [
0x0000000000000000,
0xFFFFFFFFFFFFFFFF,
0x0000000000000001,
0x8000000000000000,
];
for &value in &test_values {
let code = [0x48, 0xc1, 0xc8, 0x01, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = value;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = (value >> 1) | (value << 63);
assert_eq!(emu.regs().rax, expected, "ROR 0x{:016X} by 1", value);
}
}
#[test]
fn test_rol_count_masking_8bit() {
let code = [0xd2, 0xc0, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0x12;
emu.regs_mut().rcx = 0x1F; emu.load_code_bytes(&code);
emu.run(None).unwrap();
let rax = emu.regs().rax;
let mut emu = emu64();
let code2 = [0xc0, 0xc0, 0x07, 0xf4];
emu.load_code_bytes(&code2);
emu.regs_mut().rax = 0x12;
emu.run(None).unwrap();
assert_eq!(rax & 0xFF, emu.regs().rax & 0xFF, "Count masking for 8-bit");
}
#[test]
fn test_ror_count_masking_8bit() {
let code = [0xd2, 0xc8, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0x12;
emu.regs_mut().rcx = 0x1F; emu.load_code_bytes(&code);
emu.run(None).unwrap();
let rax = emu.regs().rax;
let code2 = [0xc0, 0xc8, 0x07, 0xf4];
let mut emu = emu64();
emu.load_code_bytes(&code2);
emu.regs_mut().rax = 0x12;
emu.run(None).unwrap();
assert_eq!(rax & 0xFF, emu.regs().rax & 0xFF, "Count masking for 8-bit");
}
#[test]
fn test_rol_count_masking_32bit() {
let code = [0xd3, 0xc0, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0x12345678;
emu.regs_mut().rcx = 0x24; emu.load_code_bytes(&code);
emu.run(None).unwrap();
let rax = emu.regs().rax;
let code2 = [0xc1, 0xc0, 0x04, 0xf4];
let mut emu = emu64();
emu.load_code_bytes(&code2);
emu.regs_mut().rax = 0x12345678;
emu.run(None).unwrap();
assert_eq!(rax & 0xFFFFFFFF, emu.regs().rax & 0xFFFFFFFF, "Count masking for 32-bit");
}
#[test]
fn test_ror_count_masking_32bit() {
let code = [0xd3, 0xc8, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0x12345678;
emu.regs_mut().rcx = 0x24; emu.load_code_bytes(&code);
emu.run(None).unwrap();
let rax = emu.regs().rax;
let code2 = [0xc1, 0xc8, 0x04, 0xf4];
let mut emu = emu64();
emu.load_code_bytes(&code2);
emu.regs_mut().rax = 0x12345678;
emu.run(None).unwrap();
assert_eq!(rax & 0xFFFFFFFF, emu.regs().rax & 0xFFFFFFFF, "Count masking for 32-bit");
}
#[test]
fn test_rol_count_masking_64bit() {
let code = [0x48, 0xd3, 0xc0, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0x123456789ABCDEF0;
emu.regs_mut().rcx = 0x48; emu.load_code_bytes(&code);
emu.run(None).unwrap();
let rax = emu.regs().rax;
let code2 = [0x48, 0xc1, 0xc0, 0x08, 0xf4];
let mut emu = emu64();
emu.load_code_bytes(&code2);
emu.regs_mut().rax = 0x123456789ABCDEF0;
emu.run(None).unwrap();
assert_eq!(rax, emu.regs().rax, "Count masking for 64-bit");
}
#[test]
fn test_ror_count_masking_64bit() {
let code = [0x48, 0xd3, 0xc8, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0x123456789ABCDEF0;
emu.regs_mut().rcx = 0x48; emu.load_code_bytes(&code);
emu.run(None).unwrap();
let rax = emu.regs().rax;
let code2 = [0x48, 0xc1, 0xc8, 0x08, 0xf4];
let mut emu = emu64();
emu.load_code_bytes(&code2);
emu.regs_mut().rax = 0x123456789ABCDEF0;
emu.run(None).unwrap();
assert_eq!(rax, emu.regs().rax, "Count masking for 64-bit");
}
#[test]
fn test_rol_of_transitions() {
let test_cases = [
(0x00, false), (0x40, true), (0x80, false), (0xC0, true), ];
for (value, _expected_of) in &test_cases {
let code = [0xd0, 0xc0, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = *value as u64;
emu.load_code_bytes(&code);
let _regs = emu.run(None).unwrap();
}
}
#[test]
fn test_ror_of_transitions() {
let code = [0xd0, 0xc8, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0x01; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x80, "Result");
assert!(emu.flags().f_of, "OF for ROR with MSB change");
}
#[test]
fn test_rol_cf_all_bits() {
for bit_pos in 0..8 {
let value = 1u8 << bit_pos;
let code = [0xc0, 0xc0, 0x01, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = value as u64;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
if bit_pos == 7 {
assert!(emu.flags().f_cf, "CF should be set for bit 7");
} else {
assert!(!emu.flags().f_cf, "CF should be clear for bit {}", bit_pos);
}
}
}
#[test]
fn test_ror_cf_all_bits() {
for bit_pos in 0..8 {
let value = 1u8 << bit_pos;
let code = [0xc0, 0xc8, 0x01, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = value as u64;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
if bit_pos == 0 {
assert!(emu.flags().f_cf, "CF should be set for bit 0");
} else {
assert!(!emu.flags().f_cf, "CF should be clear for bit {}", bit_pos);
}
}
}
#[test]
fn test_rol_alternating_pattern() {
let code = [0xc0, 0xc0, 0x04, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0xAA; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0xAA, "Alternating pattern ROL 4");
}
#[test]
fn test_ror_alternating_pattern() {
let code = [0xc0, 0xc8, 0x04, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = 0xAA; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0xAA, "Alternating pattern ROR 4");
}
#[test]
fn test_rol_sequential_rotations() {
let code = [
0xc0, 0xc0, 0x01, 0xc0, 0xc0, 0x01, 0xc0, 0xc0, 0x01, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x12;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let rax = emu.regs().rax;
let code2 = [0xc0, 0xc0, 0x03, 0xf4];
let mut emu = emu64();
emu.load_code_bytes(&code2);
emu.regs_mut().rax = 0x12;
emu.run(None).unwrap();
assert_eq!(rax & 0xFF, emu.regs().rax & 0xFF, "Sequential rotations");
}
#[test]
fn test_rol_ror_identity() {
let code = [
0xc0, 0xc0, 0x05, 0xc0, 0xc8, 0x05, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x42;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x42, "ROL then ROR returns original");
}
#[test]
fn test_rol_power_of_two() {
for i in 0..8 {
let value = 1u8 << i;
let code = [0xc0, 0xc0, 0x03, 0xf4]; let mut emu = emu64();
emu.regs_mut().rax = value as u64;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = ((value << 3) | (value >> 5)) & 0xFF;
assert_eq!(emu.regs().rax & 0xFF, expected as u64, "ROL power of 2 value 0x{:02X}", value);
}
}