From 3b746b75ec0d832c183d06cdff3150d42a0d7d3a Mon Sep 17 00:00:00 2001 From: Jared Burce Date: Thu, 18 Mar 2021 00:32:08 -0700 Subject: [PATCH] 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. --- src/emu/i8088.rs | 27 +++++++++++++++++++++++++-- src/emu/operations.rs | 22 ++++++++-------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index a28d562..12276a6 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -352,6 +352,13 @@ impl i8088 { loop { step!((self, bus) => opcodes: { + 0x06 => push[bus, regval=ss, reg=sp, regval=es] / 14, + 0x07 => pop[bus, regval=ss, reg=sp, reg=es] / 12, + 0x0E => push[bus, regval=ss, reg=sp, regval=cs] / 14, + 0x16 => push[bus, regval=ss, reg=sp, regval=ss] / 14, + 0x17 => pop[bus, regval=ss, reg=sp, reg=ss] / 12, + 0x1E => push[bus, regval=ss, reg=sp, regval=ds] / 14, + 0x1F => pop[bus, regval=ss, reg=sp, reg=ds] / 12, 0x26 => nop[seg=es, prefix] / 2, 0x2E => nop[seg=cs, prefix] / 2, 0x36 => nop[seg=ss, prefix] / 2, @@ -362,6 +369,22 @@ impl i8088 { 0x3C => cmp[flags, reglo=a, d8] / "3/24+", 0x3D => cmp[flags, reg=a, d16] / "3/24+", 0x3E => nop[seg=ds, prefix] / 2, + 0x50 => push[bus, regval=ss, reg=sp, regval=a] / 15, + 0x51 => push[bus, regval=ss, reg=sp, regval=c] / 15, + 0x52 => push[bus, regval=ss, reg=sp, regval=d] / 15, + 0x53 => push[bus, regval=ss, reg=sp, regval=b] / 15, + 0x54 => push[bus, regval=ss, reg=sp, regval=sp] / 15, + 0x55 => push[bus, regval=ss, reg=sp, regval=bp] / 15, + 0x56 => push[bus, regval=ss, reg=sp, regval=si] / 15, + 0x57 => push[bus, regval=ss, reg=sp, regval=di] / 15, + 0x58 => pop[bus, regval=ss, reg=sp, reg=a] / 12, + 0x59 => pop[bus, regval=ss, reg=sp, reg=c] / 12, + 0x5A => pop[bus, regval=ss, reg=sp, reg=d] / 12, + 0x5B => pop[bus, regval=ss, reg=sp, reg=b] / 12, + 0x5C => pop[bus, regval=ss, reg=sp, reg=sp] / 12, + 0x5D => pop[bus, regval=ss, reg=sp, reg=bp] / 12, + 0x5E => pop[bus, regval=ss, reg=sp, reg=si] / 12, + 0x5F => pop[bus, regval=ss, reg=sp, reg=di] / 12, 0x60 => show[cpu] / 0, // Fake opcode for debugging 0x61 => peek[seg=ds, addr] / 0, // Fake opcode for debugging 0x62 _ => assert[modrm8, d8] / 0, // Fake opcode for debugging @@ -413,9 +436,9 @@ impl i8088 { 0xBD => mov[reg=bp, d16] / 4, 0xBE => mov[reg=si, d16] / 4, 0xBF => mov[reg=di, d16] / 4, - 0xC3 => ret[reg=ip, regval=ss, reg=sp, mem] / 20, + 0xC3 => pop[bus, regval=ss, reg=sp, reg=ip] / 20, // RET 0xCD => int[cpu, bus, d8] / 71, - 0xE8 => call[reg=ip, regval=ss, reg=sp, mem, rel16] / 23, + 0xE8 => call[reg=ip, bus, regval=ss, reg=sp, rel16] / 23, 0xF2 => nop[rep=NotEqual, prefix] / 0, // REPNE/REPNZ 0xF3 => nop[rep=Equal, prefix] / 0, // REP/REPE/REPZ }, diff --git a/src/emu/operations.rs b/src/emu/operations.rs index 604465f..ae01807 100644 --- a/src/emu/operations.rs +++ b/src/emu/operations.rs @@ -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)) { 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,