emu: Make flags lazy, implement parity flag & JPE/JPO ops
This commit is contained in:
138
src/emu/flags.rs
138
src/emu/flags.rs
@@ -1,34 +1,118 @@
|
|||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
|
use emu::operands::OperandWidth;
|
||||||
|
|
||||||
|
const CF_BIT: u8 = 0; // Carry Flag
|
||||||
|
const PF_BIT: u8 = 2; // Parity Flag
|
||||||
|
const AF_BIT: u8 = 4; // Adjust Flag
|
||||||
|
const ZF_BIT: u8 = 6; // Zero Flag
|
||||||
|
const SF_BIT: u8 = 7; // Sign Flag
|
||||||
|
const TF_BIT: u8 = 8; // Trap Flag
|
||||||
|
const IF_BIT: u8 = 9; // Interrupt Enable
|
||||||
|
const DF_BIT: u8 = 10; // Direction Flag
|
||||||
|
const OF_BIT: u8 = 11; // Overflow Flag
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub struct Flags {
|
pub struct Flags {
|
||||||
pub cf: bool, // 0: Carry Flag: 1=CY(Carry), 0=NC(No Carry)
|
pub cf: bool, // 0: Carry Flag: 1=CY(Carry), 0=NC(No Carry)
|
||||||
// 1: Reserved
|
// 1: Reserved
|
||||||
pub pf: bool, // 2: Parity Flag: 1=PE(Even), 0=PO(Odd)
|
// 2: LAZY Parity Flag: 1=PE(Even), 0=PO(Odd)
|
||||||
// 3: Reserved
|
// 3: Reserved
|
||||||
pub af: bool, // 4: Adjust Flag: 1=AC(Aux Carry), 0=NA(No Aux Carry)
|
// 4: LAZY Adjust Flag: 1=AC(Aux Carry), 0=NA(No Aux Carry)
|
||||||
// 5: Reserved
|
// 5: Reserved
|
||||||
pub zf: bool, // 6: Zero Flag: 1=ZR(Zero), 0=NZ(Not Zero)
|
// 6: LAZY Zero Flag: 1=ZR(Zero), 0=NZ(Not Zero)
|
||||||
pub sf: bool, // 7: Sign Flag: 1=NG(Negative), 0=PL(Positive)
|
// 7: LAZY Sign Flag: 1=NG(Negative), 0=PL(Positive)
|
||||||
pub tf: bool, // 8: Trap Flag
|
pub tf: bool, // 8: Trap Flag
|
||||||
pub ie: bool, // 9: (Real name "IF") Interrupt Enable: 1=EI(Enable Interrupt), 0=DI(Disable Interrupt)
|
pub ie: bool, // 9: (Real name "IF") Interrupt Enable: 1=EI(Enable Interrupt), 0=DI(Disable Interrupt)
|
||||||
pub df: bool, // 10: Direction Flag: 1=DN(Down), 0=UP(Up)
|
pub df: bool, // 10: Direction Flag: 1=DN(Down), 0=UP(Up)
|
||||||
pub of: bool, // 11: Overflow Flag: 1=OV(Overflow), 0=NV(Not Overflow)
|
// 11: LAZY Overflow Flag: 1=OV(Overflow), 0=NV(Not Overflow)
|
||||||
// bits 12-15 always 1
|
// bits 12-15 always 1
|
||||||
|
|
||||||
|
// ALU state for lazy flag evaluation
|
||||||
|
flag_op: FlagOp,
|
||||||
|
dst: u16,
|
||||||
|
src: u16,
|
||||||
|
res: u16,
|
||||||
|
sign_bit_mask: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Flags {
|
||||||
|
pub fn pf(&self) -> bool {
|
||||||
|
match self.flag_op {
|
||||||
|
FlagOp::Eager => { self.res & 1 << PF_BIT != 0 },
|
||||||
|
_ => { self.res.count_ones() & 1 == 0 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn af(&self) -> bool {
|
||||||
|
match self.flag_op {
|
||||||
|
FlagOp::Eager => { self.res & 1 << AF_BIT != 0 },
|
||||||
|
_ => { false /* XXX: unimplemented! */ },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zf(&self) -> bool {
|
||||||
|
match self.flag_op {
|
||||||
|
FlagOp::Eager => { self.res & 1 << ZF_BIT != 0 },
|
||||||
|
_ => { self.res == 0 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sf(&self) -> bool {
|
||||||
|
match self.flag_op {
|
||||||
|
FlagOp::Eager => { self.res & 1 << SF_BIT != 0 },
|
||||||
|
_ => { self.res & self.sign_bit_mask != 0 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn of(&self) -> bool {
|
||||||
|
match self.flag_op {
|
||||||
|
FlagOp::Eager => { self.res & 1 << OF_BIT != 0 },
|
||||||
|
FlagOp::DEC => { self.res == self.sign_bit_mask - 1 },
|
||||||
|
FlagOp::INC => { self.res == self.sign_bit_mask },
|
||||||
|
FlagOp::SUB => { 0 != self.sign_bit_mask & // In the (maybe) sign bit...
|
||||||
|
(self.src ^ self.dst) & // ...operands have different signs...
|
||||||
|
(self.dst ^ self.res) /* ...and result sign-bit changed */ },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, op: FlagOp, dst: u16, src: u16, res: u16, op_width: OperandWidth) {
|
||||||
|
self.flag_op = op;
|
||||||
|
self.dst = dst;
|
||||||
|
self.src = src;
|
||||||
|
self.res = res;
|
||||||
|
self.sign_bit_mask = match op_width {
|
||||||
|
OperandWidth::Byte => 0x80,
|
||||||
|
OperandWidth::Word => 0x8000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum FlagOp {
|
||||||
|
Eager, // precomputed into result, for e.g. POPF? (Anything else?)
|
||||||
|
DEC,
|
||||||
|
INC,
|
||||||
|
SUB,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FlagOp {
|
||||||
|
fn default() -> Self { FlagOp::Eager }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u16> for Flags {
|
impl From<u16> for Flags {
|
||||||
fn from(flags: u16) -> Self {
|
fn from(flags: u16) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cf: flags & 1 != 0,
|
cf: flags & 1 << CF_BIT != 0,
|
||||||
pf: flags & 1 << 2 != 0,
|
tf: flags & 1 << TF_BIT != 0,
|
||||||
af: flags & 1 << 4 != 0,
|
ie: flags & 1 << IF_BIT != 0,
|
||||||
zf: flags & 1 << 6 != 0,
|
df: flags & 1 << DF_BIT != 0,
|
||||||
sf: flags & 1 << 7 != 0,
|
|
||||||
tf: flags & 1 << 8 != 0,
|
flag_op: FlagOp::Eager,
|
||||||
ie: flags & 1 << 9 != 0,
|
dst: 0,
|
||||||
df: flags & 1 << 10 != 0,
|
src: 0,
|
||||||
of: flags & 1 << 11 != 0,
|
res: flags,
|
||||||
|
sign_bit_mask: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,14 +121,14 @@ impl From<Flags> for u16 {
|
|||||||
fn from(flags: Flags) -> Self {
|
fn from(flags: Flags) -> Self {
|
||||||
0b1111_0000_0010_1010 // Not sure what all reserved bits should be, but it shouldn't matter
|
0b1111_0000_0010_1010 // Not sure what all reserved bits should be, but it shouldn't matter
|
||||||
| (flags.cf as u16)
|
| (flags.cf as u16)
|
||||||
| (flags.pf as u16) << 2
|
| (flags.pf() as u16) << PF_BIT
|
||||||
| (flags.af as u16) << 4
|
| (flags.af() as u16) << AF_BIT
|
||||||
| (flags.zf as u16) << 6
|
| (flags.zf() as u16) << ZF_BIT
|
||||||
| (flags.sf as u16) << 7
|
| (flags.sf() as u16) << SF_BIT
|
||||||
| (flags.tf as u16) << 8
|
| (flags.tf as u16) << TF_BIT
|
||||||
| (flags.ie as u16) << 9
|
| (flags.ie as u16) << IF_BIT
|
||||||
| (flags.df as u16) << 10
|
| (flags.df as u16) << DF_BIT
|
||||||
| (flags.of as u16) << 11
|
| (flags.of() as u16) << OF_BIT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,14 +137,14 @@ impl Debug for Flags {
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
fmt.write_str("[ ")?;
|
fmt.write_str("[ ")?;
|
||||||
for flag in [ (self.cf, "CF "),
|
for flag in [ (self.cf, "CF "),
|
||||||
(self.pf, "PF "),
|
(self.pf(), "PF "),
|
||||||
(self.af, "AF "),
|
(self.af(), "AF "),
|
||||||
(self.zf, "ZF "),
|
(self.zf(), "ZF "),
|
||||||
(self.sf, "SF "),
|
(self.sf(), "SF "),
|
||||||
(self.tf, "TF "),
|
(self.tf, "TF "),
|
||||||
(self.ie, "IF "),
|
(self.ie, "IF "),
|
||||||
(self.df, "DF "),
|
(self.df, "DF "),
|
||||||
(self.of, "OF ") ].iter() {
|
(self.of(), "OF ") ].iter() {
|
||||||
if flag.0 { fmt.write_str(flag.1)? };
|
if flag.0 { fmt.write_str(flag.1)? };
|
||||||
}
|
}
|
||||||
fmt.write_char(']')?;
|
fmt.write_char(']')?;
|
||||||
|
|||||||
@@ -456,8 +456,8 @@ impl i8088 {
|
|||||||
0x77 => ja[flags, reg=ip, rel8] / "16/4", // JNBE/JA rel8
|
0x77 => ja[flags, reg=ip, rel8] / "16/4", // JNBE/JA rel8
|
||||||
0x78 => js[flags, reg=ip, rel8] / "16/4", // JS rel8
|
0x78 => js[flags, reg=ip, rel8] / "16/4", // JS rel8
|
||||||
0x79 => jns[flags, reg=ip, rel8] / "16/4", // JNS 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
|
0x7A => jpe[flags, reg=ip, rel8] / "16/4", // JP/JPE rel8
|
||||||
//0x7B => jpo[flags, reg=ip, rel8] / "16/4", // JNP/JPO rel8 XXX: Parity flag not implemented
|
0x7B => jpo[flags, reg=ip, rel8] / "16/4", // JNP/JPO rel8
|
||||||
0x7C => jl[flags, reg=ip, rel8] / "16/4", // JL/JNGE rel8
|
0x7C => jl[flags, reg=ip, rel8] / "16/4", // JL/JNGE rel8
|
||||||
0x7D => jge[flags, reg=ip, rel8] / "16/4", // JNL/JGE rel8
|
0x7D => jge[flags, reg=ip, rel8] / "16/4", // JNL/JGE rel8
|
||||||
0x7E => jle[flags, reg=ip, rel8] / "16/4", // JLE/JNG rel8
|
0x7E => jle[flags, reg=ip, rel8] / "16/4", // JLE/JNG rel8
|
||||||
|
|||||||
@@ -7,27 +7,28 @@ use emu::util::{read_hi, read_lo, segoff_to_addr, write_hi, write_lo};
|
|||||||
use emu::pc::Bus;
|
use emu::pc::Bus;
|
||||||
|
|
||||||
pub trait Operand: Copy +
|
pub trait Operand: Copy +
|
||||||
|
std::convert::Into<u16> +
|
||||||
nt::Num +
|
nt::Num +
|
||||||
nt::ops::overflowing::OverflowingAdd +
|
nt::ops::overflowing::OverflowingAdd +
|
||||||
nt::ops::overflowing::OverflowingSub +
|
nt::ops::overflowing::OverflowingSub +
|
||||||
|
nt::ops::wrapping::WrappingAdd +
|
||||||
|
nt::ops::wrapping::WrappingSub +
|
||||||
std::ops::BitAnd<Output = Self> +
|
std::ops::BitAnd<Output = Self> +
|
||||||
std::ops::BitXor<Output = Self> {
|
std::ops::BitXor<Output = Self> {
|
||||||
const HI_BIT_MASK: Self;
|
const WIDTH: OperandWidth;
|
||||||
fn hi_bit(&self) -> bool;
|
}
|
||||||
|
|
||||||
|
pub enum OperandWidth {
|
||||||
|
Byte,
|
||||||
|
Word
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Operand for u8 {
|
impl Operand for u8 {
|
||||||
const HI_BIT_MASK: u8 = 0x80;
|
const WIDTH: OperandWidth = OperandWidth::Byte;
|
||||||
fn hi_bit(&self) -> bool {
|
|
||||||
self >> 7 == 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Operand for u16 {
|
impl Operand for u16 {
|
||||||
const HI_BIT_MASK: u16 = 0x8000;
|
const WIDTH: OperandWidth = OperandWidth::Word;
|
||||||
fn hi_bit(&self) -> bool {
|
|
||||||
self >> 15 == 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait LValue<T>: RValue<T> {
|
pub trait LValue<T>: RValue<T> {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::convert::Into;
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use emu::dos;
|
use emu::dos;
|
||||||
use emu::flags::Flags;
|
use emu::flags::{FlagOp, Flags};
|
||||||
use emu::i8088::{RepPrefix, i8088};
|
use emu::i8088::{RepPrefix, i8088};
|
||||||
use emu::operands::{Address, DynLValue, FarPtr, LValue, Operand, Reg, RValue};
|
use emu::operands::{Address, DynLValue, FarPtr, LValue, Operand, Reg, RValue};
|
||||||
use emu::pc::Bus;
|
use emu::pc::Bus;
|
||||||
@@ -50,33 +50,6 @@ macro_rules! string_op {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on SUB/CMP, others will vary!
|
|
||||||
// Decide if this can realistically be generalized
|
|
||||||
macro_rules! update_flags {
|
|
||||||
// Base Case
|
|
||||||
(@recur $flags:expr, $t:ty, $dst:ident, $carry:ident) => {};
|
|
||||||
|
|
||||||
(@af $flags:expr, $t:ty, $dst:ident, $carry:ident) => { /* XXX: Adjust/AuxCarry esoteric? (mostly for BCD?), might not need */ };
|
|
||||||
(@cf $flags:expr, $t:ty, $dst:ident, $carry:ident) => { $flags.cf = $carry };
|
|
||||||
(@of $flags:expr, $t:ty, $dst:ident, $carry:ident) => { compile_error!("compute flags.of outside macro"); };
|
|
||||||
(@pf $flags:expr, $t:ty, $dst:ident, $carry:ident) => { /* XXX: parity looks esoteric, might not need */ };
|
|
||||||
(@sf $flags:expr, $t:ty, $dst:ident, $carry:ident) => { $flags.sf = $dst.hi_bit(); };
|
|
||||||
(@zf $flags:expr, $t:ty, $dst:ident, $carry:ident) => { $flags.zf = $dst == <$t>::zero(); };
|
|
||||||
|
|
||||||
// Recursive step
|
|
||||||
(@recur $flags:expr, $t:ty, $dst:ident, $carry:ident, $next:ident $(, $rest:ident)* ) => {
|
|
||||||
update_flags!(@$next $flags, $t, $dst, $carry);
|
|
||||||
update_flags!(@recur $flags, $t, $dst, $carry $(, $rest)*);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Entry Point
|
|
||||||
($flags:expr, $t:ty, $eval:expr $(, $flagnames:ident)* ) => { {
|
|
||||||
let (dst, _carry) = $eval; // _carry used iff CF flag being updated
|
|
||||||
update_flags!(@recur $flags, $t, dst, _carry $(, $flagnames)*);
|
|
||||||
dst
|
|
||||||
} }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn assert<T: Operand + Debug>(loc: impl RValue<T>, val: impl RValue<T>) {
|
pub fn assert<T: Operand + Debug>(loc: impl RValue<T>, val: impl RValue<T>) {
|
||||||
assert_eq!(loc.read(), val.read(),
|
assert_eq!(loc.read(), val.read(),
|
||||||
"ASSERT instruction failed: {:#2X?} != {:#2X?}", loc.read(), val.read());
|
"ASSERT instruction failed: {:#2X?} != {:#2X?}", loc.read(), val.read());
|
||||||
@@ -99,10 +72,9 @@ pub fn call(mut ip: Reg, bus: &mut Bus, ss: u16, sp: Reg, rel16: u16) {
|
|||||||
|
|
||||||
pub fn cmp<T: Operand>(flags: &mut Flags, dst: impl RValue<T>, src: impl RValue<T>) {
|
pub fn cmp<T: Operand>(flags: &mut Flags, dst: impl RValue<T>, src: impl RValue<T>) {
|
||||||
let (dst, src) = (dst.read(), src.read());
|
let (dst, src) = (dst.read(), src.read());
|
||||||
let after = update_flags!(flags, T, dst.overflowing_sub(&src), af, cf, pf, sf, zf);
|
let (res, carry) = dst.overflowing_sub(&src);
|
||||||
flags.of = T::zero() != T::HI_BIT_MASK & // In the (maybe) sign bit...
|
flags.cf = carry;
|
||||||
(src ^ dst) & // ...operands have different signs...
|
flags.update(FlagOp::SUB, dst.into(), src.into(), res.into(), T::WIDTH);
|
||||||
(dst ^ after); // ...and destination sign-bit changed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cmpsb(flags: &mut Flags,
|
pub fn cmpsb(flags: &mut Flags,
|
||||||
@@ -113,7 +85,7 @@ pub fn cmpsb(flags: &mut Flags,
|
|||||||
mut si: Reg,
|
mut si: Reg,
|
||||||
es: Reg,
|
es: Reg,
|
||||||
mut di: Reg) {
|
mut di: Reg) {
|
||||||
string_op!((u8, flags, rep, cx, si=si, di=di, zf=flags.zf), {
|
string_op!((u8, flags, rep, cx, si=si, di=di, zf=flags.zf()), {
|
||||||
let src = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
let src = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
||||||
let dst = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
let dst = <FarPtr as RValue<u8>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
||||||
|
|
||||||
@@ -129,7 +101,7 @@ pub fn cmpsw(flags: &mut Flags,
|
|||||||
mut si: Reg,
|
mut si: Reg,
|
||||||
es: Reg,
|
es: Reg,
|
||||||
mut di: Reg) {
|
mut di: Reg) {
|
||||||
string_op!((u16, flags, rep, cx, si=si, di=di, zf=flags.zf), {
|
string_op!((u16, flags, rep, cx, si=si, di=di, zf=flags.zf()), {
|
||||||
let src = <FarPtr as RValue<u16>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
let src = <FarPtr as RValue<u16>>::read(&FarPtr { bus: bus, segment: seg, offset: si.read() });
|
||||||
let dst = <FarPtr as RValue<u16>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
let dst = <FarPtr as RValue<u16>>::read(&FarPtr { bus: bus, segment: es.read(), offset: di.read() });
|
||||||
|
|
||||||
@@ -138,15 +110,17 @@ pub fn cmpsw(flags: &mut Flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn dec<T: Operand, LVal: LValue<T>>(flags: &mut Flags, mut dst: LVal) {
|
pub fn dec<T: Operand, LVal: LValue<T>>(flags: &mut Flags, mut dst: LVal) {
|
||||||
let res = update_flags!(flags, T, dst.read().overflowing_sub(&T::one()), sf, zf, af, pf);
|
let dst_before = dst.read();
|
||||||
flags.of = res == T::HI_BIT_MASK - T::one();
|
let res = dst_before.wrapping_sub(&T::one());
|
||||||
dst.write(res);
|
dst.write(res);
|
||||||
|
flags.update(FlagOp::DEC, dst_before.into(), 0, res.into(), T::WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inc<T: Operand, LVal: LValue<T>>(flags: &mut Flags, mut dst: LVal) {
|
pub fn inc<T: Operand, LVal: LValue<T>>(flags: &mut Flags, mut dst: LVal) {
|
||||||
let res = update_flags!(flags, T, dst.read().overflowing_add(&T::one()), sf, zf, af, pf);
|
let dst_before = dst.read();
|
||||||
flags.of = res == T::HI_BIT_MASK;
|
let res = dst_before.wrapping_add(&T::one());
|
||||||
dst.write(res);
|
dst.write(res);
|
||||||
|
flags.update(FlagOp::INC, dst_before.into(), 0, res.into(), T::WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn int(cpu: &mut i8088, bus: &mut Bus, num: u8) {
|
pub fn int(cpu: &mut i8088, bus: &mut Bus, num: u8) {
|
||||||
@@ -157,7 +131,7 @@ pub fn int(cpu: &mut i8088, bus: &mut Bus, num: u8) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ja(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn ja(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if !flags.cf && !flags.zf {
|
if !flags.cf && !flags.zf() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,7 +149,7 @@ pub fn jb(flags: &Flags, mut ip: Reg, rel8: u16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn jbe(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jbe(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if flags.cf || flags.zf {
|
if flags.cf || flags.zf() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,25 +161,25 @@ pub fn jcxz(mut ip: Reg, cx: Reg, rel8: u16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn jg(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jg(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if flags.zf && flags.sf == flags.of {
|
if flags.zf() && flags.sf() == flags.of() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jge(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jge(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if flags.sf == flags.of {
|
if flags.sf() == flags.of() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jl(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jl(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if flags.sf != flags.of {
|
if flags.sf() != flags.of() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jle(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jle(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if flags.zf || flags.sf != flags.of {
|
if flags.zf() || flags.sf() != flags.of() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,37 +189,50 @@ pub fn jmp(mut ip: Reg, rel: u16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn jno(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jno(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if !flags.of {
|
if !flags.of() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jns(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jns(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if !flags.sf {
|
if !flags.sf() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jnz(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jnz(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if !flags.zf {
|
if !flags.zf() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jo(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jo(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if flags.of {
|
if flags.of() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn jpe(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
|
if flags.pf() {
|
||||||
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn jpo(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
|
if !flags.pf() {
|
||||||
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn js(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn js(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if flags.sf {
|
if flags.sf() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jz(flags: &Flags, mut ip: Reg, rel8: u16) {
|
pub fn jz(flags: &Flags, mut ip: Reg, rel8: u16) {
|
||||||
if flags.zf {
|
if flags.zf() {
|
||||||
ip.write(ip.read().wrapping_add(rel8));
|
ip.write(ip.read().wrapping_add(rel8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -394,7 +381,7 @@ pub fn scasb(flags: &mut Flags,
|
|||||||
mut di: Reg,
|
mut di: Reg,
|
||||||
needle: impl RValue<u8>) {
|
needle: impl RValue<u8>) {
|
||||||
let needle = needle.read();
|
let needle = needle.read();
|
||||||
string_op!((u8, flags, rep, cx, di=di, zf=flags.zf), {
|
string_op!((u8, flags, rep, cx, di=di, zf=flags.zf()), {
|
||||||
let elem = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
let elem = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
||||||
cmp(flags, elem, needle);
|
cmp(flags, elem, needle);
|
||||||
});
|
});
|
||||||
@@ -408,7 +395,7 @@ pub fn scasw(flags: &mut Flags,
|
|||||||
mut di: Reg,
|
mut di: Reg,
|
||||||
needle: impl RValue<u16>) {
|
needle: impl RValue<u16>) {
|
||||||
let needle = needle.read();
|
let needle = needle.read();
|
||||||
string_op!((u16, flags, rep, cx, di=di, zf=flags.zf), {
|
string_op!((u16, flags, rep, cx, di=di, zf=flags.zf()), {
|
||||||
let elem = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
let elem = FarPtr { bus: bus, segment: es.read(), offset: di.read() };
|
||||||
cmp(flags, elem, needle);
|
cmp(flags, elem, needle);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user