From c8d6a3312a40bfbea697894b1758c60f7342e2e5 Mon Sep 17 00:00:00 2001 From: Jared Burce Date: Thu, 18 Mar 2021 02:09:46 -0700 Subject: [PATCH] emu: near/short JUMP instructions. Use u16+wrapping_add for all rels --- src/emu/i8088.rs | 26 +++++++++++- src/emu/operations.rs | 98 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 121 insertions(+), 3 deletions(-) diff --git a/src/emu/i8088.rs b/src/emu/i8088.rs index d208b68..3f1b8b4 100644 --- a/src/emu/i8088.rs +++ b/src/emu/i8088.rs @@ -253,11 +253,16 @@ macro_rules! step { step!(@arg $cookie, $cpu.$reg.get()); }; + (@rel8 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { { + let rel8 = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus) as i8; + step!(@arg $cookie, rel8 as u16) + } }; + (@rel16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { { let mut buf = [0; 2]; buf[0] = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus); buf[1] = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus); - step!(@arg $cookie, LittleEndian::read_i16(&buf)) + step!(@arg $cookie, LittleEndian::read_i16(&buf) as u16) } }; (@rep $cookie:tt, $cpu:expr, $bus:expr, @@ -393,6 +398,22 @@ impl i8088 { 0x61 => peek[seg=ds, addr] / 0, // Fake opcode for debugging 0x62 _ => assert[modrm8, d8] / 0, // Fake opcode for debugging 0x63 _ => assert[modrm16, d16] / 0, // Fake opcode for debugging + 0x70 => jo[flags, reg=ip, rel8] / "16/4", // JO rel8 + 0x71 => jno[flags, reg=ip, rel8] / "16/4", // JNO rel8 + 0x72 => jb[flags, reg=ip, rel8] / "16/4", // JB/JNAE/JC rel8 + 0x73 => jae[flags, reg=ip, rel8] / "16/4", // JNB/JAE/JNC rel8 + 0x74 => jz[flags, reg=ip, rel8] / "16/4", // JE/JZ rel8 + 0x75 => jnz[flags, reg=ip, rel8] / "16/4", // JNE/JNZ rel8 + 0x76 => jbe[flags, reg=ip, rel8] / "16/4", // JBE/JNA rel8 + 0x77 => ja[flags, reg=ip, rel8] / "16/4", // JNBE/JA rel8 + 0x78 => js[flags, reg=ip, rel8] / "16/4", // JS rel8 + 0x79 => jns[flags, reg=ip, rel8] / "16/4", // JNS rel8 + //0x7A => jpe[flags, reg=ip, rel8] / "16/4", // JP/JPE rel8 XXX: Parity flag not implemented + //0x7B => jpo[flags, reg=ip, rel8] / "16/4", // JNP/JPO rel8 XXX: Parity flag not implemented + 0x7C => jl[flags, reg=ip, rel8] / "16/4", // JL/JNGE rel8 + 0x7D => jge[flags, reg=ip, rel8] / "16/4", // JNL/JGE rel8 + 0x7E => jle[flags, reg=ip, rel8] / "16/4", // JLE/JNG rel8 + 0x7F => jg[flags, reg=ip, rel8] / "16/4", // JNLE/JG rel8 0x80: { 0x38 => cmp[flags, modrm8, d8] / "4/23+", }, 0x81: { 0x38 => cmp[flags, modrm16, d16] / "4/23+", }, 0x83: { 0x38 => cmp[flags, modrm16, d8_as_d16] / "4/23+", }, @@ -442,6 +463,9 @@ impl i8088 { 0xBF => mov[reg=di, d16] / 4, 0xC3 => pop[bus, regval=ss, reg=sp, reg=ip] / 20, // RET 0xCD => int[cpu, bus, d8] / 71, + 0xE3 => jcxz[reg=ip, reg=c, rel8] / "18/6", // JCXZ rel8 + 0xE9 => jmp[reg=ip, rel16] / 15, // JMP rel16 + 0xEB => jmp[reg=ip, rel8] / 15, // JMP rel8 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 02a95df..9dba65a 100644 --- a/src/emu/operations.rs +++ b/src/emu/operations.rs @@ -89,8 +89,8 @@ pub fn peek(addr: &(impl Address + RValue)) { println!("PEEK: @{:#X} = {:#X} ({})", addr.addr(), addr.read(), addr.read()); } -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); +pub fn call(ip: &mut Reg, bus: &mut Bus, ss: u16, sp: &mut Reg, rel16: u16) { + let target = ip.read().wrapping_add(rel16); push(bus, ss, sp, ip.read()); ip.write(target); } @@ -142,6 +142,100 @@ pub fn int(cpu: &mut i8088, bus: &mut Bus, num: &u8) { } } +pub fn ja(flags: &Flags, ip: &mut Reg, rel8: u16) { + if !flags.cf && !flags.zf { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jae(flags: &Flags, ip: &mut Reg, rel8: u16) { + if !flags.cf { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jb(flags: &Flags, ip: &mut Reg, rel8: u16) { + if flags.cf { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jbe(flags: &Flags, ip: &mut Reg, rel8: u16) { + if flags.cf || flags.zf { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jcxz(ip: &mut Reg, cx: &mut Reg, rel8: u16) { + if cx.read() == 0 { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jg(flags: &Flags, ip: &mut Reg, rel8: u16) { + if flags.zf && flags.sf == flags.of { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jge(flags: &Flags, ip: &mut Reg, rel8: u16) { + if flags.sf == flags.of { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jl(flags: &Flags, ip: &mut Reg, rel8: u16) { + if flags.sf != flags.of { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jle(flags: &Flags, ip: &mut Reg, rel8: u16) { + if flags.zf || flags.sf != flags.of { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jmp(ip: &mut Reg, rel: u16) { + ip.write(ip.read().wrapping_add(rel)); +} + +pub fn jno(flags: &Flags, ip: &mut Reg, rel8: u16) { + if !flags.of { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jns(flags: &Flags, ip: &mut Reg, rel8: u16) { + if !flags.sf { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jnz(flags: &Flags, ip: &mut Reg, rel8: u16) { + if !flags.zf { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jo(flags: &Flags, ip: &mut Reg, rel8: u16) { + if flags.of { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn js(flags: &Flags, ip: &mut Reg, rel8: u16) { + if flags.sf { + ip.write(ip.read().wrapping_add(rel8)); + } +} + +pub fn jz(flags: &Flags, ip: &mut Reg, rel8: u16) { + if flags.zf { + ip.write(ip.read().wrapping_add(rel8)); + } +} + pub fn lea(dst: &mut Reg, addr: &FarPtr) { dst.write(addr.offset) }