emu: ROL/ROR operations
This commit is contained in:
@@ -87,11 +87,22 @@ impl Flags {
|
|||||||
OperandWidth::Word => 0x8000,
|
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)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum FlagOp {
|
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,
|
DEC,
|
||||||
INC,
|
INC,
|
||||||
SHIFT,
|
SHIFT,
|
||||||
|
|||||||
@@ -520,16 +520,24 @@ impl i8088 {
|
|||||||
0xBF => mov[reg=di, d16] / 4,
|
0xBF => mov[reg=di, d16] / 4,
|
||||||
0xC3 => pop[bus, regval=ss, reg=sp, reg=ip] / 20, // RET
|
0xC3 => pop[bus, regval=ss, reg=sp, reg=ip] / 20, // RET
|
||||||
0xCD => int[cpu, bus, d8] / 71,
|
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
|
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: { 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
|
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: { 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
|
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: { 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
|
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
|
||||||
0xE3 => jcxz[reg=ip, reg=c, rel8] / "18/6", // JCXZ rel8
|
0xE3 => jcxz[reg=ip, reg=c, rel8] / "18/6", // JCXZ rel8
|
||||||
|
|||||||
@@ -8,20 +8,19 @@ use emu::pc::Bus;
|
|||||||
|
|
||||||
pub trait Operand: Copy + 'static +
|
pub trait Operand: Copy + 'static +
|
||||||
std::convert::Into<u16> +
|
std::convert::Into<u16> +
|
||||||
nt::Num +
|
nt::int::PrimInt +
|
||||||
nt::Bounded +
|
|
||||||
nt::ops::checked::CheckedShl<Output = Self> +
|
nt::ops::checked::CheckedShl<Output = Self> +
|
||||||
nt::ops::checked::CheckedShr<Output = Self> +
|
nt::ops::checked::CheckedShr<Output = Self> +
|
||||||
nt::ops::overflowing::OverflowingAdd +
|
|
||||||
nt::ops::overflowing::OverflowingSub +
|
nt::ops::overflowing::OverflowingSub +
|
||||||
nt::ops::wrapping::WrappingAdd +
|
nt::ops::wrapping::WrappingAdd +
|
||||||
nt::ops::wrapping::WrappingSub +
|
nt::ops::wrapping::WrappingSub +
|
||||||
std::ops::BitAnd<Output = Self> +
|
std::ops::Shl<Output = Self> +
|
||||||
std::ops::BitXor<Output = Self>
|
std::ops::Shr<Output = Self>
|
||||||
{
|
{
|
||||||
type Signed: nt::ops::checked::CheckedShr<Output = Self::Signed>;
|
type Signed: nt::ops::checked::CheckedShr<Output = Self::Signed>;
|
||||||
const WIDTH: OperandWidth;
|
const WIDTH: OperandWidth;
|
||||||
const HI_BIT_MASK: Self;
|
const HI_BIT_MASK: Self;
|
||||||
|
const BITS: Self;
|
||||||
|
|
||||||
fn hi_bit(self) -> bool;
|
fn hi_bit(self) -> bool;
|
||||||
fn as_signed(self) -> Self::Signed;
|
fn as_signed(self) -> Self::Signed;
|
||||||
@@ -37,6 +36,7 @@ impl Operand for u8 {
|
|||||||
type Signed = i8;
|
type Signed = i8;
|
||||||
const WIDTH: OperandWidth = OperandWidth::Byte;
|
const WIDTH: OperandWidth = OperandWidth::Byte;
|
||||||
const HI_BIT_MASK: u8 = 0x80;
|
const HI_BIT_MASK: u8 = 0x80;
|
||||||
|
const BITS: u8 = 8;
|
||||||
|
|
||||||
fn hi_bit(self) -> bool {
|
fn hi_bit(self) -> bool {
|
||||||
self >> 7 == 1
|
self >> 7 == 1
|
||||||
@@ -55,6 +55,7 @@ impl Operand for u16 {
|
|||||||
type Signed = i16;
|
type Signed = i16;
|
||||||
const WIDTH: OperandWidth = OperandWidth::Word;
|
const WIDTH: OperandWidth = OperandWidth::Word;
|
||||||
const HI_BIT_MASK: u16 = 0x8000;
|
const HI_BIT_MASK: u16 = 0x8000;
|
||||||
|
const BITS: u16 = 16;
|
||||||
|
|
||||||
fn hi_bit(self) -> bool {
|
fn hi_bit(self) -> bool {
|
||||||
self >> 15 == 1
|
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)
|
pub fn sar<T, U, LVal, RVal>(flags: &mut Flags, mut dst: LVal, src: RVal)
|
||||||
where T: Operand,
|
where T: Operand,
|
||||||
U: Operand + AsPrimitive<u32>,
|
U: Operand + AsPrimitive<u32>,
|
||||||
|
|||||||
Reference in New Issue
Block a user