use crate::*;
const DATA_ADDR: u64 = 0x2000;
fn write_f64(mem: u64, addr: u64, value: f64) {
let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes());
}
fn read_f64(mem: u64, addr: u64) -> f64 {
let emu = emu64(); let mut buf = [0u8; 8];
emu.maps.read_bytes_buff(&mut buf, addr);
f64::from_le_bytes(buf)
}
#[test]
fn test_fcmovb_when_cf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xF9, 0xDA, 0xC1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmovb_when_cf_clear() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xF8, 0xDA, 0xC1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); }
#[test]
fn test_fcmovb_st2() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xF9, 0xDA, 0xC2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.maps.write_f64(DATA_ADDR + 16, 3.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0);
}
#[test]
fn test_fcmovb_after_cmp() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xBB, 0x02, 0x00, 0x00, 0x00, 0x39, 0xD8, 0xDA, 0xC1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 5.0);
emu.maps.write_f64(DATA_ADDR + 8, 10.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 5.0); }
#[test]
fn test_fcmove_when_zf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x05, 0x00, 0x00, 0x00, 0xBB, 0x05, 0x00, 0x00, 0x00, 0x39, 0xD8, 0xDA, 0xC9, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmove_when_zf_clear() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xBB, 0x02, 0x00, 0x00, 0x00, 0x39, 0xD8, 0xDA, 0xC9, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); }
#[test]
fn test_fcmove_st3() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, 0xB8, 0x07, 0x00, 0x00, 0x00, 0xBB, 0x07, 0x00, 0x00, 0x00, 0x39, 0xD8, 0xDA, 0xCB, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.maps.write_f64(DATA_ADDR + 16, 3.0);
emu.maps.write_f64(DATA_ADDR + 24, 4.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmovbe_when_cf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xF9, 0xDA, 0xD1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmovbe_when_zf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x03, 0x00, 0x00, 0x00, 0x3D, 0x03, 0x00, 0x00, 0x00, 0xDA, 0xD1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmovbe_when_neither_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x05, 0x00, 0x00, 0x00, 0x3D, 0x02, 0x00, 0x00, 0x00, 0xDA, 0xD1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); }
#[test]
fn test_fcmovu_when_pf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB0, 0x03, 0xA8, 0xFF, 0xDA, 0xD9, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmovu_when_pf_clear() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB0, 0x07, 0xA8, 0xFF, 0xDA, 0xD9, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); }
#[test]
fn test_fcmovnb_when_cf_clear() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xF8, 0xDB, 0xC1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmovnb_when_cf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xF9, 0xDB, 0xC1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); }
#[test]
fn test_fcmovnb_after_cmp_greater() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x05, 0x00, 0x00, 0x00, 0xBB, 0x02, 0x00, 0x00, 0x00, 0x39, 0xD8, 0xDB, 0xC1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 5.0);
emu.maps.write_f64(DATA_ADDR + 8, 10.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 5.0); }
#[test]
fn test_fcmovne_when_zf_clear() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xBB, 0x02, 0x00, 0x00, 0x00, 0x39, 0xD8, 0xDB, 0xC9, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmovne_when_zf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x05, 0x00, 0x00, 0x00, 0xBB, 0x05, 0x00, 0x00, 0x00, 0x39, 0xD8, 0xDB, 0xC9, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); }
#[test]
fn test_fcmovnbe_when_neither_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x05, 0x00, 0x00, 0x00, 0x3D, 0x02, 0x00, 0x00, 0x00, 0xDB, 0xD1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmovnbe_when_cf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xF9, 0xDB, 0xD1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); }
#[test]
fn test_fcmovnbe_when_zf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x03, 0x00, 0x00, 0x00, 0x3D, 0x03, 0x00, 0x00, 0x00, 0xDB, 0xD1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); }
#[test]
fn test_fcmovnu_when_pf_clear() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB0, 0x07, 0xA8, 0xFF, 0xDB, 0xD9, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); }
#[test]
fn test_fcmovnu_when_pf_set() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB0, 0x03, 0xA8, 0xFF, 0xDB, 0xD9, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); }
#[test]
fn test_fcmov_chain() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xF8, 0xDA, 0xC1, 0xF9, 0xDB, 0xC2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.maps.write_f64(DATA_ADDR + 16, 3.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 3.0); }
#[test]
fn test_fcmov_preserves_other_registers() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xF9, 0xDA, 0xC1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.maps.write_f64(DATA_ADDR + 16, 3.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0); assert_eq!(emu.maps.read_f64(0x3008).unwrap(), 2.0); assert_eq!(emu.maps.read_f64(0x3010).unwrap(), 1.0); }
#[test]
fn test_fcmov_with_arithmetic() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xBB, 0x02, 0x00, 0x00, 0x00, 0x39, 0xD8, 0xDA, 0xC1, 0xDE, 0xC1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 10.0);
emu.maps.write_f64(DATA_ADDR + 8, 20.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 20.0); }
#[test]
fn test_fcmov_all_conditions() {
let mut emu = emu64(); let code = [
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xF9, 0xDA, 0xC1, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8,
0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xB8, 0x05, 0x00, 0x00, 0x00, 0x3D, 0x05, 0x00, 0x00, 0x00, 0xDA, 0xC9, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xDD, 0xD8,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_f64(DATA_ADDR, 1.0);
emu.maps.write_f64(DATA_ADDR + 8, 2.0);
emu.maps.write_f64(DATA_ADDR + 16, 3.0);
emu.run(None).unwrap();
assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1.0); assert_eq!(emu.maps.read_f64(0x3008).unwrap(), 1.0); }