fix(interpreter): set flags correctly for shifts
This commit is contained in:
@@ -418,13 +418,47 @@ impl Computer {
|
||||
Ok(imm)
|
||||
}
|
||||
|
||||
/// Rotate bits of data, pointed to from a [`ModRmTarget`].
|
||||
/// Shift bits of data, pointed to by a [`ModRMTarget`]
|
||||
pub fn shift(
|
||||
&mut self,
|
||||
target: ModRmTarget,
|
||||
shift: ImmediateOperand, // how many shifts
|
||||
shift_direction: Direction, // direction of shifting
|
||||
) -> Result<(), InterpreterError> {
|
||||
let result = match shift_direction {
|
||||
Direction::Left => {
|
||||
let imm = self.read_modrm(target)? << (shift - 1);
|
||||
self.flags.cf = imm.msb();
|
||||
let result = imm << 1;
|
||||
self.flags.of = if result.msb() == self.flags.cf {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
};
|
||||
result
|
||||
}
|
||||
Direction::Right => {
|
||||
let imm = self.read_modrm(target)? >> (shift - 1);
|
||||
self.flags.cf = imm.msb();
|
||||
imm >> 1
|
||||
}
|
||||
};
|
||||
self.write_modrm(target, result)?;
|
||||
|
||||
self.flags.zf = result.zero();
|
||||
self.flags.sf = result.msb();
|
||||
self.flags.pf = result.parity();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Rotate bits of data, pointed to by a [`ModRmTarget`].
|
||||
pub fn rotate(
|
||||
&mut self,
|
||||
target: ModRmTarget,
|
||||
rotations: usize, // how many rotations
|
||||
carry_usage: CarryUsage, // if carry should be included, or should just receive a copy
|
||||
rotation_direction: RotationDirection, // direction of rotation
|
||||
rotation_direction: Direction, // direction of rotation
|
||||
) -> Result<(), InterpreterError> {
|
||||
let mut bits = self.read_modrm(target)?.bits();
|
||||
match carry_usage {
|
||||
@@ -432,14 +466,14 @@ impl Computer {
|
||||
_ => {}
|
||||
}
|
||||
match rotation_direction {
|
||||
RotationDirection::Left => {
|
||||
Direction::Left => {
|
||||
bits.rotate_left(rotations);
|
||||
match carry_usage {
|
||||
CarryUsage::ReceiveCopy => self.flags.cf = bits[7],
|
||||
CarryUsage::FullRotation => self.flags.cf = bits.pop().unwrap(),
|
||||
}
|
||||
}
|
||||
RotationDirection::Right => {
|
||||
Direction::Right => {
|
||||
bits.rotate_right(rotations);
|
||||
match carry_usage {
|
||||
CarryUsage::ReceiveCopy => self.flags.cf = bits[0],
|
||||
@@ -451,7 +485,7 @@ impl Computer {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum RotationDirection {
|
||||
pub enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::{
|
||||
disasm::Disassembler,
|
||||
instructions::{Instruction, Mnemonic},
|
||||
interpreter::{
|
||||
computer::{CarryUsage, RotationDirection},
|
||||
interrupt::Mess1,
|
||||
computer::{CarryUsage, Direction},
|
||||
interrupt::{Mess1, Mess2},
|
||||
},
|
||||
operands::{Byte, ImmediateOperand, ModRmTarget, Word},
|
||||
};
|
||||
@@ -644,69 +644,83 @@ impl Interpreter {
|
||||
target,
|
||||
b.into(),
|
||||
CarryUsage::ReceiveCopy,
|
||||
RotationDirection::Left,
|
||||
Direction::Left,
|
||||
)?,
|
||||
Mnemonic::ROR_b(target, b) => self.computer.rotate(
|
||||
target,
|
||||
b.into(),
|
||||
CarryUsage::ReceiveCopy,
|
||||
RotationDirection::Right,
|
||||
Direction::Right,
|
||||
)?,
|
||||
Mnemonic::RCL_b(target, b) => self.computer.rotate(
|
||||
target,
|
||||
b.into(),
|
||||
CarryUsage::FullRotation,
|
||||
RotationDirection::Left,
|
||||
Direction::Left,
|
||||
)?,
|
||||
Mnemonic::RCR_b(target, b) => self.computer.rotate(
|
||||
target,
|
||||
b.into(),
|
||||
CarryUsage::FullRotation,
|
||||
RotationDirection::Right,
|
||||
Direction::Right,
|
||||
)?,
|
||||
Mnemonic::ROL_fromReg(target, reg) => self.computer.rotate(
|
||||
target,
|
||||
self.computer.regs.read(reg).into(),
|
||||
CarryUsage::ReceiveCopy,
|
||||
RotationDirection::Left,
|
||||
Direction::Left,
|
||||
)?,
|
||||
Mnemonic::ROR_fromReg(target, reg) => self.computer.rotate(
|
||||
target,
|
||||
self.computer.regs.read(reg).into(),
|
||||
CarryUsage::ReceiveCopy,
|
||||
RotationDirection::Right,
|
||||
Direction::Right,
|
||||
)?,
|
||||
Mnemonic::RCL_fromReg(target, reg) => self.computer.rotate(
|
||||
target,
|
||||
self.computer.regs.read(reg).into(),
|
||||
CarryUsage::FullRotation,
|
||||
RotationDirection::Left,
|
||||
Direction::Left,
|
||||
)?,
|
||||
Mnemonic::RCR_fromReg(target, reg) => self.computer.rotate(
|
||||
target,
|
||||
self.computer.regs.read(reg).into(),
|
||||
CarryUsage::FullRotation,
|
||||
RotationDirection::Right,
|
||||
Direction::Right,
|
||||
)?,
|
||||
|
||||
/*
|
||||
* Shfit
|
||||
*/
|
||||
Mnemonic::SHL_b(target, b) => self
|
||||
.computer
|
||||
.write_modrm(target, self.computer.read_modrm(target)? << b)?,
|
||||
Mnemonic::SHR_b(target, b) => self
|
||||
.computer
|
||||
.write_modrm(target, self.computer.read_modrm(target)? >> b)?,
|
||||
Mnemonic::SHL_b(target, b) => {
|
||||
self.computer.shift(target, b.into(), Direction::Left)?
|
||||
}
|
||||
Mnemonic::SHR_b(target, b) => {
|
||||
self.computer.shift(target, b.into(), Direction::Right)?;
|
||||
// For the SHR instruction, the OF flag is set to the most-significant bit of the original operand.
|
||||
self.computer.flags.of = self.computer.read_modrm(target)?.msb();
|
||||
}
|
||||
Mnemonic::SAR_b(_, _) => todo!(),
|
||||
Mnemonic::SHL_fromReg(target, reg) => self.computer.write_modrm(
|
||||
// Mnemonic::SAR_b(_, _) => {
|
||||
// For the SAR instruction, the OF flag is cleared for all 1-bit shifts.
|
||||
// if b == 1 {
|
||||
// self.flags.of = 0;
|
||||
// }
|
||||
// },
|
||||
Mnemonic::SHL_fromReg(target, reg) => self.computer.shift(
|
||||
target,
|
||||
self.computer.read_modrm(target)? << self.computer.regs.read(reg),
|
||||
self.computer.regs.read(reg).into(),
|
||||
Direction::Left,
|
||||
)?,
|
||||
Mnemonic::SHR_fromReg(target, reg) => self.computer.write_modrm(
|
||||
Mnemonic::SHR_fromReg(target, reg) => {
|
||||
self.computer.shift(
|
||||
target,
|
||||
self.computer.read_modrm(target)? >> self.computer.regs.read(reg),
|
||||
)?,
|
||||
self.computer.regs.read(reg).into(),
|
||||
Direction::Right,
|
||||
)?;
|
||||
// For the SHR instruction, the OF flag is set to the most-significant bit of the original operand.
|
||||
self.computer.flags.of = self.computer.read_modrm(target)?.msb();
|
||||
}
|
||||
Mnemonic::SAR_fromReg(_, _) => todo!(),
|
||||
|
||||
/*
|
||||
|
||||
@@ -282,10 +282,10 @@ impl Shl for ImmediateOperand {
|
||||
}
|
||||
}
|
||||
|
||||
impl Shl<u8> for ImmediateOperand {
|
||||
impl Shl<Word> for ImmediateOperand {
|
||||
type Output = Self;
|
||||
|
||||
fn shl(self, rhs: u8) -> Self::Output {
|
||||
fn shl(self, rhs: Word) -> Self::Output {
|
||||
match self {
|
||||
Self::Byte(b) => Self::Byte(b << rhs),
|
||||
Self::Word(w) => Self::Word(w << rhs),
|
||||
@@ -310,10 +310,10 @@ impl Shr for ImmediateOperand {
|
||||
}
|
||||
}
|
||||
|
||||
impl Shr<u8> for ImmediateOperand {
|
||||
impl Shr<Word> for ImmediateOperand {
|
||||
type Output = Self;
|
||||
|
||||
fn shr(self, rhs: u8) -> Self::Output {
|
||||
fn shr(self, rhs: Word) -> Self::Output {
|
||||
match self {
|
||||
Self::Byte(b) => Self::Byte(b >> rhs),
|
||||
Self::Word(w) => Self::Word(w >> rhs),
|
||||
|
||||
Reference in New Issue
Block a user