From 0f4e52697abe67a19ecd316a8dd5d8702de58cf1 Mon Sep 17 00:00:00 2001 From: Jared Burce Date: Sat, 6 Mar 2021 04:52:09 -0800 Subject: [PATCH] emu: reghi & d8 address modes. make next_ip assoc instead of member next_ip would borrow all of the cpu, now we just need IP and CS. --- src/emu/i8088.rs | 56 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index 3e42c8d..353238d 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -88,6 +88,12 @@ pub trait RValue { fn read(&self) -> T; } +impl RValue for u8 { + fn read(&self) -> u8 { + *self + } +} + impl LValue for u16 { fn write(&mut self, val: u16) { *self = val; @@ -100,6 +106,27 @@ impl RValue for u16 { } } +struct RegHi<'a> { + reg: &'a mut u16 +} + +impl<'a> LValue for RegHi<'a> { + fn write(&mut self, val: u8) { + let mut buf = [0; 2]; + LittleEndian::write_u16(&mut buf, *self.reg); + buf[1] = val; + *self.reg = LittleEndian::read_u16(&buf); + } +} + +impl<'a> RValue for RegHi<'a> { + fn read(&self) -> u8 { + let mut buf = [0; 2]; + LittleEndian::write_u16(&mut buf, *self.reg); + buf[1] as u8 + } +} + macro_rules! step { // Base case: all args processed and ready to call op (@code ( $($args:tt)* ), @@ -112,7 +139,9 @@ macro_rules! step { (@code ( $($args:tt)* ), $cpu:ident, $bus:ident, $name:ident, $cycles:literal, ($next:ident $(= $nextrhs:ident)? $($rest:ident $(= $restrhs:ident)?)*)) => { - step!(@$next$(= $nextrhs)? ( ($($args)*), $cpu, $bus, $name, $cycles, ($($rest $(= $restrhs)?)*) ), $cpu, $bus) + 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 @@ -123,10 +152,14 @@ macro_rules! step { // Argument Decoders + (@d8 $cookie:tt, $cpu:ident, $bus:ident) => { { + step!(@arg $cookie, &i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus)) + } }; + (@d16 $cookie:tt, $cpu:ident, $bus:ident) => { { let mut buf = [0; 2]; - buf[0] = $cpu.next_ip($bus); - buf[1] = $cpu.next_ip($bus); + 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)) } }; @@ -138,21 +171,25 @@ macro_rules! step { step!(@arg $cookie, &mut $cpu.$reg); }; + (@reghi=$reg:ident $cookie:tt, $cpu:ident, $bus:ident) => { + step!(@arg $cookie, &mut RegHi { reg: &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); - buf[1] = $cpu.next_ip($bus); + 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_i16(&buf)) } }; // Entry Point (($cpu:ident, $bus:ident) => { $( $code:literal => $name:ident[$($args:ident $(= $argrhs:ident)?),*] / $cycles:literal ),*$(,)? } ) => { { - let opcode = $cpu.next_ip($bus); + let opcode = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus); match(opcode) { $( $code => step!(@code (), $cpu, $bus, $name, $cycles, ($($args $(= $argrhs)?)*)) ),*, _ => unimplemented!("opcode: {:02X}\ncpu: {:#X?}", opcode, $cpu) @@ -170,6 +207,7 @@ impl i8088 { pub fn run(&mut self, bus: &mut Bus) { loop { step!((self, bus) => { + 0xB4 => mov[reghi=a, d8] / 4, 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, @@ -177,9 +215,9 @@ impl i8088 { } } - fn next_ip<'a>(&mut self, bus: &Bus) -> u8 { - let eip = segoff_to_addr(self.cs, self.ip); - self.ip += 1; + fn next_ip<'a>(cs: u16, ip: &mut u16, bus: &Bus) -> u8 { + let eip = segoff_to_addr(cs, *ip); + *ip += 1; // We'll assume cpu is always executing in RAM. Also assume the // IP doesn't reach the end of the segment (My guess is that it