diff --git a/src/emu/dos.rs b/src/emu/dos.rs new file mode 100644 index 0000000..28603f1 --- /dev/null +++ b/src/emu/dos.rs @@ -0,0 +1,9 @@ +use emu::pc::Bus; +use emu::i8088::i8088; + +pub fn interrupt(cpu: &mut i8088, _bus: &mut Bus) { + let svc = cpu.a; + match svc { + _ => unimplemented!("dos service: {:#02X}\ncpu: {:#X?}", svc, cpu) + } +} diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index 353238d..683526d 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -50,8 +50,9 @@ pub struct Flags { } mod ops { - use emu::i8088::{LValue, RValue, segoff_to_addr}; use emu::byteorder::{ByteOrder, LittleEndian}; + use emu::dos; + use emu::i8088::{Bus, LValue, RValue, i8088, segoff_to_addr}; pub fn call(ip: &mut u16, ss: u16, sp: &mut u16, mem: &mut [u8], addr: i16) { let target = ip.wrapping_add(addr as u16); @@ -59,6 +60,13 @@ mod ops { *ip = target; } + pub fn int(cpu: &mut i8088, bus: &mut Bus, num: &u8) { + match num { + 0x21 => dos::interrupt(cpu, bus), + _ => unimplemented!("interrupt: {:02X}\ncpu: {:#X?}", num, cpu) + } + } + pub fn mov(dst: &mut impl LValue, src: &impl RValue) { dst.write(src.read()); } @@ -130,14 +138,14 @@ impl<'a> RValue for RegHi<'a> { macro_rules! step { // Base case: all args processed and ready to call op (@code ( $($args:tt)* ), - $cpu:ident, $bus:ident, $name:ident, $cycles:literal, + $cpu:expr, $bus:expr, $name:ident, $cycles:literal, ()) => { ops::$name($($args),*); }; // Inductive case: decode next arg to be placed in list (@code ( $($args:tt)* ), - $cpu:ident, $bus:ident, $name:ident, $cycles:literal, + $cpu:expr, $bus:expr, $name:ident, $cycles:literal, ($next:ident $(= $nextrhs:ident)? $($rest:ident $(= $restrhs:ident)?)*)) => { step!(@$next$(= $nextrhs)? ( ($($args)*), $cpu, $bus, $name, $cycles, ($($rest $(= $restrhs)?)*) ), @@ -145,41 +153,50 @@ macro_rules! step { }; // accept an argument from a decoder and recur to look for next arg - (@arg ( ($($args:tt)*), $cpu:ident, $bus:ident, $name:ident, $cycles:literal, ( $($rest:tt)* ) ), + (@arg ( ($($args:tt)*), $cpu:expr, $bus:expr, $name:ident, $cycles:literal, ( $($rest:tt)* ) ), $arg:expr) => { step!(@code ($($args)* $arg), $cpu, $bus, $name, $cycles, ( $($rest)* )) }; // Argument Decoders - (@d8 $cookie:tt, $cpu:ident, $bus:ident) => { { - step!(@arg $cookie, &i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus)) + (@bus $cookie:tt, $cpu:expr, $bus:expr) => { { + step!(@arg $cookie, $bus) } }; - (@d16 $cookie:tt, $cpu:ident, $bus:ident) => { { + (@cpu $cookie:tt, $cpu:expr, $bus:expr) => { { + step!(@arg $cookie, $cpu) + } }; + + (@d8 $cookie:tt, $cpu:expr, $bus:expr) => { { + let d8 = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus); + step!(@arg $cookie, &d8) + } }; + + (@d16 $cookie:tt, $cpu:expr, $bus:expr) => { { let mut buf = [0; 2]; buf[0] = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus); buf[1] = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus); step!(@arg $cookie, &LittleEndian::read_u16(&buf)) } }; - (@mem $cookie:tt, $cpu:ident, $bus:ident) => { + (@mem $cookie:tt, $cpu:expr, $bus:expr) => { step!(@arg $cookie, &mut $bus.ram) }; - (@reg=$reg:ident $cookie:tt, $cpu:ident, $bus:ident) => { + (@reg=$reg:ident $cookie:tt, $cpu:expr, $bus:expr) => { step!(@arg $cookie, &mut $cpu.$reg); }; - (@reghi=$reg:ident $cookie:tt, $cpu:ident, $bus:ident) => { + (@reghi=$reg:ident $cookie:tt, $cpu:expr, $bus:expr) => { step!(@arg $cookie, &mut RegHi { reg: &mut $cpu.$reg }); }; - (@regval=$reg:ident $cookie:tt, $cpu:ident, $bus:ident) => { + (@regval=$reg:ident $cookie:tt, $cpu:expr, $bus:expr) => { step!(@arg $cookie, $cpu.$reg); }; - (@rel16 $cookie:tt, $cpu:ident, $bus:ident) => { { + (@rel16 $cookie:tt, $cpu:expr, $bus:expr) => { { let mut buf = [0; 2]; buf[0] = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus); buf[1] = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus); @@ -187,7 +204,7 @@ macro_rules! step { } }; // Entry Point - (($cpu:ident, $bus:ident) => { $( $code:literal => $name:ident[$($args:ident $(= $argrhs:ident)?),*] / $cycles:literal ),*$(,)? } ) => { + (($cpu:expr, $bus:expr) => { $( $code:literal => $name:ident[$($args:ident $(= $argrhs:ident)?),*] / $cycles:literal ),*$(,)? } ) => { { let opcode = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus); match(opcode) { @@ -210,6 +227,7 @@ impl i8088 { 0xB4 => mov[reghi=a, d8] / 4, 0xBA => mov[reg=d, d16] / 4, 0xC3 => ret[reg=ip, regval=ss, reg=sp, mem] / 20, + 0xCD => int[cpu, bus, d8] / 71, 0xE8 => call[reg=ip, regval=ss, reg=sp, mem, rel16] / 23, }) } diff --git a/src/emu/mod.rs b/src/emu/mod.rs index d9a9281..66dbcf2 100644 --- a/src/emu/mod.rs +++ b/src/emu/mod.rs @@ -1,4 +1,5 @@ extern crate byteorder; -pub mod pc; +pub mod dos; pub mod i8088; +pub mod pc;