emu: PUSH/POP opcodes, reimpl RET as just "POP IP"

This also promotes CALL/RET to actually using the bus for
addressing (because it goes through the generic PUSH/POP code), which
is probably more correct anyway.
This commit is contained in:
2021-03-18 00:32:08 -07:00
parent dcf96ec5b3
commit 3b746b75ec
2 changed files with 33 additions and 16 deletions

View File

@@ -1,12 +1,9 @@
use std::fmt::Debug;
use emu::byteorder::{ByteOrder, LittleEndian};
use emu::dos;
use emu::i8088::{Flags, RepPrefix, i8088};
use emu::operands::{Addr, Address, LValue, Operand, Reg, RValue};
use emu::pc::Bus;
use emu::util::segoff_to_addr;
macro_rules! string_op {
( ($type:ty,
@@ -92,9 +89,9 @@ pub fn peek(addr: &(impl Address + RValue<u8>)) {
println!("PEEK: @{:#X} = {:#X} ({})", addr.addr(), addr.read(), addr.read());
}
pub fn call(ip: &mut Reg, ss: u16, sp: &mut Reg, mem: &mut [u8], addr: i16) {
pub fn call(ip: &mut Reg, bus: &mut Bus, ss: u16, sp: &mut Reg, addr: i16) {
let target = ip.read().wrapping_add(addr as u16);
push16(ss, sp, mem, ip.read());
push(bus, ss, sp, ip.read());
ip.write(target);
}
@@ -209,20 +206,17 @@ pub fn movsw(flags: &Flags,
pub fn nop() {}
pub fn pop16(ss: u16, sp: &mut Reg, mem: &[u8]) -> u16 {
let val = LittleEndian::read_u16(&mem[segoff_to_addr(ss.read(), sp.read())..]);
pub fn pop(bus: &mut Bus, ss: u16, sp: &mut Reg, dst: &mut Reg) {
let ptr = Addr { bus: bus, segment: ss, offset: sp.read() };
dst.write(ptr.read());
sp.write(sp.read() + 2);
val
}
pub fn push16(ss: u16, sp: &mut Reg, mem: &mut [u8], val: u16) {
pub fn push(bus: &mut Bus, ss: u16, sp: &mut Reg, val: u16) {
// XXX: Not checking for stack faults or anything
sp.write(sp.read() - 2);
LittleEndian::write_u16(&mut mem[segoff_to_addr(ss.read(), sp.read())..], val);
}
pub fn ret(ip: &mut Reg, ss: u16, sp: &mut Reg, mem: &[u8]) {
ip.write(pop16(ss, sp, mem));
let mut ptr = Addr { bus: bus, segment: ss, offset: sp.read() };
ptr.write(val);
}
pub fn scasb(flags: &mut Flags,