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.
This commit is contained in:
@@ -88,6 +88,12 @@ pub trait RValue<T> {
|
|||||||
fn read(&self) -> T;
|
fn read(&self) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RValue<u8> for u8 {
|
||||||
|
fn read(&self) -> u8 {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LValue<u16> for u16 {
|
impl LValue<u16> for u16 {
|
||||||
fn write(&mut self, val: u16) {
|
fn write(&mut self, val: u16) {
|
||||||
*self = val;
|
*self = val;
|
||||||
@@ -100,6 +106,27 @@ impl RValue<u16> for u16 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RegHi<'a> {
|
||||||
|
reg: &'a mut u16
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LValue<u8> 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<u8> 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 {
|
macro_rules! step {
|
||||||
// Base case: all args processed and ready to call op
|
// Base case: all args processed and ready to call op
|
||||||
(@code ( $($args:tt)* ),
|
(@code ( $($args:tt)* ),
|
||||||
@@ -112,7 +139,9 @@ macro_rules! step {
|
|||||||
(@code ( $($args:tt)* ),
|
(@code ( $($args:tt)* ),
|
||||||
$cpu:ident, $bus:ident, $name:ident, $cycles:literal,
|
$cpu:ident, $bus:ident, $name:ident, $cycles:literal,
|
||||||
($next:ident $(= $nextrhs:ident)? $($rest:ident $(= $restrhs:ident)?)*)) => {
|
($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
|
// accept an argument from a decoder and recur to look for next arg
|
||||||
@@ -123,10 +152,14 @@ macro_rules! step {
|
|||||||
|
|
||||||
// Argument Decoders
|
// 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) => { {
|
(@d16 $cookie:tt, $cpu:ident, $bus:ident) => { {
|
||||||
let mut buf = [0; 2];
|
let mut buf = [0; 2];
|
||||||
buf[0] = $cpu.next_ip($bus);
|
buf[0] = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus);
|
||||||
buf[1] = $cpu.next_ip($bus);
|
buf[1] = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus);
|
||||||
step!(@arg $cookie, &LittleEndian::read_u16(&buf))
|
step!(@arg $cookie, &LittleEndian::read_u16(&buf))
|
||||||
} };
|
} };
|
||||||
|
|
||||||
@@ -138,21 +171,25 @@ macro_rules! step {
|
|||||||
step!(@arg $cookie, &mut $cpu.$reg);
|
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) => {
|
(@regval=$reg:ident $cookie:tt, $cpu:ident, $bus:ident) => {
|
||||||
step!(@arg $cookie, $cpu.$reg);
|
step!(@arg $cookie, $cpu.$reg);
|
||||||
};
|
};
|
||||||
|
|
||||||
(@rel16 $cookie:tt, $cpu:ident, $bus:ident) => { {
|
(@rel16 $cookie:tt, $cpu:ident, $bus:ident) => { {
|
||||||
let mut buf = [0; 2];
|
let mut buf = [0; 2];
|
||||||
buf[0] = $cpu.next_ip($bus);
|
buf[0] = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus);
|
||||||
buf[1] = $cpu.next_ip($bus);
|
buf[1] = i8088::next_ip($cpu.cs, &mut $cpu.ip, $bus);
|
||||||
step!(@arg $cookie, LittleEndian::read_i16(&buf))
|
step!(@arg $cookie, LittleEndian::read_i16(&buf))
|
||||||
} };
|
} };
|
||||||
|
|
||||||
// Entry Point
|
// Entry Point
|
||||||
(($cpu:ident, $bus:ident) => { $( $code:literal => $name:ident[$($args:ident $(= $argrhs:ident)?),*] / $cycles:literal ),*$(,)? } ) => {
|
(($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) {
|
match(opcode) {
|
||||||
$( $code => step!(@code (), $cpu, $bus, $name, $cycles, ($($args $(= $argrhs)?)*)) ),*,
|
$( $code => step!(@code (), $cpu, $bus, $name, $cycles, ($($args $(= $argrhs)?)*)) ),*,
|
||||||
_ => unimplemented!("opcode: {:02X}\ncpu: {:#X?}", opcode, $cpu)
|
_ => unimplemented!("opcode: {:02X}\ncpu: {:#X?}", opcode, $cpu)
|
||||||
@@ -170,6 +207,7 @@ impl i8088 {
|
|||||||
pub fn run(&mut self, bus: &mut Bus) {
|
pub fn run(&mut self, bus: &mut Bus) {
|
||||||
loop {
|
loop {
|
||||||
step!((self, bus) => {
|
step!((self, bus) => {
|
||||||
|
0xB4 => mov[reghi=a, d8] / 4,
|
||||||
0xBA => mov[reg=d, d16] / 4,
|
0xBA => mov[reg=d, d16] / 4,
|
||||||
0xC3 => ret[reg=ip, regval=ss, reg=sp, mem] / 20,
|
0xC3 => ret[reg=ip, regval=ss, reg=sp, mem] / 20,
|
||||||
0xE8 => call[reg=ip, regval=ss, reg=sp, mem, rel16] / 23,
|
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 {
|
fn next_ip<'a>(cs: u16, ip: &mut u16, bus: &Bus) -> u8 {
|
||||||
let eip = segoff_to_addr(self.cs, self.ip);
|
let eip = segoff_to_addr(cs, *ip);
|
||||||
self.ip += 1;
|
*ip += 1;
|
||||||
|
|
||||||
// We'll assume cpu is always executing in RAM. Also assume the
|
// 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
|
// IP doesn't reach the end of the segment (My guess is that it
|
||||||
|
|||||||
Reference in New Issue
Block a user