use crate::*;
const SCRATCH: u64 = 0x800000;
fn run_code(code: &[u8]) -> Emu {
let mut emu = emu64();
emu.load_code_bytes(code);
emu.maps
.create_map(
"scratch",
SCRATCH,
0x1000,
crate::maps::mem64::Permission::READ_WRITE,
)
.expect("scratch map");
emu.run(None).unwrap();
emu
}
#[test]
fn movhps_load_high_qword() {
let code = [
0x48, 0xc7, 0xc0, 0x00, 0x00, 0x80, 0x00, 0x48, 0xbb, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x48, 0x89, 0x18, 0x48, 0xb9, 0xef, 0xbe, 0xad, 0xde, 0xbe, 0xba, 0xfe, 0xca, 0x66, 0x48, 0x0f, 0x6e, 0xc1, 0x0f, 0x16, 0x00, 0xf4, ];
let emu = run_code(&code);
let xmm0 = emu.regs().get_xmm_by_name("xmm0");
assert_eq!(
xmm0, 0x1122334455667788_CAFEBABEDEADBEEFu128,
"movhps must load the full 64-bit qword into the high half (got {:032x})",
xmm0
);
}
#[test]
fn movlps_load_low_qword() {
let code = [
0x48, 0xc7, 0xc0, 0x00, 0x00, 0x80, 0x00, 0x48, 0xbb, 0x00, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x48, 0x89, 0x18, 0x48, 0xb9, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x66, 0x48, 0x0f, 0x6e, 0xc1, 0x66, 0x0f, 0x73, 0xf8, 0x08, 0x0f, 0x12, 0x00, 0xf4, ];
let emu = run_code(&code);
let xmm0 = emu.regs().get_xmm_by_name("xmm0");
assert_eq!(
xmm0, 0x1111111122222222_99AABBCCDDEEFF00u128,
"movlps must load the low qword and preserve the high half (got {:032x})",
xmm0
);
}
#[test]
fn movups_and_movhps_store() {
let code = [
0x48, 0xc7, 0xc0, 0x00, 0x00, 0x80, 0x00, 0x48, 0xbb, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x48, 0x89, 0x58, 0x10, 0x48, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x48, 0x89, 0x58, 0x18, 0x0f, 0x10, 0x40, 0x10, 0x0f, 0x17, 0x00, 0x0f, 0x11, 0x40, 0x20, 0xf4, ];
let emu = run_code(&code);
let xmm0 = emu.regs().get_xmm_by_name("xmm0");
assert_eq!(
xmm0, 0xBBBBBBBBBBBBBBBB_AAAAAAAAAAAAAAAAu128,
"movups load (got {:032x})",
xmm0
);
assert_eq!(
emu.maps.read_qword(SCRATCH).unwrap(),
0xBBBBBBBBBBBBBBBB,
"movhps store should write the high qword"
);
assert_eq!(emu.maps.read_qword(SCRATCH + 0x20).unwrap(), 0xAAAAAAAAAAAAAAAA);
assert_eq!(emu.maps.read_qword(SCRATCH + 0x28).unwrap(), 0xBBBBBBBBBBBBBBBB);
}
#[test]
fn movhpd_load_high_qword() {
let code = [
0x48, 0xc7, 0xc0, 0x00, 0x00, 0x80, 0x00, 0x48, 0xbb, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x48, 0x89, 0x18, 0x48, 0xb9, 0xef, 0xbe, 0xad, 0xde, 0xbe, 0xba, 0xfe, 0xca, 0x66, 0x48, 0x0f, 0x6e, 0xc1, 0x66, 0x0f, 0x16, 0x00, 0xf4, ];
let emu = run_code(&code);
let xmm0 = emu.regs().get_xmm_by_name("xmm0");
assert_eq!(
xmm0, 0x1122334455667788_CAFEBABEDEADBEEFu128,
"movhpd must load the full 64-bit qword into the high half (got {:032x})",
xmm0
);
}
#[test]
fn movlpd_load_low_qword() {
let code = [
0x48, 0xc7, 0xc0, 0x00, 0x00, 0x80, 0x00, 0x48, 0xbb, 0x00, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x48, 0x89, 0x18, 0x48, 0xb9, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x66, 0x48, 0x0f, 0x6e, 0xc1, 0x66, 0x0f, 0x73, 0xf8, 0x08, 0x66, 0x0f, 0x12, 0x00, 0xf4, ];
let emu = run_code(&code);
let xmm0 = emu.regs().get_xmm_by_name("xmm0");
assert_eq!(
xmm0, 0x1111111122222222_99AABBCCDDEEFF00u128,
"movlpd must load the low qword and preserve the high half (got {:032x})",
xmm0
);
}
#[test]
fn movhpd_movlpd_store() {
let code = [
0x48, 0xc7, 0xc0, 0x00, 0x00, 0x80, 0x00, 0x48, 0xbb, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x48, 0x89, 0x58, 0x10, 0x48, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x48, 0x89, 0x58, 0x18, 0x0f, 0x10, 0x40, 0x10, 0x66, 0x0f, 0x17, 0x00, 0x66, 0x0f, 0x13, 0x40, 0x08, 0xf4, ];
let emu = run_code(&code);
assert_eq!(
emu.maps.read_qword(SCRATCH).unwrap(),
0xBBBBBBBBBBBBBBBB,
"movhpd store should write the high qword"
);
assert_eq!(
emu.maps.read_qword(SCRATCH + 8).unwrap(),
0xAAAAAAAAAAAAAAAA,
"movlpd store should write the low qword"
);
}