use std::num::Wrapping;
use crate::machine::Machine;
use crate::cpu::{Flags, R, Segment};
use crate::memory::MMU;
#[test]
fn can_execute_push_pop() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x88, 0x88, 0x8E, 0xD8, 0x1E, 0x07, ];
machine.load_executable(&code);
machine.execute_instruction(); machine.execute_instruction();
assert_eq!(0xFFFC, machine.cpu.get_r16(R::SP));
machine.execute_instruction(); assert_eq!(0xFFFA, machine.cpu.get_r16(R::SP));
machine.execute_instruction(); assert_eq!(0xFFFC, machine.cpu.get_r16(R::SP));
assert_eq!(0x8888, machine.cpu.get_r16(R::AX));
assert_eq!(0x8888, machine.cpu.get_r16(R::DS));
assert_eq!(0x8888, machine.cpu.get_r16(R::ES));
}
#[test]
fn can_execute_inc32() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x66, 0xB8, 0xFF, 0xFF, 0x00, 0x80, 0x66, 0x40, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x8001_0000, machine.cpu.get_r32(R::EAX));
}
#[test]
fn can_execute_dec32() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x66, 0xB8, 0x00, 0x00, 0x01, 0x80, 0x66, 0x48, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x8000_FFFF, machine.cpu.get_r32(R::EAX));
}
#[test]
fn can_execute_add8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFF, 0x80, 0xC4, 0x01,
0xB4, 0x01, 0x80, 0xC4, 0xFF,
0xB4, 0xFF, 0x80, 0xC4, 0x00,
0xB4, 0xFF, 0x80, 0xC4, 0xFF, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x00, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.adjust);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x00, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.adjust);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.adjust);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFE, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.adjust);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_add16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFF, 0xFF, 0x83, 0xC0, 0x01,
0xB8, 0x01, 0x00, 0x83, 0xC0, 0xFF,
0xB8, 0xFF, 0xFF, 0x83, 0xC0, 0x00,
0xB8, 0xFF, 0xFF, 0x83, 0xC0, 0xFF, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.adjust);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.adjust);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.adjust);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFFFE, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.adjust);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_mov_r8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB2, 0x13, 0x88, 0xD0, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x13, machine.cpu.get_r8(R::DL));
machine.execute_instruction();
assert_eq!(0x13, machine.cpu.get_r8(R::AL));
}
#[test]
fn can_execute_mov_r32() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x66, 0xB8, 0x78, 0x56, 0x34, 0x12, 0x66, 0xB8, 0x23, 0x01, 0xFF, 0x00, 0x66, 0x89, 0xC5, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 1);
assert_eq!("[085F:0100] 66B878563412 Mov32 eax, 0x12345678", res);
machine.execute_instruction();
assert_eq!(0x1234_5678, machine.cpu.get_r32(R::EAX));
machine.execute_instructions(2);
assert_eq!(0x00FF_0123, machine.cpu.get_r32(R::EBP));
}
#[test]
fn can_execute_mov_r8_rm8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x05, 0x01, 0x8A, 0x27, 0x99, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x103, machine.cpu.regs.ip);
assert_eq!(0x105, machine.cpu.get_r16(R::BX));
machine.execute_instruction();
assert_eq!(0x105, machine.cpu.regs.ip);
assert_eq!(0x99, machine.cpu.get_r8(R::AH));
}
#[test]
fn can_execute_mv_r16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x23, 0x01, 0x8B, 0xE0, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x103, machine.cpu.regs.ip);
assert_eq!(0x123, machine.cpu.get_r16(R::AX));
machine.execute_instruction();
assert_eq!(0x105, machine.cpu.regs.ip);
assert_eq!(0x123, machine.cpu.get_r16(R::SP));
}
#[test]
fn can_execute_mov_r16_rm16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB9, 0x23, 0x01, 0x8E, 0xC1, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x103, machine.cpu.regs.ip);
assert_eq!(0x123, machine.cpu.get_r16(R::CX));
machine.execute_instruction();
assert_eq!(0x105, machine.cpu.regs.ip);
assert_eq!(0x123, machine.cpu.get_r16(R::ES));
}
#[test]
fn can_execute_mov_rm16_sreg() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x34, 0x12, 0x8E, 0xC3, 0x8C, 0x06, 0x09, 0x01, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x103, machine.cpu.regs.ip);
assert_eq!(0x1234, machine.cpu.get_r16(R::BX));
machine.execute_instruction();
assert_eq!(0x105, machine.cpu.regs.ip);
assert_eq!(0x1234, machine.cpu.get_r16(R::ES));
machine.execute_instruction();
assert_eq!(0x109, machine.cpu.regs.ip);
let cs = machine.cpu.get_r16(R::CS);
assert_eq!(0x1234, machine.mmu.read_u16(cs, 0x0109));
}
#[test]
fn can_execute_mov_data() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xC6, 0x06, 0x31, 0x10, 0x38, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x105, machine.cpu.regs.ip);
let cs = machine.cpu.get_r16(R::CS);
assert_eq!(0x38, machine.mmu.read_u8(cs, 0x1031));
}
#[test]
fn can_execute_mov_es_segment() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x68, 0x40, 0x40, 0x07, 0xBF, 0x00, 0x02, 0xB4, 0x88,
0x26, 0x88, 0x25, 0x26, 0x8A, 0x05,
0x26, 0x8A, 0x45, 0x01, 0x26, 0x8A, 0x5D, 0xFF,
0x26, 0x8A, 0x85, 0x40, 0x01, 0x26, 0x8A, 0x9D, 0xC0, 0xFE, ];
machine.load_executable(&code);
machine.execute_instructions(4);
let es = machine.cpu.get_r16(R::ES);
let di = machine.cpu.get_r16(R::DI);
machine.execute_instruction(); assert_eq!(0x88, machine.mmu.read_u8(es, di));
machine.execute_instruction(); assert_eq!(0x88, machine.cpu.get_r8(R::AL));
machine.mmu.write_u8(es, di + 1, 0x1);
machine.mmu.write_u8(es, di - 1, 0xFF);
machine.execute_instruction(); assert_eq!(0x1, machine.cpu.get_r8(R::AL));
machine.execute_instruction(); assert_eq!(0xFF, machine.cpu.get_r8(R::BL));
machine.mmu.write_u8(es, di + 0x140, 0x22);
machine.mmu.write_u8(es, di - 0x140, 0x88);
machine.execute_instruction(); assert_eq!(0x22, machine.cpu.get_r8(R::AL));
machine.execute_instruction(); assert_eq!(0x88, machine.cpu.get_r8(R::BL));
}
#[test]
fn can_execute_mov_fs_segment() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x68, 0x40, 0x40, 0x0F, 0xA1, 0xBF, 0x00, 0x02, 0xB0, 0xFF,
0x64, 0x88, 0x05, ];
machine.load_executable(&code);
machine.execute_instructions(5); assert_eq!(0xFF, machine.mmu.read_u8(machine.cpu.get_r16(R::FS), machine.cpu.get_r16(R::DI)));
}
#[test]
fn can_execute_imms8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBF, 0x00, 0x01, 0x83, 0xC7, 0x3A, 0x83, 0xC7, 0xC6, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x103, machine.cpu.regs.ip);
assert_eq!(0x0100, machine.cpu.get_r16(R::DI));
machine.execute_instruction();
assert_eq!(0x106, machine.cpu.regs.ip);
assert_eq!(0x013A, machine.cpu.get_r16(R::DI));
machine.execute_instruction();
assert_eq!(0x109, machine.cpu.regs.ip);
assert_eq!(0x0100, machine.cpu.get_r16(R::DI));
}
#[test]
fn can_execute_with_flags() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFE, 0x80, 0xC4, 0x02, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x102, machine.cpu.regs.ip);
assert_eq!(0xFE, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
assert_eq!(false, machine.cpu.regs.flags.adjust);
assert_eq!(false, machine.cpu.regs.flags.parity);
machine.execute_instruction();
assert_eq!(0x105, machine.cpu.regs.ip);
assert_eq!(0x00, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
assert_eq!(true, machine.cpu.regs.flags.adjust);
assert_eq!(true, machine.cpu.regs.flags.parity);
}
#[test]
fn can_execute_cmp() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x00, 0x00, 0x89, 0xDF, 0x81, 0xFF, 0x00, 0x20, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x103, machine.cpu.regs.ip);
assert_eq!(0, machine.cpu.get_r16(R::BX));
machine.execute_instruction();
assert_eq!(0x105, machine.cpu.regs.ip);
assert_eq!(0, machine.cpu.get_r16(R::DI));
machine.execute_instruction();
assert_eq!(0x109, machine.cpu.regs.ip);
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
assert_eq!(false, machine.cpu.regs.flags.adjust);
assert_eq!(true, machine.cpu.regs.flags.parity);
}
#[test]
fn can_execute_xchg() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x34, 0x12, 0xB9, 0xFF, 0xFF, 0x91, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(0x1234, machine.cpu.get_r16(R::CX));
}
#[test]
fn can_execute_rep_movsb() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBE, 0x00, 0x01, 0xBF, 0x00, 0x02, 0xB9, 0x04, 0x00, 0xF3, 0xA4, ];
machine.load_executable(&code);
machine.execute_instructions(3);
machine.execute_instructions(4);
machine.execute_instruction(); machine.execute_instruction(); machine.execute_instruction(); assert_eq!(0x0, machine.cpu.get_r16(R::CX));
let min = 0x100;
let max = min + 4;
for i in min..max {
assert_eq!(
machine.mmu.read_u8(machine.cpu.get_r16(R::ES), i),
machine.mmu.read_u8(machine.cpu.get_r16(R::ES), i+0x100));
}
}
#[test]
fn can_execute_rep_outsb() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBE, 0x00, 0x01, 0xBA, 0xC8, 0x03, 0xB9, 0x02, 0x00, 0xF3, 0x6E, ];
machine.load_executable(&code);
assert_eq!(0, machine.gpu_mut().unwrap().dac.write_index);
machine.execute_instructions(3);
machine.execute_instruction(); assert_eq!(0xBE, machine.gpu_mut().unwrap().dac.write_index);
machine.execute_instruction(); assert_eq!(0x00, machine.gpu_mut().unwrap().dac.write_index);
assert_eq!(0x0, machine.cpu.get_r16(R::CX));
}
#[test]
fn can_execute_es_outsb() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x68, 0x00, 0x80, 0x07, 0xBE, 0x00, 0x01, 0x26, 0xC6, 0x04, 0x09, 0xBA, 0xC8, 0x03, 0x26, 0x6E, ];
machine.load_executable(&code);
assert_eq!(0, machine.gpu_mut().unwrap().dac.write_index);
machine.execute_instructions(6);
assert_eq!(0x09, machine.gpu_mut().unwrap().dac.write_index);
}
#[test]
fn can_execute_lea() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x44, 0x44, 0x8D, 0x3F, 0x8D, 0x36, 0x33, 0x22, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x4444, machine.cpu.get_r16(R::DI));
machine.execute_instruction();
assert_eq!(0x2233, machine.cpu.get_r16(R::SI));
}
#[test]
fn can_execute_8bit_16bit_addressing() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x00, 0x02, 0xC6, 0x47, 0x2C, 0xFF, 0x8B, 0x14, 0x8B, 0x47, 0x2C, 0x89, 0x87, 0x30, 0x00, 0x89, 0x05, 0xC6, 0x85, 0xAE, 0x06, 0xFE, 0x8A, 0x85, 0xAE, 0x06, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 8);
assert_eq!("[085F:0100] BB0002 Mov16 bx, 0x0200
[085F:0103] C6472CFF Mov8 byte [ds:bx+0x2C], 0xFF
[085F:0107] 8B14 Mov16 dx, word [ds:si]
[085F:0109] 8B472C Mov16 ax, word [ds:bx+0x2C]
[085F:010C] 89873000 Mov16 word [ds:bx+0x0030], ax
[085F:0110] 8905 Mov16 word [ds:di], ax
[085F:0112] C685AE06FE Mov8 byte [ds:di+0x06AE], 0xFE
[085F:0117] 8A85AE06 Mov8 al, byte [ds:di+0x06AE]", res);
machine.execute_instruction();
assert_eq!(0x200, machine.cpu.get_r16(R::BX));
machine.execute_instruction();
let ds = machine.cpu.get_r16(R::DS);
assert_eq!(0xFF, machine.mmu.read_u8(ds, 0x22C));
machine.execute_instruction();
assert_eq!(0x00BB, machine.cpu.get_r16(R::DX));
machine.execute_instruction();
assert_eq!(0x00FF, machine.cpu.get_r16(R::AX));
machine.execute_instruction();
assert_eq!(0x00FF, machine.mmu.read_u16(ds, 0x230));
machine.execute_instruction();
let di = machine.cpu.get_r16(R::DI);
assert_eq!(0x00FF, machine.mmu.read_u16(ds, di));
machine.execute_instruction();
assert_eq!(0xFE, machine.mmu.read_u8(ds, (Wrapping(di) +
Wrapping(0x06AE)).0));
machine.execute_instruction();
assert_eq!(0xFE, machine.cpu.get_r8(R::AL));
}
#[test]
fn can_execute_32bit_addressing() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x66, 0xBB, 0x00, 0x02, 0x00, 0x00, 0x66, 0x89, 0x1E, 0x50, 0x02, 0x66, 0xC7, 0x05, 0x01, 0x01, 0x01, 0x01, 0x66, 0x89, 0x5D, 0xF8, 0x66, 0x89, 0x9D, 0xC0, 0xFE, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 5);
assert_eq!("[085F:0100] 66BB00020000 Mov32 ebx, 0x00000200
[085F:0106] 66891E5002 Mov32 dword [ds:0x0250], ebx
[085F:010B] 66C70501010101 Mov32 dword [ds:di], 0x01010101
[085F:0112] 66895DF8 Mov32 dword [ds:di-0x08], ebx
[085F:0116] 66899DC0FE Mov32 dword [ds:di-0x0140], ebx", res);
machine.execute_instructions(2);
let ds = machine.cpu.get_r16(R::DS);
assert_eq!(0x0000_0200, machine.mmu.read_u32(ds, 0x250));
machine.execute_instruction();
let di = machine.cpu.get_r16(R::DI);
assert_eq!(0x0101_0101, machine.mmu.read_u32(ds, di));
machine.execute_instruction();
let di = machine.cpu.get_r16(R::DI);
assert_eq!(0x0000_0200, machine.mmu.read_u32(ds, di - 8));
machine.execute_instruction();
let di = machine.cpu.get_r16(R::DI);
assert_eq!(0x0000_0200, machine.mmu.read_u32(ds, di - 0x140));
}
#[test]
fn can_execute_math() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xF6, 0x06, 0x2C, 0x12, 0xFF, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 1);
assert_eq!("[085F:0100] F6062C12FF Test8 byte [ds:0x122C], 0xFF",
res);
}
#[test]
fn can_execute_and() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB0, 0xF0, 0xB4, 0x1F, 0x20, 0xC4, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 3);
assert_eq!("[085F:0100] B0F0 Mov8 al, 0xF0
[085F:0102] B41F Mov8 ah, 0x1F
[085F:0104] 20C4 And8 ah, al",
res);
machine.execute_instruction();
assert_eq!(0xF0, machine.cpu.get_r8(R::AL));
machine.execute_instruction();
assert_eq!(0x1F, machine.cpu.get_r8(R::AH));
machine.execute_instruction();
assert_eq!(0x10, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.parity);
}
#[test]
fn can_execute_mul8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB0, 0x40, 0xB3, 0x10, 0xF6, 0xE3, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0x400, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_mul16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x00, 0x80, 0xBB, 0x04, 0x00, 0xF7, 0xE3, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0x0002, machine.cpu.get_r16(R::DX));
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_div8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x40, 0x00, 0xB3, 0x10, 0xF6, 0xF3, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 3);
assert_eq!("[085F:0100] B84000 Mov16 ax, 0x0040
[085F:0103] B310 Mov8 bl, 0x10
[085F:0105] F6F3 Div8 bl",
res);
machine.execute_instruction();
assert_eq!(0x40, machine.cpu.get_r8(R::AL));
machine.execute_instruction();
assert_eq!(0x10, machine.cpu.get_r8(R::BL));
machine.execute_instruction();
assert_eq!(0x04, machine.cpu.get_r8(R::AL)); assert_eq!(0x00, machine.cpu.get_r8(R::AH)); }
#[test]
fn can_execute_div16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBA, 0x10, 0x00, 0xB8, 0x00, 0x40, 0xBB, 0x00, 0x01, 0xF7, 0xF3, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 4);
assert_eq!("[085F:0100] BA1000 Mov16 dx, 0x0010
[085F:0103] B80040 Mov16 ax, 0x4000
[085F:0106] BB0001 Mov16 bx, 0x0100
[085F:0109] F7F3 Div16 bx",
res);
machine.execute_instruction();
assert_eq!(0x10, machine.cpu.get_r16(R::DX));
machine.execute_instruction();
assert_eq!(0x4000, machine.cpu.get_r16(R::AX));
machine.execute_instruction();
assert_eq!(0x100, machine.cpu.get_r16(R::BX));
machine.execute_instruction();
assert_eq!(0x1040, machine.cpu.get_r16(R::AX)); assert_eq!(0x0000, machine.cpu.get_r16(R::DX)); }
#[test]
fn can_execute_idiv8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x00, 0x00, 0xB3, 0x02, 0xF6, 0xFB,
0xB8, 0xFF, 0xFF, 0xB3, 0x02, 0xF6, 0xFB,
0xB8, 0x01, 0x00, 0xB3, 0x0F, 0xF6, 0xFB, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0x00, machine.cpu.get_r8(R::AL)); assert_eq!(0x00, machine.cpu.get_r8(R::AH));
machine.execute_instructions(3);
assert_eq!(0x00, machine.cpu.get_r8(R::AL));
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
machine.execute_instructions(3);
assert_eq!(0x00, machine.cpu.get_r8(R::AL));
assert_eq!(0x01, machine.cpu.get_r8(R::AH));
}
#[test]
fn can_execute_idiv16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBA, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0xBB, 0x02, 0x00, 0xF7, 0xFB,
0xBA, 0x00, 0x00, 0xB8, 0xFF, 0xFF, 0xBB, 0x02, 0x00, 0xF7, 0xFB,
0xBA, 0x00, 0x00, 0xB8, 0x01, 0x00, 0xBB, 0x0F, 0x00, 0xF7, 0xFB,
0xBA, 0x00, 0x00, 0xB8, 0x01, 0x00, 0xBB, 0xFF, 0xFF, 0xF7, 0xFB, ];
machine.load_executable(&code);
machine.execute_instructions(4);
assert_eq!(0x8000, machine.cpu.get_r16(R::AX)); assert_eq!(0x0000, machine.cpu.get_r16(R::DX));
machine.execute_instructions(4);
assert_eq!(0x7FFF, machine.cpu.get_r16(R::AX));
assert_eq!(0x0001, machine.cpu.get_r16(R::DX));
machine.execute_instructions(4);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
assert_eq!(0x0001, machine.cpu.get_r16(R::DX));
machine.execute_instructions(4);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(0x0000, machine.cpu.get_r16(R::DX));
}
#[test]
fn can_execute_idiv32() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x66, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x66, 0xB8, 0x00, 0x00, 0x00, 0x44, 0x66, 0xBB, 0x02, 0x00, 0x00, 0x00, 0x66, 0xF7, 0xFB, ];
machine.load_executable(&code);
machine.execute_instructions(4);
assert_eq!(0x2200_0000, machine.cpu.get_r32(R::EAX)); assert_eq!(0x0000_0000, machine.cpu.get_r32(R::EDX)); }
#[test]
fn can_execute_lds() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x00, 0x60, 0xC7, 0x07, 0x22, 0x11, 0xC7, 0x47, 0x02, 0x88, 0x66, 0x8C, 0xD9, 0xC5, 0x17, 0x8C, 0xD8, 0x8E, 0xD9, ];
machine.load_executable(&code);
machine.execute_instructions(7);
assert_eq!(0x1122, machine.cpu.get_r16(R::DX));
assert_eq!(0x6688, machine.cpu.get_r16(R::AX)); }
#[test]
fn can_execute_lds_2() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x00, 0x60, 0xC7, 0x47, 0x06, 0x22, 0x11, 0xC7, 0x47, 0x08, 0x88, 0x66, 0x8C, 0xD9, 0xC5, 0x57, 0x06, 0x8C, 0xD8, 0x8E, 0xD9, ];
machine.load_executable(&code);
machine.execute_instructions(7);
assert_eq!(0x1122, machine.cpu.get_r16(R::DX));
assert_eq!(0x6688, machine.cpu.get_r16(R::AX)); }
#[test]
fn can_execute_les() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xC4, 0x06, 0x00, 0x01, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x06C4, machine.cpu.get_r16(R::AX));
assert_eq!(0x0100, machine.cpu.get_r16(R::ES));
}
#[test]
fn can_execute_cwd() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x00, 0xFE, 0x99, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::DX));
}
#[test]
fn can_execute_aaa() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB0, 0x7E, 0x37, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x0104, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_aam() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x44, 0x44, 0xD4, 0x0A, 0xB8, 0x00, 0x00, 0xD4, 0x0A, 0xB8, 0xFF, 0xFF, 0xD4, 0x0A, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x0608, machine.cpu.get_r16(R::AX));
machine.execute_instructions(2);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
machine.execute_instructions(2);
assert_eq!(0x1905, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_aas() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB0, 0x13, 0x3F, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x0003, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_bts() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x0F, 0xBA, 0x2E, 0xAE, 0x01, 0x0F, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 1);
assert_eq!("[085F:0100] 0FBA2EAE010F Bts word [ds:0x01AE], 0x0F", res);
machine.execute_instructions(1);
}
#[test]
fn can_execute_bsf() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x04, 0x00, 0x0F, 0xBC, 0xD0, 0xB8, 0xF0, 0xFF, 0x0F, 0xBC, 0xD0, 0xB8, 0x00, 0x00, 0x0F, 0xBC, 0xD0, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(2, machine.cpu.get_r16(R::DX));
assert_eq!(false, machine.cpu.regs.flags.zero);
machine.execute_instructions(2);
assert_eq!(4, machine.cpu.get_r16(R::DX));
assert_eq!(false, machine.cpu.regs.flags.zero);
machine.execute_instructions(2);
assert_eq!(4, machine.cpu.get_r16(R::DX)); assert_eq!(true, machine.cpu.regs.flags.zero);
}
#[test]
fn can_execute_bt() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x02, 0x00, 0xBA, 0x02, 0x00, 0x0F, 0xA3, 0xD0, 0xBA, 0x01, 0x00, 0x0F, 0xA3, 0xD0, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(false, machine.cpu.regs.flags.carry);
machine.execute_instructions(2);
assert_eq!(true, machine.cpu.regs.flags.carry);
}
#[test]
fn can_execute_daa() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB0, 0x79, 0xB3, 0x35, 0x27, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0x0079, machine.cpu.get_r16(R::AX)); }
#[test]
fn can_execute_das() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB0, 0x35, 0xB3, 0x47, 0x2F, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0x0035, machine.cpu.get_r16(R::AX)); }
#[test]
fn can_execute_sahf() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x6A, 0x00, 0x9D, 0xB4, 0xFF, 0x9E, ];
machine.load_executable(&code);
machine.execute_instructions(4);
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.adjust);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
}
#[test]
fn can_execute_pusha_popa() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xE8, 0x03, 0xB9, 0xE9, 0x03, 0xBA, 0xEA, 0x03, 0xBB, 0xEB, 0x03, 0xBC, 0xEC, 0x03, 0xBD, 0xED, 0x03, 0xBE, 0xEE, 0x03, 0xBF, 0xEF, 0x03, 0x60, 0x61, ];
machine.load_executable(&code);
machine.execute_instructions(8);
machine.execute_instruction(); machine.execute_instruction(); assert_eq!(1000, machine.cpu.get_r16(R::AX));
assert_eq!(1001, machine.cpu.get_r16(R::CX));
assert_eq!(1002, machine.cpu.get_r16(R::DX));
assert_eq!(1003, machine.cpu.get_r16(R::BX));
assert_eq!(1004, machine.cpu.get_r16(R::SP));
assert_eq!(1005, machine.cpu.get_r16(R::BP));
assert_eq!(1006, machine.cpu.get_r16(R::SI));
assert_eq!(1007, machine.cpu.get_r16(R::DI));
}
#[test]
fn can_execute_dec() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBD, 0x00, 0x02, 0x4D, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x200, machine.cpu.get_r16(R::BP));
machine.execute_instruction();
assert_eq!(0x1FF, machine.cpu.get_r16(R::BP));
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(true, machine.cpu.regs.flags.parity);
}
#[test]
fn can_execute_neg() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x23, 0x01, 0xF7, 0xDB, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x0123, machine.cpu.get_r16(R::BX));
machine.execute_instruction();
assert_eq!(0xFEDD, machine.cpu.get_r16(R::BX));
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
assert_eq!(true, machine.cpu.regs.flags.adjust);
assert_eq!(true, machine.cpu.regs.flags.parity);
}
#[test]
fn can_execute_sbb16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x48, 0xF0, 0x1D, 0x45, 0x44, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xAC03, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.adjust);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_jmp_far() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xEA, 0x00, 0x06, 0x00, 0x00, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 1);
assert_eq!("[085F:0100] EA00060000 JmpFar 0000:0600", res);
machine.execute_instruction();
assert_eq!(0x0000, machine.cpu.get_r16(R::CS));
assert_eq!(0x0600, machine.cpu.regs.ip);
}
#[test]
fn can_execute_jmp_far_mem() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x31, 0xC0, 0xBE, 0x88, 0x88, 0xBB, 0x22, 0x44, 0xC6, 0x00, 0x40, 0xFF, 0x28, ];
machine.load_executable(&code);
machine.execute_instructions(6);
assert_eq!(0xCCAB, machine.cpu.regs.ip);
assert_eq!(0x0001, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_setc() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x0F, 0x92, 0xC0, ];
machine.load_executable(&code);
machine.cpu.regs.flags.carry = true;
machine.execute_instruction();
assert_eq!(0x01, machine.cpu.get_r8(R::AL));
machine.load_executable(&code);
machine.cpu.regs.flags.carry = false;
machine.execute_instruction();
assert_eq!(0x00, machine.cpu.get_r8(R::AL));
}
#[test]
fn can_execute_movzx() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFF, 0x0F, 0xB6, 0xDC,
];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 2);
assert_eq!("[085F:0100] B4FF Mov8 ah, 0xFF
[085F:0102] 0FB6DC Movzx16 bx, ah",
res);
machine.execute_instruction();
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
machine.execute_instruction();
assert_eq!(0xFFFF, machine.cpu.get_r16(R::BX));
}
#[test]
fn can_execute_rol8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFE, 0xC0, 0xC4, 0x01, 0xB4, 0xFF, 0xC0, 0xC4, 0xFF, 0xB4, 0x01, 0xC0, 0xC4, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFD, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
machine.execute_instructions(2);
assert_eq!(0x10, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
}
#[test]
fn can_execute_rol16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFE, 0xFF, 0xC1, 0xC0, 0x01, 0xB8, 0xFF, 0xFF, 0xC1, 0xC0, 0xFF, 0xB8, 0x01, 0x00, 0xC1, 0xC0, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFFFD, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
machine.execute_instructions(2);
assert_eq!(0x0010, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
}
#[test]
fn can_execute_ror8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFE, 0xC0, 0xCC, 0x01, 0xB4, 0xFF, 0xC0, 0xCC, 0xFF, 0xB4, 0x01, 0xC0, 0xCC, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x7F, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
machine.execute_instructions(2);
assert_eq!(0x10, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
}
#[test]
fn can_execute_ror16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFE, 0xFF, 0xC1, 0xC8, 0x01, 0xB8, 0xFF, 0xFF, 0xC1, 0xC8, 0xFF, 0xB8, 0x01, 0x00, 0xC1, 0xC8, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x7FFF, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
machine.execute_instructions(2);
assert_eq!(0x1000, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
}
#[test]
fn can_execute_rcl8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFE, 0xF9, 0xC0, 0xD4, 0x01, 0xB4, 0xFF, 0xF9, 0xC0, 0xD4, 0xFF, 0xB4, 0x01, 0xF9, 0xC0, 0xD4, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0xFD, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0x18, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_rcl16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFE, 0xFF, 0xF9, 0xC1, 0xD0, 0x01, 0xB8, 0xFF, 0xFF, 0xF9, 0xC1, 0xD0, 0xFF, 0xB8, 0x01, 0x00, 0xF9, 0xC1, 0xD0, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0xFFFD, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0x0018, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_rcr8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFE, 0xF9, 0xC0, 0xDC, 0x01,
0xB4, 0xFE, 0xF8, 0xC0, 0xDC, 0x01,
0xB4, 0xFF, 0xF9, 0xC0, 0xDC, 0xFF,
0xB4, 0x01, 0xF9, 0xC0, 0xDC, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0x7F, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0x30, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow); }
#[test]
fn can_execute_rcr16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFE, 0xFF, 0xF9, 0xC1, 0xD8, 0x01,
0xB8, 0xFE, 0xFF, 0xF8, 0xC1, 0xD8, 0x01,
0xB8, 0xFF, 0xFF, 0xF9, 0xC1, 0xD8, 0xFF,
0xB8, 0x01, 0x00, 0xF9, 0xC1, 0xD8, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0x7FFF, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(3);
assert_eq!(0x3000, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.overflow); }
#[test]
fn can_execute_shl8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFF, 0xC0, 0xE4, 0x01, 0xB4, 0xFF, 0xC0, 0xE4, 0xFF, 0xB4, 0x01, 0xC0, 0xE4, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFE, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
machine.execute_instructions(2);
assert_eq!(0x00, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x10, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_shl16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFF, 0xFF, 0xC1, 0xE0, 0x01, 0xB8, 0xFF, 0xFF, 0xC1, 0xE0, 0xFF, 0xB8, 0x01, 0x00, 0xC1, 0xE0, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFFFE, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x0010, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_shr8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFF, 0xC0, 0xEC, 0x01, 0xB4, 0xFF, 0xC0, 0xEC, 0xFF, 0xB4, 0x01, 0xC0, 0xEC, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x7F, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(false, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(true, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x00, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(true, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x00, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_shr16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFF, 0xFF, 0xC1, 0xE8, 0x01, 0xB8, 0xFF, 0xFF, 0xC1, 0xE8, 0xFF, 0xB8, 0x01, 0x00, 0xC1, 0xE8, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0x7FFF, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(true, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(true, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_sar8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB4, 0xFE, 0xC0, 0xFC, 0x01, 0xB4, 0xFF, 0xC0, 0xFC, 0xFF, 0xB4, 0x01, 0xC0, 0xFC, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFF, machine.cpu.get_r8(R::AH));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x00, machine.cpu.get_r8(R::AH));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_sar16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFE, 0xFF, 0xC1, 0xF8, 0x01, 0xB8, 0xFF, 0xFF, 0xC1, 0xF8, 0xFF, 0xB8, 0x01, 0x00, 0xC1, 0xF8, 0x04, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(true, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
machine.execute_instructions(2);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.parity);
assert_eq!(true, machine.cpu.regs.flags.zero);
assert_eq!(false, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
}
#[test]
fn can_execute_imul8() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB0, 0xFF, 0xB3, 0x02, 0xF6, 0xEB, 0xB0, 0x00, 0xB3, 0x02, 0xF6, 0xEB, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0xFFFE, machine.cpu.get_r16(R::AX));
machine.execute_instructions(3);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_imul16_1_args() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFF, 0xFF, 0xBB, 0x02, 0x00, 0xF7, 0xEB,
0xB8, 0x00, 0x00, 0xBB, 0x02, 0x00, 0xF7, 0xEB,
0xB8, 0xF0, 0x0F, 0xBB, 0xF0, 0x00, 0xF7, 0xEB, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0xFFFF, machine.cpu.get_r16(R::DX)); assert_eq!(0xFFFE, machine.cpu.get_r16(R::AX));
machine.execute_instructions(3);
assert_eq!(0x0000, machine.cpu.get_r16(R::DX));
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
machine.execute_instructions(3);
assert_eq!(0x000E, machine.cpu.get_r16(R::DX));
assert_eq!(0xF100, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_imul16_2_args() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFF, 0xFF, 0xBB, 0x02, 0x00, 0x0F, 0xAF, 0xC3,
0xB8, 0x00, 0x00, 0xBB, 0x02, 0x00, 0x0F, 0xAF, 0xC3,
0xB8, 0xF0, 0x0F, 0xBB, 0xF0, 0x00, 0x0F, 0xAF, 0xC3, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0xFFFE, machine.cpu.get_r16(R::AX));
machine.execute_instructions(3);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
machine.execute_instructions(3);
assert_eq!(0xF100, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_imul16_3_args() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFF, 0xFF, 0x6B, 0xC0, 0x02,
0xB8, 0x00, 0x00, 0x6B, 0xC0, 0x02,
0xB8, 0xF0, 0x0F, 0x69, 0xC0, 0xF0, 0x00, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFFFE, machine.cpu.get_r16(R::AX));
machine.execute_instructions(2);
assert_eq!(0x0000, machine.cpu.get_r16(R::AX));
machine.execute_instructions(2);
assert_eq!(0xF100, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_imul32_1_args() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x66, 0xB8, 0xFF, 0xFF, 0x00, 0x00, 0x66, 0xBB, 0x02, 0x00, 0x00, 0x00, 0x66, 0xF7, 0xEB, 0x66, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x66, 0xBB, 0x02, 0x00, 0x00, 0x00, 0x66, 0xF7, 0xEB, 0x66, 0xB8, 0xF0, 0x0F, 0x00, 0x00, 0x66, 0xBB, 0xF0, 0x00, 0x00, 0x00, 0x66, 0xF7, 0xEB, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0x0000_0000, machine.cpu.get_r32(R::EDX)); assert_eq!(0x0001_FFFE, machine.cpu.get_r32(R::EAX));
machine.execute_instructions(3);
assert_eq!(0x0000_0000, machine.cpu.get_r32(R::EDX));
assert_eq!(0x0000_0000, machine.cpu.get_r32(R::EAX));
machine.execute_instructions(3);
assert_eq!(0x0000_0000, machine.cpu.get_r32(R::EDX));
assert_eq!(0x000E_F100, machine.cpu.get_r32(R::EAX));
}
#[test]
fn can_execute_imul32_3_args() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x66, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x6B, 0xC0, 0x02, 0x66, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6B, 0xC0, 0x02, 0x66, 0xB8, 0xF0, 0x0F, 0x00, 0x00, 0x66, 0x69, 0xC0, 0xF0, 0x00, 0x00, 0x00, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFFFF_FFFE, machine.cpu.get_r32(R::EAX));
machine.execute_instructions(2);
assert_eq!(0x0000_0000, machine.cpu.get_r32(R::EAX));
machine.execute_instructions(2);
assert_eq!(0x000E_F100, machine.cpu.get_r32(R::EAX));
}
#[test]
fn can_execute_int_iret() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xCD, 0x72, ];
machine.load_executable(&code);
assert_eq!(0x085F, machine.cpu.get_r16(R::CS));
machine.execute_instruction();
assert_eq!(0xF000, machine.cpu.get_r16(R::CS));
assert_eq!(0x0072, machine.cpu.regs.ip);
machine.execute_instruction(); assert_eq!(0x085F, machine.cpu.get_r16(R::CS));
assert_eq!(0x0102, machine.cpu.regs.ip);
}
#[test]
fn can_execute_xlatb() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x40, 0x02, 0xC6, 0x06, 0x40, 0x02, 0x80, 0xD7, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0x80, machine.cpu.get_r8(R::AL)); }
#[test]
fn can_execute_cmpsw() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBE, 0x30, 0x30, 0xC7, 0x04, 0x22, 0x22, 0xBF, 0x40, 0x30, 0xC7, 0x05, 0x11, 0x11, 0xA7, ];
machine.load_executable(&code);
machine.execute_instructions(5);
}
#[test]
fn can_execute_shld() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xBB, 0x88, 0x44, 0xBF, 0x33, 0x22, 0x0F, 0xA4, 0xFB, 0x08, ];
machine.load_executable(&code);
machine.execute_instructions(3);
assert_eq!(0x8822, machine.cpu.get_r16(R::BX));
assert_eq!(false, machine.cpu.regs.flags.carry);
assert_eq!(true, machine.cpu.regs.flags.overflow);
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(true, machine.cpu.regs.flags.parity);
}
#[test]
fn can_execute_scasb() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x00, 0x40, 0x8E, 0xC0, 0xBF, 0x00, 0x00, 0x26, 0xC6, 0x05, 0xFF, 0xB0, 0xFF, 0xAE ];
machine.load_executable(&code);
machine.execute_instructions(6);
assert_eq!(0x0001, machine.cpu.get_r16(R::DI));
assert_eq!(Flags::new_from_u16(0x3246), machine.cpu.regs.flags); }
#[test]
fn can_execute_scasw() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0x00, 0x40, 0x8E, 0xC0, 0xBF, 0x00, 0x00, 0x26, 0xC7, 0x05, 0xFF, 0xFF, 0xB8, 0xFF, 0xFF, 0xAF ];
machine.load_executable(&code);
machine.execute_instructions(6);
assert_eq!(0x0002, machine.cpu.get_r16(R::DI));
assert_eq!(Flags::new_from_u16(0x3246), machine.cpu.regs.flags); }
#[test]
fn can_execute_movsx16() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB7, 0xFE, 0x0F, 0xBE, 0xC7, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFFFE, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_movsx32() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB7, 0xFE, 0x66, 0x0F, 0xBE, 0xC7, ];
machine.load_executable(&code);
machine.execute_instructions(2);
assert_eq!(0xFFFF_FFFE, machine.cpu.get_r32(R::EAX));
}
#[test]
fn can_execute_mov_ds_addressing() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x68, 0x00, 0x80, 0x1F, 0xBB, 0x10, 0x00, 0xBE, 0x01, 0x00, 0xBA, 0x99, 0x99, 0x89, 0x10, ];
machine.load_executable(&code);
machine.execute_instructions(6);
let cs = machine.cpu.get_r16(R::CS);
let ds = machine.cpu.get_r16(R::DS);
assert_eq!(0x0000, machine.mmu.read_u16(cs, 0x10 + 0x1));
assert_eq!(0x9999, machine.mmu.read_u16(ds, 0x10 + 0x1));
}
#[test]
fn can_execute_shrd() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB8, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, 0x0F, 0xAC, 0xD0, 0x0E, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 3);
assert_eq!("[085F:0100] B8FFFF Mov16 ax, 0xFFFF
[085F:0103] BAFFFF Mov16 dx, 0xFFFF
[085F:0106] 0FACD00E Shrd ax, dx, 0x0E",
res);
machine.execute_instruction();
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
machine.execute_instruction();
assert_eq!(0xFFFF, machine.cpu.get_r16(R::DX));
machine.execute_instruction();
assert_eq!(0xFFFF, machine.cpu.get_r16(R::AX));
assert_eq!(false, machine.cpu.regs.flags.zero);
assert_eq!(true, machine.cpu.regs.flags.sign);
assert_eq!(false, machine.cpu.regs.flags.overflow);
assert_eq!(false, machine.cpu.regs.flags.adjust);
assert_eq!(true, machine.cpu.regs.flags.parity);
}
#[test]
fn can_execute_ret_imm() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xE8, 0x03, 0x00, 0xB9, 0x34, 0x12, 0xC2, 0x01, 0x00, ];
machine.load_executable(&code);
assert_eq!(0x0100, machine.cpu.regs.ip);
assert_eq!(0xFFFC, machine.cpu.get_r16(R::SP));
machine.execute_instruction(); assert_eq!(0x0106, machine.cpu.regs.ip);
assert_eq!(0xFFFA, machine.cpu.get_r16(R::SP));
machine.execute_instruction(); assert_eq!(0xFFFD, machine.cpu.get_r16(R::SP));
assert_eq!(0x0103, machine.cpu.regs.ip);
}
#[test]
fn can_execute_call_far() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x9A, 0xD3, 0x00, 0x00, 0x00, ];
machine.load_executable(&code);
machine.execute_instruction();
assert_eq!(0x0000, machine.cpu.get_r16(R::CS));
assert_eq!(0x00D3, machine.cpu.regs.ip);
}
#[test]
fn can_execute_sldt() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x0F, 0x00, 0x00, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 1);
assert_eq!("[085F:0100] 0F0000 Sldt word [ds:bx+si]", res);
machine.execute_instruction();
}
#[test]
fn can_execute_operand_prefix() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x67, 0xC7, 0x02, 0x22, 0x44, 0x67, 0x8B, 0x02, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 2);
assert_eq!("[085F:0100] 67C7022244 Mov16 word [ds:edx], 0x4422
[085F:0105] 678B02 Mov16 ax, word [ds:edx]", res);
machine.execute_instruction();
machine.execute_instruction();
assert_eq!(0x4422, machine.cpu.get_r16(R::AX));
}
#[test]
fn can_execute_operand_and_address_prefix() {
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0x67, 0xC7, 0x02, 0x22, 0x44, 0x66, 0x67, 0x81, 0x02, 0x00, 0x00, 0x33, 0x88, 0x66, 0x67, 0x8B, 0x02, ];
machine.load_executable(&code);
let res = machine.cpu.decoder.disassemble_block_to_str(&mut machine.mmu, 0x85F, 0x100, 3);
assert_eq!("[085F:0100] 67C7022244 Mov16 word [ds:edx], 0x4422
[085F:0105] 6667810200003388 Add32 dword [ds:edx], 0x88330000
[085F:010D] 66678B02 Mov32 eax, dword [ds:edx]", res);
machine.execute_instructions(3);
assert_eq!(0x88334422, machine.cpu.get_r32(R::EAX));
}
#[test]
fn estimate_mips() {
use std::time::Instant;
let mut machine = Machine::deterministic();
let code: Vec<u8> = vec![
0xB9, 0xFF, 0xFF, 0x49, 0xEB, 0xFA, ];
machine.load_executable(&code);
const RUN_SECONDS: u64 = 1;
let start = Instant::now();
loop {
machine.execute_instruction();
if start.elapsed().as_secs() >= RUN_SECONDS {
break
}
}
let mips = (machine.cpu.instruction_count as f64) / 1_000_000.;
println!("MIPS: {}", mips);
}