emu: CMC/CLC/STC/CLD/STC instructions. POPF flags differ from Eager

This commit is contained in:
2021-04-04 00:53:05 -07:00
parent 67b5b7a615
commit 647841469d
3 changed files with 73 additions and 16 deletions

View File

@@ -35,9 +35,10 @@ pub struct Flags {
impl Flags {
pub fn cf(&self) -> bool {
match self.flag_op {
FlagOp::Eager => { self.res & 1 << CF_BIT != 0 },
FlagOp::DEC { cf } => { cf },
FlagOp::INC { cf } => { cf },
FlagOp::Eager { cf, .. } => cf,
FlagOp::DEC { cf } => cf,
FlagOp::INC { cf } => cf,
FlagOp::POPF => { self.res & 1 << CF_BIT != 0 },
FlagOp::ROL { dst, src, rot_mask, .. } => {
dst & (self.sign_mask >> ((src.wrapping_sub(1)) & rot_mask as u16)) != 0
},
@@ -62,49 +63,54 @@ impl Flags {
None => false
}
},
FlagOp::SUB { cf, .. } => { cf },
FlagOp::SUB { cf, .. } => cf,
}
}
pub fn pf(&self) -> bool {
match self.flag_op {
FlagOp::Eager => { self.res & 1 << PF_BIT != 0 },
FlagOp::Eager { pf, .. } => pf,
FlagOp::POPF => { self.res & 1 << PF_BIT != 0 },
FlagOp::ROL { pf, .. }
| FlagOp::ROR { pf, .. } => { pf },
| FlagOp::ROR { pf, .. } => pf,
_ => { self.res.count_ones() & 1 == 0 },
}
}
pub fn af(&self) -> bool {
match self.flag_op {
FlagOp::Eager => { self.res & 1 << AF_BIT != 0 },
FlagOp::Eager { af, .. } => af,
FlagOp::POPF => { self.res & 1 << AF_BIT != 0 },
FlagOp::ROL { af, .. }
| FlagOp::ROR { af, .. } => { af },
| FlagOp::ROR { af, .. } => af,
_ => { false /* XXX: unimplemented! */ },
}
}
pub fn zf(&self) -> bool {
match self.flag_op {
FlagOp::Eager => { self.res & 1 << ZF_BIT != 0 },
FlagOp::Eager { zf, .. } => zf,
FlagOp::POPF => { self.res & 1 << ZF_BIT != 0 },
FlagOp::ROL { zf, .. }
| FlagOp::ROR { zf, .. } => { zf },
| FlagOp::ROR { zf, .. } => zf,
_ => { self.res == 0 },
}
}
pub fn sf(&self) -> bool {
match self.flag_op {
FlagOp::Eager => { self.res & 1 << SF_BIT != 0 },
FlagOp::Eager { sf, .. } => sf,
FlagOp::POPF => { self.res & 1 << SF_BIT != 0 },
FlagOp::ROL { sf, .. }
| FlagOp::ROR { sf, .. } => { sf },
| FlagOp::ROR { sf, .. } => sf,
_ => { self.res & self.sign_mask != 0 },
}
}
pub fn of(&self) -> bool {
match self.flag_op {
FlagOp::Eager => { self.res & 1 << OF_BIT != 0 },
FlagOp::Eager { of, .. } => of,
FlagOp::POPF => { self.res & 1 << OF_BIT != 0 },
FlagOp::DEC { .. } => { self.res == self.sign_mask - 1 },
FlagOp::INC { .. } => { self.res == self.sign_mask },
FlagOp::ROL { dst, .. }
@@ -127,9 +133,10 @@ impl Flags {
#[derive(Clone, Copy)]
pub enum FlagOp {
Eager, // precomputed into result, for e.g. POPF
Eager { cf: bool, pf: bool, af: bool, zf: bool, sf: bool, of: bool }, // all flags precomputed
DEC { cf: bool },
INC { cf: bool },
POPF, // flags encoded in result
ROL { dst: u16, src: u16, rot_mask: u16, cf: bool, pf: bool, af: bool, zf: bool, sf: bool },
ROR { dst: u16, src: u16, rot_mask: u16, cf: bool, pf: bool, af: bool, zf: bool, sf: bool },
SAR { dst: u16, src: u16, sign_bit: bool },
@@ -139,7 +146,14 @@ pub enum FlagOp {
}
impl Default for FlagOp {
fn default() -> Self { FlagOp::Eager }
fn default() -> Self {
FlagOp::Eager { cf: false,
pf: false,
af: false,
zf: false,
sf: false,
of: false }
}
}
impl From<u16> for Flags {
@@ -149,7 +163,7 @@ impl From<u16> for Flags {
ie: flags & 1 << IF_BIT != 0,
df: flags & 1 << DF_BIT != 0,
flag_op: FlagOp::Eager,
flag_op: FlagOp::POPF,
res: flags,
sign_mask: 0,
}