emu: use mask, not mod for ROL/ROR CF calc. No flags when SHL/SHR=0
This commit is contained in:
@@ -38,8 +38,12 @@ impl Flags {
|
||||
FlagOp::Eager => { self.res & 1 << CF_BIT != 0 },
|
||||
FlagOp::DEC { cf } => { cf },
|
||||
FlagOp::INC { cf } => { cf },
|
||||
FlagOp::ROL { dst, src, bits, .. } => { dst & (self.sign_mask >> ((src - 1) % bits as u16)) != 0 },
|
||||
FlagOp::ROR { dst, src, bits, .. } => { dst & (1 << ((src - 1) % bits as u16)) != 0 },
|
||||
FlagOp::ROL { dst, src, rot_mask, .. } => {
|
||||
dst & (self.sign_mask >> ((src.wrapping_sub(1)) & rot_mask as u16)) != 0
|
||||
},
|
||||
FlagOp::ROR { dst, src, rot_mask, .. } => {
|
||||
dst & (1 << ((src.wrapping_sub(1)) & rot_mask as u16)) != 0
|
||||
},
|
||||
FlagOp::SAR { dst, src, sign_bit } => {
|
||||
match 1u16.checked_shl(src as u32 - 1) {
|
||||
Some(carrymask) => dst & carrymask != 0,
|
||||
@@ -126,8 +130,8 @@ pub enum FlagOp {
|
||||
Eager, // precomputed into result, for e.g. POPF
|
||||
DEC { cf: bool },
|
||||
INC { cf: bool },
|
||||
ROL { dst: u16, src: u16, bits: u8, cf: bool, pf: bool, af: bool, zf: bool, sf: bool },
|
||||
ROR { dst: u16, src: u16, bits: u8, cf: bool, pf: bool, af: bool, zf: bool, sf: bool },
|
||||
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 },
|
||||
SHL { dst: u16, src: u16 },
|
||||
SHR { dst: u16, src: u16 },
|
||||
|
||||
@@ -19,7 +19,7 @@ pub trait Operand: Copy + 'static +
|
||||
{
|
||||
type Signed: nt::ops::checked::CheckedShr<Output = Self::Signed>;
|
||||
const HI_BIT_MASK: Self;
|
||||
const BITS: u8;
|
||||
const ROTATE_MASK: u16 = (std::mem::size_of::<Self>() * 8 - 1) as _;
|
||||
|
||||
fn hi_bit(self) -> bool;
|
||||
fn as_signed(self) -> Self::Signed;
|
||||
@@ -29,7 +29,6 @@ pub trait Operand: Copy + 'static +
|
||||
impl Operand for u8 {
|
||||
type Signed = i8;
|
||||
const HI_BIT_MASK: u8 = 0x80;
|
||||
const BITS: u8 = 8;
|
||||
|
||||
fn hi_bit(self) -> bool {
|
||||
self >> 7 == 1
|
||||
@@ -47,7 +46,6 @@ impl Operand for u8 {
|
||||
impl Operand for u16 {
|
||||
type Signed = i16;
|
||||
const HI_BIT_MASK: u16 = 0x8000;
|
||||
const BITS: u8 = 16;
|
||||
|
||||
fn hi_bit(self) -> bool {
|
||||
self >> 15 == 1
|
||||
|
||||
@@ -345,7 +345,7 @@ where T: Operand,
|
||||
dst.write(res);
|
||||
flags.update(FlagOp::ROL { dst: dst_before.into(),
|
||||
src: src_before.into(),
|
||||
bits: T::BITS,
|
||||
rot_mask: T::ROTATE_MASK,
|
||||
cf: flags.cf(),
|
||||
pf: flags.pf(),
|
||||
af: flags.af(),
|
||||
@@ -370,7 +370,7 @@ where T: Operand,
|
||||
dst.write(res);
|
||||
flags.update(FlagOp::ROR { dst: dst_before.into(),
|
||||
src: src_before.into(),
|
||||
bits: T::BITS,
|
||||
rot_mask: T::ROTATE_MASK,
|
||||
cf: flags.cf(),
|
||||
pf: flags.pf(),
|
||||
af: flags.af(),
|
||||
@@ -438,6 +438,7 @@ where T: Operand,
|
||||
{
|
||||
let dst_before = dst.read();
|
||||
let src_before = src.read(); // may alias dst
|
||||
if src_before == U::zero() { return }
|
||||
let res = match dst_before.checked_shl(src_before.as_()) {
|
||||
Some(shifted) => shifted,
|
||||
None => T::zero()
|
||||
@@ -459,6 +460,7 @@ where T: Operand,
|
||||
{
|
||||
let dst_before = dst.read();
|
||||
let src_before = src.read(); // may alias dst
|
||||
if src_before == U::zero() { return }
|
||||
let res = match dst_before.checked_shr(src_before.as_()) {
|
||||
Some(shifted) => shifted,
|
||||
None => T::zero()
|
||||
|
||||
Reference in New Issue
Block a user