emu: modrm displacement, LEA instruction
This commit is contained in:
116
src/emu/i8088.rs
116
src/emu/i8088.rs
@@ -64,7 +64,7 @@ macro_rules! step {
|
|||||||
// Inductive case: decode next arg to be placed in list
|
// Inductive case: decode next arg to be placed in list
|
||||||
(@code ( $($done:tt)* ),
|
(@code ( $($done:tt)* ),
|
||||||
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
|
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
|
||||||
($next:ident $(= $nextrhs:ident)? $($rest:ident $(= $restrhs:ident)?)*)) => {
|
($next:ident $(= $nextrhs:tt)? $($rest:ident $(= $restrhs:tt)?)*)) => {
|
||||||
step!(@$next$(= $nextrhs)?
|
step!(@$next$(= $nextrhs)?
|
||||||
// "cookie" tt to be passed thru to @arg so we have all the args for the recursive step
|
// "cookie" tt to be passed thru to @arg so we have all the args for the recursive step
|
||||||
( ($($done)*), $cpu, $bus, $prefix, $modrm, $name, $cycles, ($($rest $(= $restrhs)?)*) ),
|
( ($($done)*), $cpu, $bus, $prefix, $modrm, $name, $cycles, ($($rest $(= $restrhs)?)*) ),
|
||||||
@@ -87,8 +87,7 @@ macro_rules! step {
|
|||||||
|
|
||||||
(@addr $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $prefix_loop:lifetime), $modrm:tt) => { {
|
(@addr $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $prefix_loop:lifetime), $modrm:tt) => { {
|
||||||
let a16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus);
|
let a16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus);
|
||||||
let addr = segoff_to_addr($segment.unwrap(), a16);
|
step!(@arg $cookie, &mut Addr { bus: $bus, segment: $segment.unwrap(), offset: a16 } )
|
||||||
step!(@arg $cookie, &mut Addr { bus: $bus, addr: addr } )
|
|
||||||
} };
|
} };
|
||||||
|
|
||||||
(@bus $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
(@bus $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||||
@@ -109,33 +108,76 @@ macro_rules! step {
|
|||||||
step!(@arg $cookie, &d16)
|
step!(@arg $cookie, &d16)
|
||||||
} };
|
} };
|
||||||
|
|
||||||
|
(@displace0=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $prefix_loop:lifetime), $modrm:tt) => {
|
||||||
|
step!(@arg $cookie, &mut Addr { bus: $bus,
|
||||||
|
segment: $segment.unwrap(),
|
||||||
|
offset: $cpu.$reg1.get() $(+ $cpu.$reg2.get())? })
|
||||||
|
};
|
||||||
|
|
||||||
|
(@displace8=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $prefix_loop:lifetime), $modrm:tt) => { {
|
||||||
|
let d8 = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus);
|
||||||
|
step!(@arg $cookie, &mut Addr { bus: $bus,
|
||||||
|
segment: $segment.unwrap(),
|
||||||
|
offset: $cpu.$reg1.get() $(+ $cpu.$reg2.get())? + d8 as u16 })
|
||||||
|
} };
|
||||||
|
|
||||||
|
(@displace16=($reg1:ident $(+ $reg2:ident)? ) $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $prefix_loop:lifetime), $modrm:tt) => { {
|
||||||
|
let d16 = i8088::next_ip16($cpu.cs.get(), &mut $cpu.ip, $bus);
|
||||||
|
step!(@arg $cookie, &mut Addr { bus: $bus,
|
||||||
|
segment: $segment.unwrap(),
|
||||||
|
offset: $cpu.$reg1.get() $(+ $cpu.$reg2.get())? + d16 })
|
||||||
|
} };
|
||||||
|
|
||||||
(@mem $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
(@mem $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
|
||||||
step!(@arg $cookie, &mut $bus.ram)
|
step!(@arg $cookie, &mut $bus.ram)
|
||||||
};
|
};
|
||||||
|
|
||||||
(@modrm16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt,
|
(@modrm $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt,
|
||||||
($modrm_val:ident, { $($val:literal => $($args:ident = $argrhs:tt),* / $mode:ident $cycles:literal),*$(,)? }, $modrm8:tt)) => { {
|
($modrm_val:ident,
|
||||||
|
{ $($val:literal => $($args:ident $(= $argrhs:tt)?),* / $mode:ident $cycles:literal),*$(,)? },
|
||||||
|
$modrm16:tt,
|
||||||
|
$modrm8:tt
|
||||||
|
)) => { {
|
||||||
let modrm_val = $modrm_val & !0x38;
|
let modrm_val = $modrm_val & !0x38;
|
||||||
match modrm_val {
|
match modrm_val {
|
||||||
$( $val => step!(@push $cookie, ($($args = $argrhs)* ) ) ),*,
|
$( $val => step!(@push $cookie, ($($args $(= $argrhs)?)* ) ) ),*,
|
||||||
|
_ => unimplemented!("modrm: {:02X}({:02X})\ncpu: {:#X?}", $modrm_val, modrm_val, $cpu)
|
||||||
|
}
|
||||||
|
} };
|
||||||
|
|
||||||
|
(@modrm16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt,
|
||||||
|
($modrm_val:ident,
|
||||||
|
{ $($val:literal => $($args:ident $(= $argrhs:tt)?),* / $mode:ident $cycles:literal),*$(,)? },
|
||||||
|
{ $($val16:literal => $($args16:ident $(= $argrhs16:tt)?),* / $mode16:ident $cycles16:literal),*$(,)? },
|
||||||
|
$modrm8:tt
|
||||||
|
)) => { {
|
||||||
|
let modrm_val = $modrm_val & !0x38;
|
||||||
|
match modrm_val {
|
||||||
|
$( $val => step!(@push $cookie, ($($args $(= $argrhs)?)* ) ) ),*,
|
||||||
|
$( $val16 => step!(@push $cookie, ($($args16 $(= $argrhs16)?)* ) ) ),*,
|
||||||
_ => unimplemented!("modrm: {:02X}({:02X})\ncpu: {:#X?}", $modrm_val, modrm_val, $cpu)
|
_ => unimplemented!("modrm: {:02X}({:02X})\ncpu: {:#X?}", $modrm_val, modrm_val, $cpu)
|
||||||
}
|
}
|
||||||
} };
|
} };
|
||||||
|
|
||||||
(@modrm8 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt,
|
(@modrm8 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt,
|
||||||
($modrm_val:ident, $modrm16:tt, { $($val:literal => $($args:ident = $argrhs:tt),* / $mode:ident $cycles:literal),*$(,)? } )) => { {
|
($modrm_val:ident,
|
||||||
|
{ $($val:literal => $($args:ident $(= $argrhs:tt)?),* / $mode:ident $cycles:literal),*$(,)? },
|
||||||
|
$modrm16:tt,
|
||||||
|
{ $($val8:literal => $($args8:ident $(= $argrhs8:tt)?),* / $mode8:ident $cycles8:literal),*$(,)? }
|
||||||
|
)) => { {
|
||||||
let modrm_val = $modrm_val & !0x38;
|
let modrm_val = $modrm_val & !0x38;
|
||||||
match modrm_val {
|
match modrm_val {
|
||||||
$( $val => step!(@push $cookie, ($($args = $argrhs)* ) ) ),*,
|
$( $val => step!(@push $cookie, ($($args $(= $argrhs)?)* ) ) ),*,
|
||||||
|
$( $val8 => step!(@push $cookie, ($($args8 $(= $argrhs8)?)* ) ) ),*,
|
||||||
_ => unimplemented!("modrm: {:02X}({:02X})\ncpu: {:#X?}", $modrm_val, modrm_val, $cpu)
|
_ => unimplemented!("modrm: {:02X}({:02X})\ncpu: {:#X?}", $modrm_val, modrm_val, $cpu)
|
||||||
}
|
}
|
||||||
} };
|
} };
|
||||||
|
|
||||||
(@prefix $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $prefix_loop:lifetime), $modrm:tt) => { continue $prefix_loop; };
|
(@prefix $cookie:tt, $cpu:expr, $bus:expr, ($segment:ident, $prefix_loop:lifetime), $modrm:tt) => { continue $prefix_loop; };
|
||||||
|
|
||||||
(@r16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, ($modrm:ident, $modrm16:tt, $modrm8:tt)) => {
|
(@r16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, ($modrm_val:ident, $modrm:tt, $modrm16:tt, $modrm8:tt)) => {
|
||||||
// TODO: Should these also be passed into the macro like the modrm specs?
|
// TODO: Should these also be passed into the macro like the modrm specs?
|
||||||
match $modrm >> 3 & 0x7 {
|
match $modrm_val >> 3 & 0x7 {
|
||||||
0 => step!(@arg $cookie, &mut Reg { reg: &$cpu.a } ),
|
0 => step!(@arg $cookie, &mut Reg { reg: &$cpu.a } ),
|
||||||
1 => step!(@arg $cookie, &mut Reg { reg: &$cpu.c } ),
|
1 => step!(@arg $cookie, &mut Reg { reg: &$cpu.c } ),
|
||||||
2 => step!(@arg $cookie, &mut Reg { reg: &$cpu.d } ),
|
2 => step!(@arg $cookie, &mut Reg { reg: &$cpu.d } ),
|
||||||
@@ -148,9 +190,9 @@ macro_rules! step {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
(@r8 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, ($modrm:ident, $modrm16:tt, $modrm8:tt)) => {
|
(@r8 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, ($modrm_val:ident, $modrm:tt, $modrm16:tt, $modrm8:tt)) => {
|
||||||
// TODO: Should these also be passed into the macro like the modrm specs?
|
// TODO: Should these also be passed into the macro like the modrm specs?
|
||||||
match $modrm >> 3 & 0x7 {
|
match $modrm_val >> 3 & 0x7 {
|
||||||
0 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.a } ),
|
0 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.a } ),
|
||||||
1 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.c } ),
|
1 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.c } ),
|
||||||
2 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.d } ),
|
2 => step!(@arg $cookie, &mut RegHi { reg: &$cpu.d } ),
|
||||||
@@ -192,13 +234,13 @@ macro_rules! step {
|
|||||||
} };
|
} };
|
||||||
|
|
||||||
// Group Decoder
|
// Group Decoder
|
||||||
(@group $cpu:expr, $bus:expr, $prefix:tt, ($modrm:ident, $modrm16:tt, $modrm8:tt), $code:literal,
|
(@group $cpu:expr, $bus:expr, $prefix:tt, ($modrm_val:ident, $modrm:tt, $modrm16:tt, $modrm8:tt), $code:literal,
|
||||||
{ $( $subcode:literal =>
|
{ $( $subcode:literal =>
|
||||||
$name:ident[$($args:ident $(= $argrhs:ident)?),*] / $cycles:literal),*$(,)? } ) => { {
|
$name:ident[$($args:ident $(= $argrhs:tt)?),*] / $cycles:literal),*$(,)? } ) => { {
|
||||||
let subcode = $modrm & 0x38;
|
let subcode = $modrm_val & 0x38;
|
||||||
match subcode {
|
match subcode {
|
||||||
$( $subcode => step!(@code (), $cpu, $bus, $prefix, ($modrm, $modrm16, $modrm8), $name, $cycles, ($($args $(= $argrhs)?)*)) ),*,
|
$( $subcode => step!(@code (), $cpu, $bus, $prefix, ($modrm_val, $modrm, $modrm16, $modrm8), $name, $cycles, ($($args $(= $argrhs)?)*)) ),*,
|
||||||
_ => unimplemented!("opcode: {:02X} {:02X}({:02X})\ncpu: {:#X?}", $code, $modrm, subcode, $cpu)
|
_ => unimplemented!("opcode: {:02X} {:02X}({:02X})\ncpu: {:#X?}", $code, $modrm_val, subcode, $cpu)
|
||||||
} }
|
} }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -209,31 +251,32 @@ macro_rules! step {
|
|||||||
|
|
||||||
// Non-group opcodes
|
// Non-group opcodes
|
||||||
$( $($ext:pat)? =>
|
$( $($ext:pat)? =>
|
||||||
$name:ident[$($args:ident $(= $argrhs:ident)?),*] / $cycles:literal
|
$name:ident[$($args:ident $(= $argrhs:tt)?),*] / $cycles:literal
|
||||||
)?
|
)?
|
||||||
|
|
||||||
// Group opcodes
|
// Group opcodes
|
||||||
$( : $subcodes:tt )?
|
$( : $subcodes:tt )?
|
||||||
),*
|
),*
|
||||||
$(,)? },
|
$(,)? },
|
||||||
|
modrm: $modrm:tt,
|
||||||
modrm16: $modrm16:tt,
|
modrm16: $modrm16:tt,
|
||||||
modrm8: $modrm8:tt
|
modrm8: $modrm8:tt
|
||||||
) => {
|
) => {
|
||||||
{
|
{
|
||||||
let mut segment = None;
|
let mut segment = None;
|
||||||
let modrm: u8; // Type ascription unnecessary but gives better err messages when missing $ext
|
let modrm_val: u8; // Type ascription unnecessary but gives better err messages when missing $ext
|
||||||
'prefix_loop: loop {
|
'prefix_loop: loop {
|
||||||
let opcode = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus);
|
let opcode = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus);
|
||||||
match(opcode) {
|
match(opcode) {
|
||||||
$( $( $code => {
|
$( $( $code => {
|
||||||
$( let $ext = (); /* No-op just to trigger expansion. */
|
$( let $ext = (); /* No-op just to trigger expansion. */
|
||||||
modrm = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus); )?
|
modrm_val = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus); )?
|
||||||
step!(@code (), $cpu, $bus, (segment, 'prefix_loop), (modrm, $modrm16, $modrm8), $name, $cycles, ($($args $(= $argrhs)?)*))
|
step!(@code (), $cpu, $bus, (segment, 'prefix_loop), (modrm_val, $modrm, $modrm16, $modrm8), $name, $cycles, ($($args $(= $argrhs)?)*))
|
||||||
}
|
}
|
||||||
)?
|
)?
|
||||||
$( $code => {
|
$( $code => {
|
||||||
modrm = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus);
|
modrm_val = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus);
|
||||||
step!(@group $cpu, $bus, (segment, 'prefix_loop), (modrm, $modrm16, $modrm8), $code, $subcodes)
|
step!(@group $cpu, $bus, (segment, 'prefix_loop), (modrm_val, $modrm, $modrm16, $modrm8), $code, $subcodes)
|
||||||
}
|
}
|
||||||
)?
|
)?
|
||||||
),*,
|
),*,
|
||||||
@@ -265,6 +308,7 @@ impl i8088 {
|
|||||||
0x08 => mov[modrm16, reg=cs] / "2/13+",
|
0x08 => mov[modrm16, reg=cs] / "2/13+",
|
||||||
0x10 => mov[modrm16, reg=ss] / "2/13+",
|
0x10 => mov[modrm16, reg=ss] / "2/13+",
|
||||||
0x18 => mov[modrm16, reg=ds] / "2/13+", },
|
0x18 => mov[modrm16, reg=ds] / "2/13+", },
|
||||||
|
0x8D _ => lea[r16, modrm] / "2+",
|
||||||
0x8E: { 0x00 => mov[reg=es, modrm16] / "2/12+",
|
0x8E: { 0x00 => mov[reg=es, modrm16] / "2/12+",
|
||||||
0x08 => mov[reg=cs, modrm16] / "2/12+",
|
0x08 => mov[reg=cs, modrm16] / "2/12+",
|
||||||
0x10 => mov[reg=ss, modrm16] / "2/12+",
|
0x10 => mov[reg=ss, modrm16] / "2/12+",
|
||||||
@@ -294,6 +338,32 @@ impl i8088 {
|
|||||||
0xCD => int[cpu, bus, d8] / 71,
|
0xCD => int[cpu, bus, d8] / 71,
|
||||||
0xE8 => call[reg=ip, regval=ss, reg=sp, mem, rel16] / 23,
|
0xE8 => call[reg=ip, regval=ss, reg=sp, mem, rel16] / 23,
|
||||||
},
|
},
|
||||||
|
modrm: {
|
||||||
|
0x00 => seg=ds, displace0=(b+si) / M 7,
|
||||||
|
0x01 => seg=ds, displace0=(b+di) / M 8,
|
||||||
|
0x02 => seg=ss, displace0=(bp+si) / M 8,
|
||||||
|
0x03 => seg=ss, displace0=(bp+di) / M 7,
|
||||||
|
0x04 => seg=ds, displace0=(si) / M 5,
|
||||||
|
0x05 => seg=ds, displace0=(di) / M 5,
|
||||||
|
0x06 => seg=ds, addr / M 6,
|
||||||
|
0x07 => seg=ds, displace0=(b) / M 5,
|
||||||
|
0x40 => seg=ds, displace8=(b+si) / M 11,
|
||||||
|
0x41 => seg=ds, displace8=(b+di) / M 12,
|
||||||
|
0x42 => seg=ss, displace8=(bp+si) / M 12,
|
||||||
|
0x43 => seg=ss, displace8=(bp+di) / M 11,
|
||||||
|
0x44 => seg=ds, displace8=(si) / M 9,
|
||||||
|
0x45 => seg=ds, displace8=(di) / M 9,
|
||||||
|
0x46 => seg=ss, displace8=(bp) / M 9,
|
||||||
|
0x47 => seg=ds, displace8=(b) / M 9,
|
||||||
|
0x80 => seg=ds, displace16=(b+si) / M 11,
|
||||||
|
0x81 => seg=ds, displace16=(b+di) / M 12,
|
||||||
|
0x82 => seg=ss, displace16=(bp+si) / M 12,
|
||||||
|
0x83 => seg=ss, displace16=(bp+di) / M 11,
|
||||||
|
0x84 => seg=ds, displace16=(si) / M 9,
|
||||||
|
0x85 => seg=ds, displace16=(di) / M 9,
|
||||||
|
0x86 => seg=ss, displace16=(bp) / M 9,
|
||||||
|
0x87 => seg=ds, displace16=(b) / M 9,
|
||||||
|
},
|
||||||
modrm16: {
|
modrm16: {
|
||||||
0xC0 => reg=a / R 0,
|
0xC0 => reg=a / R 0,
|
||||||
0xC1 => reg=c / R 0,
|
0xC1 => reg=c / R 0,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use emu::util::segoff_to_addr;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use emu::util::{read_hi, read_lo, write_hi, write_lo};
|
use emu::util::{read_hi, read_lo, write_hi, write_lo};
|
||||||
@@ -35,40 +36,42 @@ impl RValue<u16> for u16 {
|
|||||||
|
|
||||||
pub struct Addr<'a> {
|
pub struct Addr<'a> {
|
||||||
pub bus: &'a mut Bus,
|
pub bus: &'a mut Bus,
|
||||||
pub addr: usize
|
pub segment: u16,
|
||||||
|
pub offset: u16
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Address for Addr<'_> {
|
impl Address for Addr<'_> {
|
||||||
fn addr(&self) -> usize {
|
fn addr(&self) -> usize {
|
||||||
self.addr
|
segoff_to_addr(self.segment, self.offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LValue<u8> for Addr<'_> {
|
impl LValue<u8> for Addr<'_> {
|
||||||
fn write(&mut self, val: u8) {
|
fn write(&mut self, val: u8) {
|
||||||
self.bus.write(self.addr, val);
|
self.bus.write(self.addr(), val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RValue<u8> for Addr<'_> {
|
impl RValue<u8> for Addr<'_> {
|
||||||
fn read(&self) -> u8 {
|
fn read(&self) -> u8 {
|
||||||
self.bus.read(self.addr)
|
self.bus.read(self.addr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LValue<u16> for Addr<'_> {
|
impl LValue<u16> for Addr<'_> {
|
||||||
fn write(&mut self, val: u16) {
|
fn write(&mut self, val: u16) {
|
||||||
let buf = val.to_le_bytes();
|
let buf = val.to_le_bytes();
|
||||||
self.bus.write(self.addr, buf[0]);
|
self.bus.write(self.addr(), buf[0]);
|
||||||
self.bus.write(self.addr + 1, buf[1]);
|
self.bus.write(self.addr() + 1, buf[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RValue<u16> for Addr<'_> {
|
impl RValue<u16> for Addr<'_> {
|
||||||
fn read(&self) -> u16 {
|
fn read(&self) -> u16 {
|
||||||
|
let addr = self.addr();
|
||||||
let mut buf = [0u8; 2];
|
let mut buf = [0u8; 2];
|
||||||
buf[0] = self.bus.read(self.addr);
|
buf[0] = self.bus.read(addr);
|
||||||
buf[1] = self.bus.read(self.addr + 1);
|
buf[1] = self.bus.read(addr + 1);
|
||||||
u16::from_le_bytes(buf)
|
u16::from_le_bytes(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use emu::byteorder::{ByteOrder, LittleEndian};
|
use emu::byteorder::{ByteOrder, LittleEndian};
|
||||||
use emu::dos;
|
use emu::dos;
|
||||||
use emu::i8088::i8088;
|
use emu::i8088::i8088;
|
||||||
use emu::operands::{Address, LValue, Reg, RValue};
|
use emu::operands::{Addr, Address, LValue, Reg, RValue};
|
||||||
use emu::pc::Bus;
|
use emu::pc::Bus;
|
||||||
use emu::util::segoff_to_addr;
|
use emu::util::segoff_to_addr;
|
||||||
|
|
||||||
@@ -26,6 +26,10 @@ pub fn int(cpu: &mut i8088, bus: &mut Bus, num: &u8) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn lea(dst: &mut Reg, addr: &Addr) {
|
||||||
|
dst.write(addr.offset)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mov<T>(dst: &mut impl LValue<T>, src: &impl RValue<T>) {
|
pub fn mov<T>(dst: &mut impl LValue<T>, src: &impl RValue<T>) {
|
||||||
dst.write(src.read());
|
dst.write(src.read());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user