Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Daa das #52

Merged
merged 2 commits into from
Jan 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1153,15 +1153,41 @@ lazy_static! {
define_opcode(0x40).calls(increment_native_word).with_gas(Low)
.with_suffix_regw()
.into_table(&mut ops);
// 0xFE dec r/m8
// 0xFE inc r/m8
define_opcode(0xFE).is_group(0).calls(increment_8bit).with_gas(Low)
.with_rm8()
.into_table(&mut ops);
// 0xFF dec r/m16
// 0xFF dec r/m32
// 0xFF inc r/m16
// 0xFF inc r/m32
define_opcode(0xFF).is_group(0).calls(increment_native_word).with_gas(Low)
.with_rmw()
.into_table(&mut ops);
// 0x9E SAHF
define_opcode(0x9E).calls(sahf).with_gas(Low)
.into_table(&mut ops);
// 0x9F LAHF
define_opcode(0x9F).calls(lahf).with_gas(Low)
.into_table(&mut ops);
//0x2F DAS
define_opcode(0x2F).calls(das).with_gas(Low)
.into_table(&mut ops);
//0x27 DAA
define_opcode(0x27).calls(daa).with_gas(Low)
.into_table(&mut ops);
// 0x37 aaa
define_opcode(0x37).calls(aaa).with_gas(Low)
.into_table(&mut ops);
// 0x3F aas
define_opcode(0x3F).calls(aas).with_gas(Low)
.into_table(&mut ops);
// 0xD4 aam imm8
define_opcode(0xD4).calls(aam).with_gas(Low)
.with_imm8()
.into_table(&mut ops);
// 0xD5 aad imm8
define_opcode(0xD5).calls(aad).with_gas(Low)
.with_imm8()
.into_table(&mut ops);
// 0xCD int imm8
define_opcode(0xCD).calls(interrupt).with_gas(Moderate)
.with_imm8()
Expand Down
130 changes: 128 additions & 2 deletions src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ pub fn bswap(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Resu

pub fn pushf(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let flag_int = vm.flags.serialize_flag_storage();
vm.push_stack(SizedValue::Dword(flag_int), pipeline);
vm.push_stack(SizedValue::Dword(flag_int), pipeline)?;
Ok(())
}

Expand All @@ -157,6 +157,18 @@ pub fn popf(vm: &mut VM, _pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Resu
Ok(())
}

pub fn lahf(vm: &mut VM, _pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let flag_int = vm.flags.serialize_flag_storage();
vm.set_reg(Reg8::AH as u8, SizedValue::Byte(flag_int as u8));
Ok(())
}

pub fn sahf(vm: &mut VM, _pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let ah = vm.get_reg(Reg8::AH as u8, ValueSize::Byte).u8_exact()?;
vm.flags.deserialize_flag_storage(ah as u32);
Ok(())
}

pub fn cbw_cwde(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
if pipeline.size_override{
let lower_half = vm.reg8(Reg8::AL) as u8;
Expand Down Expand Up @@ -804,6 +816,120 @@ pub fn shr_32bit(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) ->
Ok(())
}

pub fn aaa(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let mut al = vm.get_reg(Reg8::AL as u8, ValueSize::Byte).u8_exact()?;
let ah = vm.get_reg(Reg8::AH as u8, ValueSize::Byte).u8_exact()?;
if (al & 0x0F) > 9 || vm.flags.adjust {
vm.set_reg(Reg8::AL as u8, SizedValue::Byte(al.wrapping_add(6)));
vm.set_reg(Reg8::AH as u8, SizedValue::Byte(ah.wrapping_add(1)));
vm.flags.adjust = true;
vm.flags.carry = true;
} else {
vm.flags.adjust = false;
vm.flags.carry = false;
}
al = vm.get_reg(Reg8::AL as u8, ValueSize::Byte).u8_exact()?;
vm.set_reg(Reg8::AL as u8, SizedValue::Byte(al & 0x0F));
Ok(())
}

pub fn aas(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let mut al = vm.get_reg(Reg8::AL as u8, ValueSize::Byte).u8_exact()?;
let ah = vm.get_reg(Reg8::AH as u8, ValueSize::Byte).u8_exact()?;
if ((al & 0x0F) > 9) || vm.flags.adjust {
vm.set_reg(Reg8::AL as u8, SizedValue::Byte(al.wrapping_sub(6)));
vm.set_reg(Reg8::AH as u8, SizedValue::Byte(ah.wrapping_sub(1)));
vm.flags.adjust = true;
vm.flags.carry = true;
} else {
vm.flags.adjust = false;
vm.flags.carry = false;
}
al = vm.get_reg(Reg8::AL as u8, ValueSize::Byte).u8_exact()?;
vm.set_reg(Reg8::AL as u8, SizedValue::Byte(al & 0x0F));
Ok(())
}

pub fn daa(vm: &mut VM, _pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let old_al = vm.get_reg(Reg8::AL as u8, ValueSize::Byte).u8_exact()?;
let mut al = old_al;
let old_carry = vm.flags.carry;
if (al & 0x0F) > 9 || vm.flags.adjust{
let (temp_al, carry) = al.overflowing_add(6);
al = temp_al;
vm.flags.carry = carry;
vm.flags.adjust = true;
} else {
vm.flags.adjust = false;
}
if (old_al > 0x99) || old_carry {
let (temp_al, _carry) = al.overflowing_add(0x60);
al = temp_al;
vm.flags.carry = true;
} else {
vm.flags.carry = false;
}
vm.flags.calculate_parity(al as u32);
vm.flags.calculate_sign8(al);
vm.flags.calculate_zero(al as u32);
vm.set_reg(Reg8::AL as u8, SizedValue::Byte(al));
Ok(())
}

pub fn das(vm: &mut VM, _pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let old_al = vm.get_reg(Reg8::AL as u8, ValueSize::Byte).u8_exact()?;
let mut al = old_al;
let old_carry = vm.flags.carry;
if (al & 0x0F) > 9 || vm.flags.adjust{
let (temp_al, carry) = al.overflowing_sub(6);
al = temp_al;
vm.flags.carry = carry;
vm.flags.adjust = true;
} else {
vm.flags.adjust = false;
}
if (old_al > 0x99) || old_carry {
let (temp_al, _carry) = al.overflowing_sub(0x60);
al = temp_al;
vm.flags.carry = true;
}
vm.flags.calculate_parity(al as u32);
vm.flags.calculate_sign8(al);
vm.flags.calculate_zero(al as u32);
vm.set_reg(Reg8::AL as u8, SizedValue::Byte(al));
Ok(())
}

pub fn aad(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let al = vm.get_reg(Reg8::AL as u8, ValueSize::Byte).u8_exact()?;
let ah = vm.get_reg(Reg8::AH as u8, ValueSize::Byte).u8_exact()?;
let second_byte = vm.get_arg(pipeline.args[0].location)?.u8_exact()?;
let result = ah.wrapping_mul(second_byte).wrapping_add(al);
vm.flags.calculate_sign8(result);
vm.flags.calculate_parity(result as u32);
vm.flags.calculate_zero(result as u32);
vm.set_reg(Reg8::AL as u8, SizedValue::Byte(result));
vm.set_reg(Reg8::AH as u8, SizedValue::Byte(0));
Ok(())
}

pub fn aam(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let al = vm.get_reg(Reg8::AL as u8, ValueSize::Byte).u8_exact()?;
let ah = vm.get_reg(Reg8::AH as u8, ValueSize::Byte).u8_exact()?;
let second_byte = vm.get_arg(pipeline.args[0].location)?.u8_exact()?;
if second_byte == 0 {
return Err(VMError::DivideByZero);
}
let result = al / second_byte;
let second_result = al % second_byte;
vm.flags.calculate_sign8(second_result);
vm.flags.calculate_parity(second_result as u32);
vm.flags.calculate_zero(second_result as u32);
vm.set_reg(Reg8::AH as u8, SizedValue::Byte(result));
vm.set_reg(Reg8::AL as u8, SizedValue::Byte(second_result));
Ok(())
}

pub fn adc_8bit(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let carry_add = if vm.flags.carry{
1
Expand Down Expand Up @@ -839,7 +965,7 @@ pub fn sbb_8bit(vm: &mut VM, pipeline: &Pipeline, _hv: &mut dyn Hypervisor) -> R
0
};
let prelim_dif = vm.get_arg(pipeline.args[0].location)?.u8_exact()?;
vm.set_arg(pipeline.args[0].location, SizedValue::Byte(prelim_dif.wrapping_sub(carry_sub)));
vm.set_arg(pipeline.args[0].location, SizedValue::Byte(prelim_dif.wrapping_sub(carry_sub)))?;
return sub_8bit(vm, pipeline, _hv);
}

Expand Down
150 changes: 150 additions & 0 deletions tests/simple_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2059,6 +2059,106 @@ fn test_cmpxchg_byte_not_equal() {
assert_eq!(vm.flags, X86Flags{carry: true, adjust: true, sign: true, parity: true, ..Default::default()});
}

#[test]
fn test_aaa() {
let vm = execute_vm_with_asm("
mov al, 0x78
aaa
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0x08);
assert_eq!(vm.flags, X86Flags{..Default::default()});
}

#[test]
fn test_aaa2() {
let vm = execute_vm_with_asm("
mov al, 0xAA
aaa
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0x0100);
assert_eq!(vm.flags, X86Flags{carry: true, adjust: true, ..Default::default()});
}

#[test]
fn test_aas() {
let vm = execute_vm_with_asm("
mov al, 0x79
aas
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0x09);
assert_eq!(vm.flags, X86Flags{..Default::default()});
}

#[test]
fn test_aas2() {
let vm = execute_vm_with_asm("
mov al, 0xAA
aas
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0xff04);
assert_eq!(vm.flags, X86Flags{carry: true, adjust: true, ..Default::default()});
}

#[test]
fn test_aam() {
let vm = execute_vm_with_asm("
mov al, 0xAA
aam
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0x1100);
assert_eq!(vm.flags, X86Flags{parity: true, zero: true, ..Default::default()});
}

#[test]
fn test_aam2() {
let vm = execute_vm_with_asm("
mov al, 0x79
aam
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0xc01);
assert_eq!(vm.flags, X86Flags{..Default::default()});
}

#[test]
fn test_aam3() {
let vm = execute_vm_with_asm("
mov ax, 0xaabb
aam 0xfa
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0xbb);
assert_eq!(vm.flags, X86Flags{sign: true, parity: true, ..Default::default()});
}

#[test]
fn test_aad() {
let vm = execute_vm_with_asm("
mov ax, 0xAAAA
aad
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0x4e);
assert_eq!(vm.flags, X86Flags{parity: true, ..Default::default()});
}

#[test]
fn test_aad2() {
let vm = execute_vm_with_asm("
mov al, 0x79
aad
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0x79);
assert_eq!(vm.flags, X86Flags{..Default::default()});
}

#[test]
fn test_aad3() {
let vm = execute_vm_with_asm("
mov ax, 0xaabb
aad 0xfa
hlt");
assert_eq!(vm.reg16(Reg16::AX), 0xbf);
assert_eq!(vm.flags, X86Flags{sign: true, ..Default::default()});
}

#[test]
fn test_pushf_popf() {
let vm = execute_vm_with_asm("
Expand All @@ -2075,4 +2175,54 @@ fn test_pushf_popf() {
popf
hlt");
assert_eq!(vm.flags, X86Flags{carry: true, adjust: true, sign: true, parity: true, ..Default::default()});
}

#[test]
fn test_lahf() {
let vm = execute_vm_with_asm("
mov ax, 0xaabb
aam 0xFA
lahf
hlt");
assert_eq!(vm.reg8(Reg8::AH), 0x86);
assert_eq!(vm.flags, X86Flags{sign: true, parity: true, ..Default::default()});
}

#[test]
fn test_sahf() {
let vm = execute_vm_with_asm("
mov ax, 0xaabb
mov bx, 0x86
mov ecx, 0xFFFFFF01
aam 0xFA
lahf
cmp ebx, ecx
sahf
hlt");
assert_eq!(vm.reg8(Reg8::AH), 0x86);
assert_eq!(vm.flags, X86Flags{sign: true, parity: true, ..Default::default()});
}

#[test]
fn test_daa() {
let vm = execute_vm_with_asm("
mov al, 0x79
mov bl, 0x35
add al, bl
daa
hlt");
assert_eq!(vm.reg8(Reg8::AL), 0x14);
assert_eq!(vm.flags, X86Flags{adjust: true, carry: true, parity: true, overflow: true, ..Default::default()});
}

#[test]
fn test_das() {
let vm = execute_vm_with_asm("
mov al, 0x35
mov bl, 0x47
sub al, bl
das
hlt");
assert_eq!(vm.reg8(Reg8::AL), 0x88);
assert_eq!(vm.flags, X86Flags{sign: true, adjust: true, carry: true, parity: true, ..Default::default()});
}