From fa49d19ae0bd0afdc1bce4948aa3a4393a497537 Mon Sep 17 00:00:00 2001 From: Jared Burce Date: Sat, 6 Mar 2021 01:01:53 -0800 Subject: [PATCH] emu: arg=rhs parsing. d16, reg, regval argtypes. non-generic MOV. --- src/emu/i8088.rs | 74 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index 52a259f..a05db3b 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -50,17 +50,37 @@ pub struct Flags { } mod ops { - pub fn call(cpu: &mut super::i8088, mem: &mut [u8], addr: i16) { - let target = cpu.ip.wrapping_add(addr as u16); + use emu::i8088::segoff_to_addr; + use emu::byteorder::{ByteOrder, LittleEndian}; + + pub fn call(ip: &mut u16, ss: u16, sp: &mut u16, mem: &mut [u8], addr: i16) { + let target = ip.wrapping_add(addr as u16); trace!("CALL 0x{:04X}", target); - cpu.push16(mem, cpu.ip); - cpu.ip = target; + push16(ss, sp, mem, *ip); + *ip = target; } - pub fn ret(cpu: &mut super::i8088, mem: &[u8]) { - trace!("RET"); - cpu.ip = cpu.pop16(mem) + pub fn mov(reg: &mut super::Reg16, val: u16) { + reg.x = val; } + + pub fn pop16(ss: u16, sp: &mut u16, mem: &[u8]) -> u16 { + let val = LittleEndian::read_u16(&mem[segoff_to_addr(ss, *sp)..]); + *sp += 2; + val + } + + pub fn push16(ss: u16, sp: &mut u16, mem: &mut [u8], val: u16) { + // XXX: Not checking for stack faults or anything + *sp -= 2; + LittleEndian::write_u16(&mut mem[segoff_to_addr(ss, *sp)..], val); + } + + pub fn ret(ip: &mut u16, ss: u16, sp: &mut u16, mem: &[u8]) { + trace!("RET"); + *ip = pop16(ss, sp, mem); + } + } macro_rules! step { @@ -74,8 +94,8 @@ macro_rules! step { // Inductive case: decode next arg to be placed in list (@code ( $($args:tt)* ), $cpu:ident, $bus:ident, $name:ident, $cycles:literal, - ($next:tt $($rest:tt)*)) => { - step!(@$next ( ($($args)*), $cpu, $bus, $name, $cycles, ($($rest)*) ), $cpu, $bus) + ($next:ident $(= $nextrhs:ident)? $($rest:ident $(= $restrhs:ident)?)*)) => { + step!(@$next$(= $nextrhs)? ( ($($args)*), $cpu, $bus, $name, $cycles, ($($rest $(= $restrhs)?)*) ), $cpu, $bus) }; // accept an argument from a decoder and recur to look for next arg @@ -86,10 +106,25 @@ macro_rules! step { // Argument Decoders + (@d16 $cookie:tt, $cpu:ident, $bus:ident) => { { + let mut buf = [0; 2]; + buf[0] = $cpu.next_ip($bus); + buf[1] = $cpu.next_ip($bus); + step!(@arg $cookie, LittleEndian::read_u16(&buf)) + } }; + (@mem $cookie:tt, $cpu:ident, $bus:ident) => { step!(@arg $cookie, &mut $bus.ram) }; + (@reg=$reg:ident $cookie:tt, $cpu:ident, $bus:ident) => { + step!(@arg $cookie, &mut $cpu.$reg); + }; + + (@regval=$reg:ident $cookie:tt, $cpu:ident, $bus:ident) => { + step!(@arg $cookie, $cpu.$reg); + }; + (@rel16 $cookie:tt, $cpu:ident, $bus:ident) => { { let mut buf = [0; 2]; buf[0] = $cpu.next_ip($bus); @@ -98,11 +133,11 @@ macro_rules! step { } }; // Entry Point - (($cpu:ident, $bus:ident) => { $( $code:literal => $name:ident[$($args:tt),*] / $cycles:literal ),*$(,)? } ) => { + (($cpu:ident, $bus:ident) => { $( $code:literal => $name:ident[$($args:ident $(= $argrhs:ident)?),*] / $cycles:literal ),*$(,)? } ) => { { let opcode = $cpu.next_ip($bus); match(opcode) { - $( $code => step!(@code ($cpu), $cpu, $bus, $name, $cycles, ($($args)*)) ),*, + $( $code => step!(@code (), $cpu, $bus, $name, $cycles, ($($args $(= $argrhs)?)*)) ),*, _ => unimplemented!("opcode: {:02X}", opcode) } } @@ -118,24 +153,13 @@ impl i8088 { pub fn run(&mut self, bus: &mut Bus) { loop { step!((self, bus) => { - 0xC3 => ret[mem] / 20, - 0xE8 => call[mem, rel16] / 23, + 0xBA => mov[reg=d, d16] / 4, + 0xC3 => ret[reg=ip, regval=ss, reg=sp, mem] / 20, + 0xE8 => call[reg=ip, regval=ss, reg=sp, mem, rel16] / 23, }) } } - fn push16(&mut self, mem: &mut [u8], val: u16) { - // XXX: Not checking for stack faults or anything - self.sp -= 2; - LittleEndian::write_u16(&mut mem[segoff_to_addr(self.ss, self.sp)..], val); - } - - fn pop16(&mut self, mem: &[u8]) -> u16 { - let val = LittleEndian::read_u16(&mem[segoff_to_addr(self.ss, self.sp)..]); - self.sp += 2; - val - } - fn next_ip<'a>(&mut self, bus: &Bus) -> u8 { let eip = segoff_to_addr(self.cs, self.ip); self.ip += 1;