emu: near/short JUMP instructions. Use u16+wrapping_add for all rels
This commit is contained in:
@@ -253,11 +253,16 @@ macro_rules! step {
|
|||||||
step!(@arg $cookie, $cpu.$reg.get());
|
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) => { {
|
(@rel16 $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => { {
|
||||||
let mut buf = [0; 2];
|
let mut buf = [0; 2];
|
||||||
buf[0] = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus);
|
buf[0] = i8088::next_ip($cpu.cs.get(), &mut $cpu.ip, $bus);
|
||||||
buf[1] = 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,
|
(@rep $cookie:tt, $cpu:expr, $bus:expr,
|
||||||
@@ -393,6 +398,22 @@ impl i8088 {
|
|||||||
0x61 => peek[seg=ds, addr] / 0, // Fake opcode for debugging
|
0x61 => peek[seg=ds, addr] / 0, // Fake opcode for debugging
|
||||||
0x62 _ => assert[modrm8, d8] / 0, // Fake opcode for debugging
|
0x62 _ => assert[modrm8, d8] / 0, // Fake opcode for debugging
|
||||||
0x63 _ => assert[modrm16, d16] / 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+", },
|
0x80: { 0x38 => cmp[flags, modrm8, d8] / "4/23+", },
|
||||||
0x81: { 0x38 => cmp[flags, modrm16, d16] / "4/23+", },
|
0x81: { 0x38 => cmp[flags, modrm16, d16] / "4/23+", },
|
||||||
0x83: { 0x38 => cmp[flags, modrm16, d8_as_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,
|
0xBF => mov[reg=di, d16] / 4,
|
||||||
0xC3 => pop[bus, regval=ss, reg=sp, reg=ip] / 20, // RET
|
0xC3 => pop[bus, regval=ss, reg=sp, reg=ip] / 20, // RET
|
||||||
0xCD => int[cpu, bus, d8] / 71,
|
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,
|
0xE8 => call[reg=ip, bus, regval=ss, reg=sp, rel16] / 23,
|
||||||
0xF2 => nop[rep=NotEqual, prefix] / 0, // REPNE/REPNZ
|
0xF2 => nop[rep=NotEqual, prefix] / 0, // REPNE/REPNZ
|
||||||
0xF3 => nop[rep=Equal, prefix] / 0, // REP/REPE/REPZ
|
0xF3 => nop[rep=Equal, prefix] / 0, // REP/REPE/REPZ
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ pub fn peek(addr: &(impl Address + RValue<u8>)) {
|
|||||||
println!("PEEK: @{:#X} = {:#X} ({})", addr.addr(), addr.read(), addr.read());
|
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) {
|
pub fn call(ip: &mut Reg, bus: &mut Bus, ss: u16, sp: &mut Reg, rel16: u16) {
|
||||||
let target = ip.read().wrapping_add(addr as u16);
|
let target = ip.read().wrapping_add(rel16);
|
||||||
push(bus, ss, sp, ip.read());
|
push(bus, ss, sp, ip.read());
|
||||||
ip.write(target);
|
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) {
|
pub fn lea(dst: &mut Reg, addr: &FarPtr) {
|
||||||
dst.write(addr.offset)
|
dst.write(addr.offset)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user