emu: ROL/ROR operations
This commit is contained in:
@@ -87,11 +87,22 @@ impl Flags {
|
||||
OperandWidth::Word => 0x8000,
|
||||
}
|
||||
}
|
||||
|
||||
// The rotate ops update OF don't touch PF/AF/ZF/SF so we make
|
||||
// everything eager so they don't get clobbered
|
||||
pub fn update_of(&mut self, of: bool) {
|
||||
let mut flags = (*self).into();
|
||||
flags &= !(1 << OF_BIT); // Mask out old OF Flag
|
||||
if of { flags |= 1 << OF_BIT; } // Mask in new OF Flag
|
||||
|
||||
self.flag_op = FlagOp::Eager;
|
||||
self.res = flags;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum FlagOp {
|
||||
Eager, // precomputed into result, for e.g. POPF? (Anything else?)
|
||||
Eager, // precomputed into result, for POPF or anything that changes only some flags
|
||||
DEC,
|
||||
INC,
|
||||
SHIFT,
|
||||
|
||||
@@ -520,16 +520,24 @@ impl i8088 {
|
||||
0xBF => mov[reg=di, d16] / 4,
|
||||
0xC3 => pop[bus, regval=ss, reg=sp, reg=ip] / 20, // RET
|
||||
0xCD => int[cpu, bus, d8] / 71,
|
||||
0xD0: { 0x20 => shl[form=byte3, flags, modrm8, const=1u8] / "2/23+", // SHL r/m8, 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
|
||||
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
|
||||
0x38 => sar[form=byte3, flags, modrm8, const=1u8] / "2/23+" }, // SAR r/m8, 1
|
||||
0xD1: { 0x20 => shl[form=word3, flags, modrm16, const=1u16] / "2/23+", // SHL 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
|
||||
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
|
||||
0x38 => sar[form=word3, flags, modrm16, const=1u16] / "2/23+" }, // SAR r/m16, 1
|
||||
0xD2: { 0x20 => shl[form=byte3, flags, modrm8, reglo=c] / "2/23+", // SHL 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
|
||||
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
|
||||
0x38 => sar[form=byte3, flags, modrm8, reglo=c] / "2/23+" }, // SAR r/m8, CL
|
||||
0xD3: { 0x20 => shl[form=word3, flags, modrm16, reglo=c] / "2/23+", // SHL 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
|
||||
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
|
||||
0x38 => sar[form=word3, flags, modrm16, reglo=c] / "2/23+" }, // SAR r/m16, CL
|
||||
0xE3 => jcxz[reg=ip, reg=c, rel8] / "18/6", // JCXZ rel8
|
||||
|
||||
@@ -8,20 +8,19 @@ use emu::pc::Bus;
|
||||
|
||||
pub trait Operand: Copy + 'static +
|
||||
std::convert::Into<u16> +
|
||||
nt::Num +
|
||||
nt::Bounded +
|
||||
nt::int::PrimInt +
|
||||
nt::ops::checked::CheckedShl<Output = Self> +
|
||||
nt::ops::checked::CheckedShr<Output = Self> +
|
||||
nt::ops::overflowing::OverflowingAdd +
|
||||
nt::ops::overflowing::OverflowingSub +
|
||||
nt::ops::wrapping::WrappingAdd +
|
||||
nt::ops::wrapping::WrappingSub +
|
||||
std::ops::BitAnd<Output = Self> +
|
||||
std::ops::BitXor<Output = Self>
|
||||
std::ops::Shl<Output = Self> +
|
||||
std::ops::Shr<Output = Self>
|
||||
{
|
||||
type Signed: nt::ops::checked::CheckedShr<Output = Self::Signed>;
|
||||
const WIDTH: OperandWidth;
|
||||
const HI_BIT_MASK: Self;
|
||||
const BITS: Self;
|
||||
|
||||
fn hi_bit(self) -> bool;
|
||||
fn as_signed(self) -> Self::Signed;
|
||||
@@ -37,6 +36,7 @@ impl Operand for u8 {
|
||||
type Signed = i8;
|
||||
const WIDTH: OperandWidth = OperandWidth::Byte;
|
||||
const HI_BIT_MASK: u8 = 0x80;
|
||||
const BITS: u8 = 8;
|
||||
|
||||
fn hi_bit(self) -> bool {
|
||||
self >> 7 == 1
|
||||
@@ -55,6 +55,7 @@ impl Operand for u16 {
|
||||
type Signed = i16;
|
||||
const WIDTH: OperandWidth = OperandWidth::Word;
|
||||
const HI_BIT_MASK: u16 = 0x8000;
|
||||
const BITS: u16 = 16;
|
||||
|
||||
fn hi_bit(self) -> bool {
|
||||
self >> 15 == 1
|
||||
|
||||
@@ -327,6 +327,40 @@ pub fn push_modrm<'a>(ss: u16, sp: Reg, src: DynLValue<'a>, bus: &mut Bus) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rol<T, U, LVal, RVal>(flags: &mut Flags,
|
||||
mut dst: LVal,
|
||||
src: RVal)
|
||||
where T: Operand + From<U>,
|
||||
U: Operand + AsPrimitive<u32>,
|
||||
LVal: LValue<T>,
|
||||
RVal: RValue<U>
|
||||
{
|
||||
let dst_before = dst.read();
|
||||
let src_before = src.read(); // may alias dst
|
||||
if src_before == U::zero() { return } // 286 and beyond probably masks shamt before this check?
|
||||
let res = dst_before.rotate_left(src_before.as_());
|
||||
dst.write(res);
|
||||
flags.cf = T::zero() != dst_before & (T::HI_BIT_MASK >> (<T as From<U>>::from(src_before - U::one()) % T::BITS));
|
||||
flags.update_of(T::zero() != T::HI_BIT_MASK & (dst_before ^ res));
|
||||
}
|
||||
|
||||
pub fn ror<T, U, LVal, RVal>(flags: &mut Flags,
|
||||
mut dst: LVal,
|
||||
src: RVal)
|
||||
where T: Operand + From<U>,
|
||||
U: Operand + Into<T> + AsPrimitive<u32>,
|
||||
LVal: LValue<T>,
|
||||
RVal: RValue<U>
|
||||
{
|
||||
let dst_before = dst.read();
|
||||
let src_before = src.read(); // may alias dst
|
||||
if src_before == U::zero() { return } // 286 and beyond probably masks shamt before this check?
|
||||
let res = dst_before.rotate_right(src_before.as_());
|
||||
dst.write(res);
|
||||
flags.cf = T::zero() != dst_before & (T::one() << (<T as From<U>>::from(src_before - U::one()) % T::BITS));
|
||||
flags.update_of(T::zero() != T::HI_BIT_MASK & (dst_before ^ res));
|
||||
}
|
||||
|
||||
pub fn sar<T, U, LVal, RVal>(flags: &mut Flags, mut dst: LVal, src: RVal)
|
||||
where T: Operand,
|
||||
U: Operand + AsPrimitive<u32>,
|
||||
|
||||
Reference in New Issue
Block a user