use crate::*;
#[test]
fn test_ror_al_1() {
let code = [
0xd0, 0xc8, 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, 0x21, "AL: 0x42 ROR 1 = 0x21");
assert!(!emu.flags().f_cf, "CF: receives LSB (was 0)");
assert!(!emu.flags().f_of, "OF: MSB XOR (MSB-1) = 0 XOR 0 = 0");
}
#[test]
fn test_ror_al_1_with_lsb() {
let code = [
0xd0, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x81; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0xC0, "AL: 0x81 ROR 1 = 0xC0 (LSB rotates to MSB)");
assert!(emu.flags().f_cf, "CF: receives LSB (was 1)");
assert!(!emu.flags().f_of, "OF: MSB XOR (MSB-1) = 1 XOR 1 = 0");
}
#[test]
fn test_ror_al_cl() {
let code = [
0xd2, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x10; emu.regs_mut().rcx = 0x04; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x01, "AL: 0x10 ROR 4 = 0x01");
assert!(!emu.flags().f_cf, "CF: last bit rotated was 0");
}
#[test]
fn test_ror_al_imm8() {
let code = [
0xc0, 0xc8, 0x03, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x88; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x11, "AL: 0x88 ROR 3 = 0x11");
assert!(!emu.flags().f_cf, "CF: last bit rotated was 0");
}
#[test]
fn test_ror_full_rotation_8bit() {
let code = [
0xc0, 0xc8, 0x08, 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, "AL: full rotation returns to original");
}
#[test]
fn test_ror_count_masked_8bit() {
let code = [
0xd2, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x88;
emu.regs_mut().rcx = 0x1B; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x11, "AL: rotation count masked");
}
#[test]
fn test_ror_count_zero_preserves_flags() {
let code = [
0xc0, 0xc8, 0x00, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x42;
emu.load_code_bytes(&code);
emu.flags_mut().load(0x2 | (1 << flags::F_CF) | (1 << flags::F_ZF) | (1 << flags::F_OF));
let initial_flags = emu.flags().dump();
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: unchanged");
assert_eq!(emu.flags().dump() & (flags::F_CF | flags::F_ZF | flags::F_OF),
initial_flags & (flags::F_CF | flags::F_ZF | flags::F_OF),
"Flags preserved");
}
#[test]
fn test_ror_bl() {
let code = [
0xd0, 0xcb, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rbx = 0xC5; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rbx & 0xFF, 0xE2, "BL: 0xC5 ROR 1 = 0xE2");
assert!(emu.flags().f_cf, "CF: LSB was 1");
}
#[test]
fn test_ror_cl_reg() {
let code = [
0xc0, 0xc9, 0x02, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rcx = 0xCC; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rcx & 0xFF, 0x33, "CL: 0xCC ROR 2 = 0x33");
}
#[test]
fn test_ror_dl() {
let code = [
0xd2, 0xca, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rdx = 0xF0;
emu.regs_mut().rcx = 0x04;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rdx & 0xFF, 0x0F, "DL: 0xF0 ROR 4 = 0x0F");
}
#[test]
fn test_ror_ax_1() {
let code = [
0x66, 0xd1, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x8642; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 0x4321, "AX: 0x8642 ROR 1 = 0x4321");
assert!(!emu.flags().f_cf, "CF: LSB was 0");
}
#[test]
fn test_ror_ax_cl() {
let code = [
0x66, 0xd3, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x1234;
emu.regs_mut().rcx = 0x04;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 0x4123, "AX: 0x1234 ROR 4 = 0x4123");
}
#[test]
fn test_ror_ax_imm8() {
let code = [
0x66, 0xc1, 0xc8, 0x08, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x1234;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 0x3412, "AX: 0x1234 ROR 8 = 0x3412 (byte swap)");
}
#[test]
fn test_ror_ax_full_rotation() {
let code = [
0x66, 0xc1, 0xc8, 0x10, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x1234;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: full rotation returns to original");
}
#[test]
fn test_ror_bx() {
let code = [
0x66, 0xd1, 0xcb, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rbx = 0x0001;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rbx & 0xFFFF, 0x8000, "BX: 0x0001 ROR 1 = 0x8000");
assert!(emu.flags().f_cf, "CF: LSB was 1");
}
#[test]
fn test_ror_cx() {
let code = [
0x66, 0xc1, 0xc9, 0x04, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rcx = 0xABCD;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rcx & 0xFFFF, 0xDABC, "CX: 0xABCD ROR 4 = 0xDABC");
}
#[test]
fn test_ror_dx_cl() {
let code = [
0x66, 0xd3, 0xca, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rdx = 0xFF00;
emu.regs_mut().rcx = 0x08;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rdx & 0xFFFF, 0x00FF, "DX: 0xFF00 ROR 8 = 0x00FF");
}
#[test]
fn test_ror_eax_1() {
let code = [
0xd1, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x86430ECA;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x43218765, "EAX: 0x86430ECA ROR 1 = 0x43218765");
}
#[test]
fn test_ror_eax_cl() {
let code = [
0xd3, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x12345678;
emu.regs_mut().rcx = 0x08;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78123456, "EAX: 0x12345678 ROR 8 = 0x78123456");
}
#[test]
fn test_ror_eax_imm8() {
let code = [
0xc1, 0xc8, 0x10, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x12345678;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x56781234, "EAX: 0x12345678 ROR 16 = 0x56781234");
}
#[test]
fn test_ror_eax_full_rotation() {
let code = [
0xc1, 0xc8, 0x20, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x12345678;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: full rotation returns to original");
}
#[test]
fn test_ror_ebx() {
let code = [
0xd1, 0xcb, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rbx = 0x00000001;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x80000000, "EBX: 0x00000001 ROR 1 = 0x80000000");
assert!(emu.flags().f_cf, "CF: LSB was 1");
}
#[test]
fn test_ror_ecx() {
let code = [
0xc1, 0xc9, 0x04, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rcx = 0xABCDEF01;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0x1ABCDEF0, "ECX: 0xABCDEF01 ROR 4 = 0x1ABCDEF0");
}
#[test]
fn test_ror_edx_cl() {
let code = [
0xd3, 0xca, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rdx = 0xFF000000;
emu.regs_mut().rcx = 0x18; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rdx & 0xFFFFFFFF, 0x000000FF, "EDX: 0xFF000000 ROR 24 = 0x000000FF");
}
#[test]
fn test_ror_esi() {
let code = [
0xd1, 0xce, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rsi = 0x80000000;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 0x40000000, "ESI: 0x80000000 ROR 1 = 0x40000000");
}
#[test]
fn test_ror_edi() {
let code = [
0xc1, 0xcf, 0x0C, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rdi = 0x12345678;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rdi & 0xFFFFFFFF, 0x67812345, "EDI: 0x12345678 ROR 12 = 0x67812345");
}
#[test]
fn test_ror_rax_1() {
let code = [
0x48, 0xd1, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x86430ECA86430ECA;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0x4321876543218765, "RAX: ROR 1");
}
#[test]
fn test_ror_rax_cl() {
let code = [
0x48, 0xd3, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x123456789ABCDEF0;
emu.regs_mut().rcx = 0x08;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0xF0123456789ABCDE, "RAX: 0x123456789ABCDEF0 ROR 8");
}
#[test]
fn test_ror_rax_imm8() {
let code = [
0x48, 0xc1, 0xc8, 0x10, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x123456789ABCDEF0;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0xDEF0123456789ABC, "RAX: 0x123456789ABCDEF0 ROR 16");
}
#[test]
fn test_ror_rax_32bits() {
let code = [
0x48, 0xc1, 0xc8, 0x20, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x123456789ABCDEF0;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0x9ABCDEF012345678, "RAX: ROR 32 swaps high/low dwords");
}
#[test]
fn test_ror_rax_full_rotation() {
let code = [
0x48, 0xc1, 0xc8, 0x40, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rax = 0x123456789ABCDEF0;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: full rotation returns to original");
}
#[test]
fn test_ror_rbx() {
let code = [
0x48, 0xd1, 0xcb, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rbx = 0x0000000000000001;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rbx, 0x8000000000000000, "RBX: 0x0000000000000001 ROR 1 = 0x8000000000000000");
assert!(emu.flags().f_cf, "CF: LSB was 1");
}
#[test]
fn test_ror_rcx() {
let code = [
0x48, 0xc1, 0xc9, 0x04, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rcx = 0xABCDEF0123456789;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rcx, 0x9ABCDEF012345678, "RCX: ROR 4");
}
#[test]
fn test_ror_rdx_cl() {
let code = [
0x48, 0xd3, 0xca, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rdx = 0xFF00000000000000;
emu.regs_mut().rcx = 0x38; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rdx, 0x00000000000000FF, "RDX: ROR 56");
}
#[test]
fn test_ror_rsi() {
let code = [
0x48, 0xd1, 0xce, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rsi = 0x8000000000000000;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rsi, 0x4000000000000000, "RSI: ROR 1");
}
#[test]
fn test_ror_rdi() {
let code = [
0x48, 0xc1, 0xcf, 0x0C, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().rdi = 0x123456789ABCDEF0;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rdi, 0xEF0123456789ABCD, "RDI: ROR 12");
}
#[test]
fn test_ror_r8() {
let code = [
0x49, 0xd1, 0xc8, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().r8 = 0xFEDCBA9876543210;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().r8, 0x7F6E5D4C3B2A1908, "R8: ROR 1");
assert!(!emu.flags().f_cf, "CF: LSB was 0");
}
#[test]
fn test_ror_r9_cl() {
let code = [
0x49, 0xd3, 0xc9, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().r9 = 0x0123456789ABCDEF;
emu.regs_mut().rcx = 0x10; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().r9, 0xCDEF0123456789AB, "R9: ROR 16");
}
#[test]
fn test_ror_r10_imm8() {
let code = [
0x49, 0xc1, 0xca, 0x08, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().r10 = 0x123456789ABCDEF0;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().r10, 0xF0123456789ABCDE, "R10: ROR 8");
}
#[test]
fn test_ror_r15() {
let code = [
0x49, 0xd1, 0xcf, 0xf4,
];
let mut emu = emu64();
emu.regs_mut().r15 = 0x2222222222222222;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().r15, 0x1111111111111111, "R15: ROR 1");
}
#[test]
fn test_ror_mem8() {
let DATA_ADDR = 0x7000;
let code = [
0xd0, 0x0c, 0x25, (DATA_ADDR & 0xFF) as u8,
((DATA_ADDR >> 8) & 0xFF) as u8,
((DATA_ADDR >> 16) & 0xFF) as u8,
((DATA_ADDR >> 24) & 0xFF) as u8,
0xf4,
];
let mut emu = emu64();
emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data");
emu.load_code_bytes(&code);
emu.maps.write_byte(DATA_ADDR, 0x81);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_byte(DATA_ADDR).unwrap(), 0xC0, "Memory: 0x81 ROR 1 = 0xC0");
assert!(emu.flags().f_cf, "CF: LSB was 1");
}
#[test]
fn test_ror_mem16() {
let DATA_ADDR = 0x7000;
let code = [
0x66, 0xc1, 0x0c, 0x25, (DATA_ADDR & 0xFF) as u8,
((DATA_ADDR >> 8) & 0xFF) as u8,
((DATA_ADDR >> 16) & 0xFF) as u8,
((DATA_ADDR >> 24) & 0xFF) as u8,
0x04, 0xf4,
];
let mut emu = emu64();
emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data");
emu.load_code_bytes(&code);
emu.maps.write_word(DATA_ADDR, 0x1234);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_word(DATA_ADDR).unwrap(), 0x4123, "Memory: 0x1234 ROR 4 = 0x4123");
}
#[test]
fn test_ror_mem32() {
let DATA_ADDR = 0x7000;
let code = [
0xd3, 0x0c, 0x25, (DATA_ADDR & 0xFF) as u8,
((DATA_ADDR >> 8) & 0xFF) as u8,
((DATA_ADDR >> 16) & 0xFF) as u8,
((DATA_ADDR >> 24) & 0xFF) as u8,
0xf4,
];
let mut emu = emu64();
emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data");
emu.regs_mut().rcx = 0x08;
emu.load_code_bytes(&code);
emu.maps.write_dword(DATA_ADDR, 0x12345678);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_dword(DATA_ADDR).unwrap(), 0x78123456, "Memory: 0x12345678 ROR 8 = 0x78123456");
}
#[test]
fn test_ror_mem64() {
let DATA_ADDR = 0x7000;
let code = [
0x48, 0xc1, 0x0c, 0x25, (DATA_ADDR & 0xFF) as u8,
((DATA_ADDR >> 8) & 0xFF) as u8,
((DATA_ADDR >> 16) & 0xFF) as u8,
((DATA_ADDR >> 24) & 0xFF) as u8,
0x10, 0xf4,
];
let mut emu = emu64();
emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data");
emu.load_code_bytes(&code);
emu.maps.write_qword(DATA_ADDR, 0x123456789ABCDEF0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_qword(DATA_ADDR).unwrap(), 0xDEF0123456789ABC, "Memory: ROR 16");
}