emu: RCL/RCR ops.
I even did some testing this time...
This commit is contained in:
@@ -7,13 +7,13 @@ authors = ["Jared Burce <jaredr@gmail.com>"]
|
|||||||
byteorder = "1.4.2"
|
byteorder = "1.4.2"
|
||||||
env_logger = "0.3"
|
env_logger = "0.3"
|
||||||
itertools = ">=0.4"
|
itertools = ">=0.4"
|
||||||
log = "0.3"
|
|
||||||
memmap = "~0.2"
|
|
||||||
gl = "0.10"
|
gl = "0.10"
|
||||||
gfx = "0.17"
|
gfx = "0.17"
|
||||||
gfx_device_gl = "0.15"
|
gfx_device_gl = "0.15"
|
||||||
image = "0.19"
|
image = "0.19"
|
||||||
|
log = "0.3"
|
||||||
lzw = "0.10"
|
lzw = "0.10"
|
||||||
|
memmap = "~0.2"
|
||||||
nalgebra = "0.16"
|
nalgebra = "0.16"
|
||||||
num-traits = "0.2.14"
|
num-traits = "0.2.14"
|
||||||
openvr = "0.6.0"
|
openvr = "0.6.0"
|
||||||
|
|||||||
@@ -39,11 +39,27 @@ impl Flags {
|
|||||||
FlagOp::DEC { cf } => cf,
|
FlagOp::DEC { cf } => cf,
|
||||||
FlagOp::INC { cf } => cf,
|
FlagOp::INC { cf } => cf,
|
||||||
FlagOp::POPF => { self.res & 1 << CF_BIT != 0 },
|
FlagOp::POPF => { self.res & 1 << CF_BIT != 0 },
|
||||||
FlagOp::ROL { dst, src, rot_mask, .. } => {
|
FlagOp::RCL { dst, shamt, bits, old_cf, .. } => {
|
||||||
dst & (self.sign_mask >> ((src.wrapping_sub(1)) & rot_mask as u16)) != 0
|
// for carry-rotate shamt bas been modded to have range [0,bits].
|
||||||
|
let full_dst = dst as u32
|
||||||
|
| (old_cf as u32) << bits; // dst w/ carry as new hi-bit
|
||||||
|
let hi_bit = 1u32 << bits;
|
||||||
|
full_dst & (hi_bit >> shamt) != 0
|
||||||
},
|
},
|
||||||
FlagOp::ROR { dst, src, rot_mask, .. } => {
|
FlagOp::RCR { dst, shamt, old_cf, .. } => {
|
||||||
dst & (1 << ((src.wrapping_sub(1)) & rot_mask as u16)) != 0
|
// for carry-rotate shamt bas been modded to have range [0,bits].
|
||||||
|
let full_dst = (dst as u32) << 1
|
||||||
|
| old_cf as u32; // dst w/ carry as new lo-bit
|
||||||
|
full_dst & (1 << shamt) != 0
|
||||||
|
},
|
||||||
|
// Rotate without carry only preserves previous CF on shamt=0,
|
||||||
|
// which is an early-return in the op and doesn't touch flags,
|
||||||
|
// so it doesn't need to be considered here.
|
||||||
|
FlagOp::ROL { dst, shamt, rot_mask, .. } => {
|
||||||
|
dst & (self.sign_mask >> ((shamt.wrapping_sub(1)) & rot_mask as u16)) != 0
|
||||||
|
},
|
||||||
|
FlagOp::ROR { dst, shamt, rot_mask, .. } => {
|
||||||
|
dst & (1 << ((shamt.wrapping_sub(1)) & rot_mask as u16)) != 0
|
||||||
},
|
},
|
||||||
FlagOp::SAR { dst, src, sign_bit } => {
|
FlagOp::SAR { dst, src, sign_bit } => {
|
||||||
match 1u16.checked_shl(src as u32 - 1) {
|
match 1u16.checked_shl(src as u32 - 1) {
|
||||||
@@ -71,7 +87,9 @@ impl Flags {
|
|||||||
match self.flag_op {
|
match self.flag_op {
|
||||||
FlagOp::Eager { pf, .. } => pf,
|
FlagOp::Eager { pf, .. } => pf,
|
||||||
FlagOp::POPF => { self.res & 1 << PF_BIT != 0 },
|
FlagOp::POPF => { self.res & 1 << PF_BIT != 0 },
|
||||||
FlagOp::ROL { pf, .. }
|
FlagOp::RCL { pf, .. }
|
||||||
|
| FlagOp::RCR { pf, .. }
|
||||||
|
| FlagOp::ROL { pf, .. }
|
||||||
| FlagOp::ROR { pf, .. } => pf,
|
| FlagOp::ROR { pf, .. } => pf,
|
||||||
_ => { self.res.count_ones() & 1 == 0 },
|
_ => { self.res.count_ones() & 1 == 0 },
|
||||||
}
|
}
|
||||||
@@ -81,7 +99,9 @@ impl Flags {
|
|||||||
match self.flag_op {
|
match self.flag_op {
|
||||||
FlagOp::Eager { af, .. } => af,
|
FlagOp::Eager { af, .. } => af,
|
||||||
FlagOp::POPF => { self.res & 1 << AF_BIT != 0 },
|
FlagOp::POPF => { self.res & 1 << AF_BIT != 0 },
|
||||||
FlagOp::ROL { af, .. }
|
FlagOp::RCL { af, .. }
|
||||||
|
| FlagOp::RCR { af, .. }
|
||||||
|
| FlagOp::ROL { af, .. }
|
||||||
| FlagOp::ROR { af, .. } => af,
|
| FlagOp::ROR { af, .. } => af,
|
||||||
_ => { false /* XXX: unimplemented! */ },
|
_ => { false /* XXX: unimplemented! */ },
|
||||||
}
|
}
|
||||||
@@ -91,7 +111,9 @@ impl Flags {
|
|||||||
match self.flag_op {
|
match self.flag_op {
|
||||||
FlagOp::Eager { zf, .. } => zf,
|
FlagOp::Eager { zf, .. } => zf,
|
||||||
FlagOp::POPF => { self.res & 1 << ZF_BIT != 0 },
|
FlagOp::POPF => { self.res & 1 << ZF_BIT != 0 },
|
||||||
FlagOp::ROL { zf, .. }
|
FlagOp::RCL { zf, .. }
|
||||||
|
| FlagOp::RCR { zf, .. }
|
||||||
|
| FlagOp::ROL { zf, .. }
|
||||||
| FlagOp::ROR { zf, .. } => zf,
|
| FlagOp::ROR { zf, .. } => zf,
|
||||||
_ => { self.res == 0 },
|
_ => { self.res == 0 },
|
||||||
}
|
}
|
||||||
@@ -101,7 +123,9 @@ impl Flags {
|
|||||||
match self.flag_op {
|
match self.flag_op {
|
||||||
FlagOp::Eager { sf, .. } => sf,
|
FlagOp::Eager { sf, .. } => sf,
|
||||||
FlagOp::POPF => { self.res & 1 << SF_BIT != 0 },
|
FlagOp::POPF => { self.res & 1 << SF_BIT != 0 },
|
||||||
FlagOp::ROL { sf, .. }
|
FlagOp::RCL { sf, .. }
|
||||||
|
| FlagOp::RCR { sf, .. }
|
||||||
|
| FlagOp::ROL { sf, .. }
|
||||||
| FlagOp::ROR { sf, .. } => sf,
|
| FlagOp::ROR { sf, .. } => sf,
|
||||||
_ => { self.res & self.sign_mask != 0 },
|
_ => { self.res & self.sign_mask != 0 },
|
||||||
}
|
}
|
||||||
@@ -110,17 +134,19 @@ impl Flags {
|
|||||||
pub fn of(&self) -> bool {
|
pub fn of(&self) -> bool {
|
||||||
match self.flag_op {
|
match self.flag_op {
|
||||||
FlagOp::Eager { of, .. } => of,
|
FlagOp::Eager { of, .. } => of,
|
||||||
FlagOp::POPF => { self.res & 1 << OF_BIT != 0 },
|
|
||||||
FlagOp::DEC { .. } => { self.res == self.sign_mask - 1 },
|
FlagOp::DEC { .. } => { self.res == self.sign_mask - 1 },
|
||||||
FlagOp::INC { .. } => { self.res == self.sign_mask },
|
FlagOp::INC { .. } => { self.res == self.sign_mask },
|
||||||
FlagOp::ROL { dst, .. }
|
FlagOp::POPF => { self.res & 1 << OF_BIT != 0 },
|
||||||
|
FlagOp::RCL { dst, .. }
|
||||||
|
| FlagOp::RCR { dst, .. }
|
||||||
|
| FlagOp::ROL { dst, .. }
|
||||||
| FlagOp::ROR { dst, .. } => { self.sign_mask & (dst ^ self.res) != 0 },
|
| FlagOp::ROR { dst, .. } => { self.sign_mask & (dst ^ self.res) != 0 },
|
||||||
FlagOp::SAR { dst, .. }
|
FlagOp::SAR { dst, .. }
|
||||||
| FlagOp::SHL { dst, .. }
|
| FlagOp::SHL { dst, .. }
|
||||||
| FlagOp::SHR { dst, .. } => { 0 != self.sign_mask & (dst ^ self.res) },
|
| FlagOp::SHR { dst, .. } => { 0 != self.sign_mask & (dst ^ self.res) },
|
||||||
FlagOp::SUB { dst, src, .. } => { 0 != self.sign_mask & // In the (maybe) sign bit...
|
FlagOp::SUB { dst, src, .. } => { 0 != self.sign_mask & // In the (maybe) sign bit...
|
||||||
(src ^ dst) & // ...operands have different signs...
|
(src ^ dst) & // ...operands have different signs...
|
||||||
(dst ^ self.res) }, /* ...and result sign-bit changed */
|
(dst ^ self.res) }, // ...and result sign-bit changed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,8 +163,10 @@ pub enum FlagOp {
|
|||||||
DEC { cf: bool },
|
DEC { cf: bool },
|
||||||
INC { cf: bool },
|
INC { cf: bool },
|
||||||
POPF, // flags encoded in result
|
POPF, // flags encoded in result
|
||||||
ROL { dst: u16, src: u16, rot_mask: u16, cf: bool, pf: bool, af: bool, zf: bool, sf: bool },
|
RCL { dst: u16, shamt: u16, bits: u16, old_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 },
|
RCR { dst: u16, shamt: u16, old_cf: bool, pf: bool, af: bool, zf: bool, sf: bool },
|
||||||
|
ROL { dst: u16, shamt: u16, rot_mask: u16, pf: bool, af: bool, zf: bool, sf: bool },
|
||||||
|
ROR { dst: u16, shamt: u16, rot_mask: u16, pf: bool, af: bool, zf: bool, sf: bool },
|
||||||
SAR { dst: u16, src: u16, sign_bit: bool },
|
SAR { dst: u16, src: u16, sign_bit: bool },
|
||||||
SHL { dst: u16, src: u16 },
|
SHL { dst: u16, src: u16 },
|
||||||
SHR { dst: u16, src: u16 },
|
SHR { dst: u16, src: u16 },
|
||||||
|
|||||||
@@ -524,21 +524,29 @@ impl i8088 {
|
|||||||
0xCD => int[cpu, bus, d8] / 71,
|
0xCD => int[cpu, bus, d8] / 71,
|
||||||
0xD0: { 0x00 => rol[form=byte3, flags, modrm8, const=1u8] / "2/23+", // ROL r/m16, 1
|
0xD0: { 0x00 => rol[form=byte3, flags, modrm8, const=1u8] / "2/23+", // ROL r/m16, 1
|
||||||
0x08 => ror[form=byte3, flags, modrm8, const=1u8] / "2/23+", // ROR r/m16, 1
|
0x08 => ror[form=byte3, flags, modrm8, const=1u8] / "2/23+", // ROR r/m16, 1
|
||||||
|
0x10 => rcl[form=byte3, flags, modrm8, const=1u8] / "2/23+", // RCL r/m16, 1
|
||||||
|
0x18 => rcr[form=byte3, flags, modrm8, const=1u8] / "2/23+", // RCR r/m16, 1
|
||||||
0x20 => shl[form=byte3, flags, modrm8, const=1u8] / "2/23+", // SHL r/m8, 1
|
0x20 => shl[form=byte3, flags, modrm8, const=1u8] / "2/23+", // SHL r/m8, 1
|
||||||
0x28 => shr[form=byte3, flags, modrm8, const=1u8] / "2/23+", // SHR r/m8, 1
|
0x28 => shr[form=byte3, flags, modrm8, const=1u8] / "2/23+", // SHR r/m8, 1
|
||||||
0x38 => sar[form=byte3, flags, modrm8, const=1u8] / "2/23+" }, // SAR r/m8, 1
|
0x38 => sar[form=byte3, flags, modrm8, const=1u8] / "2/23+" }, // SAR r/m8, 1
|
||||||
0xD1: { 0x00 => rol[form=word3, flags, modrm16, const=1u16] / "2/23+", // ROL r/m16, 1
|
0xD1: { 0x00 => rol[form=word3, flags, modrm16, const=1u16] / "2/23+", // ROL r/m16, 1
|
||||||
0x08 => ror[form=word3, flags, modrm16, const=1u16] / "2/23+", // ROR r/m16, 1
|
0x08 => ror[form=word3, flags, modrm16, const=1u16] / "2/23+", // ROR r/m16, 1
|
||||||
|
0x10 => rcl[form=word3, flags, modrm16, const=1u16] / "2/23+", // RCL r/m16, 1
|
||||||
|
0x18 => rcr[form=word3, flags, modrm16, const=1u16] / "2/23+", // RCR r/m16, 1
|
||||||
0x20 => shl[form=word3, flags, modrm16, const=1u16] / "2/23+", // SHL r/m16, 1
|
0x20 => shl[form=word3, flags, modrm16, const=1u16] / "2/23+", // SHL r/m16, 1
|
||||||
0x28 => shr[form=word3, flags, modrm16, const=1u16] / "2/23+", // SHR r/m16, 1
|
0x28 => shr[form=word3, flags, modrm16, const=1u16] / "2/23+", // SHR r/m16, 1
|
||||||
0x38 => sar[form=word3, flags, modrm16, const=1u16] / "2/23+" }, // SAR r/m16, 1
|
0x38 => sar[form=word3, flags, modrm16, const=1u16] / "2/23+" }, // SAR r/m16, 1
|
||||||
0xD2: { 0x00 => rol[form=byte3, flags, modrm8, reglo=c] / "8/28++4n", // ROL r/m8, CL
|
0xD2: { 0x00 => rol[form=byte3, flags, modrm8, reglo=c] / "8/28++4n", // ROL r/m8, CL
|
||||||
0x08 => ror[form=byte3, flags, modrm8, reglo=c] / "8/28++4n", // ROR r/m8, CL
|
0x08 => ror[form=byte3, flags, modrm8, reglo=c] / "8/28++4n", // ROR r/m8, CL
|
||||||
|
0x10 => rcl[form=byte3, flags, modrm8, reglo=c] / "8/28++4n", // RCL r/m8, CL
|
||||||
|
0x18 => rcr[form=byte3, flags, modrm8, reglo=c] / "8/28++4n", // RCR r/m8, CL
|
||||||
0x20 => shl[form=byte3, flags, modrm8, reglo=c] / "2/23+", // SHL r/m8, CL
|
0x20 => shl[form=byte3, flags, modrm8, reglo=c] / "2/23+", // SHL r/m8, CL
|
||||||
0x28 => shr[form=byte3, flags, modrm8, reglo=c] / "2/23+", // SHR r/m8, CL
|
0x28 => shr[form=byte3, flags, modrm8, reglo=c] / "2/23+", // SHR r/m8, CL
|
||||||
0x38 => sar[form=byte3, flags, modrm8, reglo=c] / "2/23+" }, // SAR r/m8, CL
|
0x38 => sar[form=byte3, flags, modrm8, reglo=c] / "2/23+" }, // SAR r/m8, CL
|
||||||
0xD3: { 0x00 => rol[form=word3, flags, modrm16, reglo=c] / "8/28++4n", // ROL r/m16, CL
|
0xD3: { 0x00 => rol[form=word3, flags, modrm16, reglo=c] / "8/28++4n", // ROL r/m16, CL
|
||||||
0x08 => ror[form=word3, flags, modrm16, reglo=c] / "8/28++4n", // ROR r/m16, CL
|
0x08 => ror[form=word3, flags, modrm16, reglo=c] / "8/28++4n", // ROR r/m16, CL
|
||||||
|
0x10 => rcl[form=word3, flags, modrm16, reglo=c] / "8/28++4n", // RCL r/m16, CL
|
||||||
|
0x18 => rcr[form=word3, flags, modrm16, reglo=c] / "8/28++4n", // RCR r/m16, CL
|
||||||
0x20 => shl[form=word3, flags, modrm16, reglo=c] / "2/23+", // SHL r/m16, CL
|
0x20 => shl[form=word3, flags, modrm16, reglo=c] / "2/23+", // SHL r/m16, CL
|
||||||
0x28 => shr[form=word3, flags, modrm16, reglo=c] / "2/23+", // SHR r/m16, CL
|
0x28 => shr[form=word3, flags, modrm16, reglo=c] / "2/23+", // SHR r/m16, CL
|
||||||
0x38 => sar[form=word3, flags, modrm16, reglo=c] / "2/23+" }, // SAR r/m16, CL
|
0x38 => sar[form=word3, flags, modrm16, reglo=c] / "2/23+" }, // SAR r/m16, CL
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use emu::pc::Bus;
|
|||||||
|
|
||||||
pub trait Operand: Copy + 'static +
|
pub trait Operand: Copy + 'static +
|
||||||
std::convert::Into<u16> +
|
std::convert::Into<u16> +
|
||||||
|
std::fmt::Display +
|
||||||
nt::int::PrimInt +
|
nt::int::PrimInt +
|
||||||
nt::ops::checked::CheckedShl<Output = Self> +
|
nt::ops::checked::CheckedShl<Output = Self> +
|
||||||
nt::ops::checked::CheckedShr<Output = Self> +
|
nt::ops::checked::CheckedShr<Output = Self> +
|
||||||
@@ -19,7 +20,8 @@ pub trait Operand: Copy + 'static +
|
|||||||
{
|
{
|
||||||
type Signed: nt::ops::checked::CheckedShr<Output = Self::Signed>;
|
type Signed: nt::ops::checked::CheckedShr<Output = Self::Signed>;
|
||||||
const HI_BIT_MASK: Self;
|
const HI_BIT_MASK: Self;
|
||||||
const ROTATE_MASK: u16 = (std::mem::size_of::<Self>() * 8 - 1) as _;
|
const BITS: u16 = std::mem::size_of::<Self>() as u16 * 8;
|
||||||
|
const ROTATE_MASK: u16 = Self::BITS - 1;
|
||||||
|
|
||||||
fn hi_bit(self) -> bool;
|
fn hi_bit(self) -> bool;
|
||||||
fn as_signed(self) -> Self::Signed;
|
fn as_signed(self) -> Self::Signed;
|
||||||
|
|||||||
@@ -354,6 +354,87 @@ pub fn push_modrm<'a>(ss: u16, sp: Reg, src: DynLValue<'a>, bus: &mut Bus) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rcl<T, U, LVal, RVal>(flags: &mut Flags,
|
||||||
|
mut dst: LVal,
|
||||||
|
src: RVal)
|
||||||
|
where T: Operand + Into<u32>,
|
||||||
|
U: Operand + AsPrimitive<u32>,
|
||||||
|
LVal: LValue<T>,
|
||||||
|
RVal: RValue<U>,
|
||||||
|
u32: AsPrimitive<T>
|
||||||
|
{
|
||||||
|
// Rust shifts overflow if shamt >= bit-size of the
|
||||||
|
// operand. Unfortunately, because we're looping-in the carry flag,
|
||||||
|
// our operand size is effectively 1 bit larger and so we might want
|
||||||
|
// a shift as large as the base operand size. We'll use u32 instead
|
||||||
|
// so that we always have adequate range on shifting operations.
|
||||||
|
//
|
||||||
|
// TODO-ish: Rust doesn't have static asserts, but it'd be nice to
|
||||||
|
// verify that u32 is larger than our operand. This technique is
|
||||||
|
// also used in the CF flag calculation.
|
||||||
|
let dst_before: u32 = dst.read().into();
|
||||||
|
let src_before = src.read().into(); // may alias dst
|
||||||
|
let shamt = src_before % (T::BITS + 1); // carry-flag effectively enlarges operand 1 bit
|
||||||
|
let res;
|
||||||
|
if shamt == 0 {
|
||||||
|
res = dst_before;
|
||||||
|
dst.write(res.as_()); // dst may be volatile
|
||||||
|
if src_before == 0 { return } // No flags update
|
||||||
|
} else {
|
||||||
|
res = dst_before << shamt
|
||||||
|
| (flags.cf() as u32) << shamt - 1
|
||||||
|
| dst_before >> T::BITS + 1 - shamt;
|
||||||
|
dst.write(res.as_());
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.update(FlagOp::RCL { dst: dst_before as u16,
|
||||||
|
shamt: shamt,
|
||||||
|
bits: T::BITS,
|
||||||
|
old_cf: flags.cf(),
|
||||||
|
pf: flags.pf(),
|
||||||
|
af: flags.af(),
|
||||||
|
zf: flags.zf(),
|
||||||
|
sf: flags.sf() },
|
||||||
|
res as u16,
|
||||||
|
T::HI_BIT_MASK.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rcr<T, U, LVal, RVal>(flags: &mut Flags,
|
||||||
|
mut dst: LVal,
|
||||||
|
src: RVal)
|
||||||
|
where T: Operand + Into<u32>,
|
||||||
|
U: Operand + AsPrimitive<u32>,
|
||||||
|
LVal: LValue<T>,
|
||||||
|
RVal: RValue<U>,
|
||||||
|
u32: AsPrimitive<T>
|
||||||
|
{
|
||||||
|
// See comments on rcl().
|
||||||
|
let dst_before:u32 = dst.read().into();
|
||||||
|
let src_before = src.read().into(); // may alias dst
|
||||||
|
let shamt = src_before % (T::BITS + 1); // carry-flag effectively enlarges operand 1 bit
|
||||||
|
let res;
|
||||||
|
if shamt == 0 {
|
||||||
|
res = dst_before;
|
||||||
|
dst.write(res.as_()); // dst may be volatile
|
||||||
|
if src_before == 0 { return } // No flags update
|
||||||
|
} else {
|
||||||
|
res = dst_before >> shamt
|
||||||
|
| (flags.cf() as u32) << T::BITS >> shamt
|
||||||
|
| dst_before << T::BITS + 1 - shamt;
|
||||||
|
dst.write(res.as_());
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.update(FlagOp::RCR { dst: dst_before as u16,
|
||||||
|
shamt: shamt,
|
||||||
|
old_cf: flags.cf(),
|
||||||
|
pf: flags.pf(),
|
||||||
|
af: flags.af(),
|
||||||
|
zf: flags.zf(),
|
||||||
|
sf: flags.sf() },
|
||||||
|
res as u16,
|
||||||
|
T::HI_BIT_MASK.into());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rol<T, U, LVal, RVal>(flags: &mut Flags,
|
pub fn rol<T, U, LVal, RVal>(flags: &mut Flags,
|
||||||
mut dst: LVal,
|
mut dst: LVal,
|
||||||
src: RVal)
|
src: RVal)
|
||||||
@@ -364,13 +445,15 @@ where T: Operand,
|
|||||||
{
|
{
|
||||||
let dst_before = dst.read();
|
let dst_before = dst.read();
|
||||||
let src_before = src.read(); // may alias dst
|
let src_before = src.read(); // may alias dst
|
||||||
if src_before == U::zero() { return } // 286 and beyond probably masks shamt before this check?
|
if src_before == U::zero() { // 286 and beyond probably masks shamt before this check?
|
||||||
|
dst.write(dst_before); // dst may be volatile
|
||||||
|
return; // No flags update
|
||||||
|
}
|
||||||
let res = dst_before.rotate_left(src_before.as_());
|
let res = dst_before.rotate_left(src_before.as_());
|
||||||
dst.write(res);
|
dst.write(res);
|
||||||
flags.update(FlagOp::ROL { dst: dst_before.into(),
|
flags.update(FlagOp::ROL { dst: dst_before.into(),
|
||||||
src: src_before.into(),
|
shamt: src_before.into(),
|
||||||
rot_mask: T::ROTATE_MASK,
|
rot_mask: T::ROTATE_MASK,
|
||||||
cf: flags.cf(),
|
|
||||||
pf: flags.pf(),
|
pf: flags.pf(),
|
||||||
af: flags.af(),
|
af: flags.af(),
|
||||||
zf: flags.zf(),
|
zf: flags.zf(),
|
||||||
@@ -389,13 +472,15 @@ where T: Operand,
|
|||||||
{
|
{
|
||||||
let dst_before = dst.read();
|
let dst_before = dst.read();
|
||||||
let src_before = src.read(); // may alias dst
|
let src_before = src.read(); // may alias dst
|
||||||
if src_before == U::zero() { return } // 286 and beyond probably masks shamt before this check?
|
if src_before == U::zero() { // 286 and beyond probably masks shamt before this check?
|
||||||
|
dst.write(dst_before); // dst may be volatile
|
||||||
|
return; // No flags update
|
||||||
|
}
|
||||||
let res = dst_before.rotate_right(src_before.as_());
|
let res = dst_before.rotate_right(src_before.as_());
|
||||||
dst.write(res);
|
dst.write(res);
|
||||||
flags.update(FlagOp::ROR { dst: dst_before.into(),
|
flags.update(FlagOp::ROR { dst: dst_before.into(),
|
||||||
src: src_before.into(),
|
shamt: src_before.into(),
|
||||||
rot_mask: T::ROTATE_MASK,
|
rot_mask: T::ROTATE_MASK,
|
||||||
cf: flags.cf(),
|
|
||||||
pf: flags.pf(),
|
pf: flags.pf(),
|
||||||
af: flags.af(),
|
af: flags.af(),
|
||||||
zf: flags.zf(),
|
zf: flags.zf(),
|
||||||
@@ -412,7 +497,10 @@ where T: Operand,
|
|||||||
{
|
{
|
||||||
let dst_before = dst.read();
|
let dst_before = dst.read();
|
||||||
let src_before = src.read(); // may alias dst
|
let src_before = src.read(); // may alias dst
|
||||||
if src_before == U::zero() { return }
|
if src_before == U::zero() { // 286 and beyond probably masks shamt before this check?
|
||||||
|
dst.write(dst_before); // dst may be volatile
|
||||||
|
return; // No flags update
|
||||||
|
}
|
||||||
|
|
||||||
// Before the 286, shifts could be up to 255 bits even though the
|
// Before the 286, shifts could be up to 255 bits even though the
|
||||||
// operands themselves could only be 16 bits. The 286 and beyond
|
// operands themselves could only be 16 bits. The 286 and beyond
|
||||||
@@ -462,7 +550,10 @@ where T: Operand,
|
|||||||
{
|
{
|
||||||
let dst_before = dst.read();
|
let dst_before = dst.read();
|
||||||
let src_before = src.read(); // may alias dst
|
let src_before = src.read(); // may alias dst
|
||||||
if src_before == U::zero() { return }
|
if src_before == U::zero() { // 286 and beyond probably masks shamt before this check?
|
||||||
|
dst.write(dst_before); // dst may be volatile
|
||||||
|
return; // No flags update
|
||||||
|
}
|
||||||
let res = match dst_before.checked_shl(src_before.as_()) {
|
let res = match dst_before.checked_shl(src_before.as_()) {
|
||||||
Some(shifted) => shifted,
|
Some(shifted) => shifted,
|
||||||
None => T::zero()
|
None => T::zero()
|
||||||
@@ -484,7 +575,10 @@ where T: Operand,
|
|||||||
{
|
{
|
||||||
let dst_before = dst.read();
|
let dst_before = dst.read();
|
||||||
let src_before = src.read(); // may alias dst
|
let src_before = src.read(); // may alias dst
|
||||||
if src_before == U::zero() { return }
|
if src_before == U::zero() { // 286 and beyond probably masks shamt before this check?
|
||||||
|
dst.write(dst_before); // dst may be volatile
|
||||||
|
return; // No flags update
|
||||||
|
}
|
||||||
let res = match dst_before.checked_shr(src_before.as_()) {
|
let res = match dst_before.checked_shr(src_before.as_()) {
|
||||||
Some(shifted) => shifted,
|
Some(shifted) => shifted,
|
||||||
None => T::zero()
|
None => T::zero()
|
||||||
|
|||||||
Reference in New Issue
Block a user