fix(interpreter): set flags correctly for shifts
This commit is contained in:
@@ -418,13 +418,47 @@ impl Computer {
|
|||||||
Ok(imm)
|
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(
|
pub fn rotate(
|
||||||
&mut self,
|
&mut self,
|
||||||
target: ModRmTarget,
|
target: ModRmTarget,
|
||||||
rotations: usize, // how many rotations
|
rotations: usize, // how many rotations
|
||||||
carry_usage: CarryUsage, // if carry should be included, or should just receive a copy
|
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> {
|
) -> Result<(), InterpreterError> {
|
||||||
let mut bits = self.read_modrm(target)?.bits();
|
let mut bits = self.read_modrm(target)?.bits();
|
||||||
match carry_usage {
|
match carry_usage {
|
||||||
@@ -432,14 +466,14 @@ impl Computer {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
match rotation_direction {
|
match rotation_direction {
|
||||||
RotationDirection::Left => {
|
Direction::Left => {
|
||||||
bits.rotate_left(rotations);
|
bits.rotate_left(rotations);
|
||||||
match carry_usage {
|
match carry_usage {
|
||||||
CarryUsage::ReceiveCopy => self.flags.cf = bits[7],
|
CarryUsage::ReceiveCopy => self.flags.cf = bits[7],
|
||||||
CarryUsage::FullRotation => self.flags.cf = bits.pop().unwrap(),
|
CarryUsage::FullRotation => self.flags.cf = bits.pop().unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RotationDirection::Right => {
|
Direction::Right => {
|
||||||
bits.rotate_right(rotations);
|
bits.rotate_right(rotations);
|
||||||
match carry_usage {
|
match carry_usage {
|
||||||
CarryUsage::ReceiveCopy => self.flags.cf = bits[0],
|
CarryUsage::ReceiveCopy => self.flags.cf = bits[0],
|
||||||
@@ -451,7 +485,7 @@ impl Computer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum RotationDirection {
|
pub enum Direction {
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use crate::{
|
|||||||
disasm::Disassembler,
|
disasm::Disassembler,
|
||||||
instructions::{Instruction, Mnemonic},
|
instructions::{Instruction, Mnemonic},
|
||||||
interpreter::{
|
interpreter::{
|
||||||
computer::{CarryUsage, RotationDirection},
|
computer::{CarryUsage, Direction},
|
||||||
interrupt::Mess1,
|
interrupt::{Mess1, Mess2},
|
||||||
},
|
},
|
||||||
operands::{Byte, ImmediateOperand, ModRmTarget, Word},
|
operands::{Byte, ImmediateOperand, ModRmTarget, Word},
|
||||||
};
|
};
|
||||||
@@ -644,69 +644,83 @@ impl Interpreter {
|
|||||||
target,
|
target,
|
||||||
b.into(),
|
b.into(),
|
||||||
CarryUsage::ReceiveCopy,
|
CarryUsage::ReceiveCopy,
|
||||||
RotationDirection::Left,
|
Direction::Left,
|
||||||
)?,
|
)?,
|
||||||
Mnemonic::ROR_b(target, b) => self.computer.rotate(
|
Mnemonic::ROR_b(target, b) => self.computer.rotate(
|
||||||
target,
|
target,
|
||||||
b.into(),
|
b.into(),
|
||||||
CarryUsage::ReceiveCopy,
|
CarryUsage::ReceiveCopy,
|
||||||
RotationDirection::Right,
|
Direction::Right,
|
||||||
)?,
|
)?,
|
||||||
Mnemonic::RCL_b(target, b) => self.computer.rotate(
|
Mnemonic::RCL_b(target, b) => self.computer.rotate(
|
||||||
target,
|
target,
|
||||||
b.into(),
|
b.into(),
|
||||||
CarryUsage::FullRotation,
|
CarryUsage::FullRotation,
|
||||||
RotationDirection::Left,
|
Direction::Left,
|
||||||
)?,
|
)?,
|
||||||
Mnemonic::RCR_b(target, b) => self.computer.rotate(
|
Mnemonic::RCR_b(target, b) => self.computer.rotate(
|
||||||
target,
|
target,
|
||||||
b.into(),
|
b.into(),
|
||||||
CarryUsage::FullRotation,
|
CarryUsage::FullRotation,
|
||||||
RotationDirection::Right,
|
Direction::Right,
|
||||||
)?,
|
)?,
|
||||||
Mnemonic::ROL_fromReg(target, reg) => self.computer.rotate(
|
Mnemonic::ROL_fromReg(target, reg) => self.computer.rotate(
|
||||||
target,
|
target,
|
||||||
self.computer.regs.read(reg).into(),
|
self.computer.regs.read(reg).into(),
|
||||||
CarryUsage::ReceiveCopy,
|
CarryUsage::ReceiveCopy,
|
||||||
RotationDirection::Left,
|
Direction::Left,
|
||||||
)?,
|
)?,
|
||||||
Mnemonic::ROR_fromReg(target, reg) => self.computer.rotate(
|
Mnemonic::ROR_fromReg(target, reg) => self.computer.rotate(
|
||||||
target,
|
target,
|
||||||
self.computer.regs.read(reg).into(),
|
self.computer.regs.read(reg).into(),
|
||||||
CarryUsage::ReceiveCopy,
|
CarryUsage::ReceiveCopy,
|
||||||
RotationDirection::Right,
|
Direction::Right,
|
||||||
)?,
|
)?,
|
||||||
Mnemonic::RCL_fromReg(target, reg) => self.computer.rotate(
|
Mnemonic::RCL_fromReg(target, reg) => self.computer.rotate(
|
||||||
target,
|
target,
|
||||||
self.computer.regs.read(reg).into(),
|
self.computer.regs.read(reg).into(),
|
||||||
CarryUsage::FullRotation,
|
CarryUsage::FullRotation,
|
||||||
RotationDirection::Left,
|
Direction::Left,
|
||||||
)?,
|
)?,
|
||||||
Mnemonic::RCR_fromReg(target, reg) => self.computer.rotate(
|
Mnemonic::RCR_fromReg(target, reg) => self.computer.rotate(
|
||||||
target,
|
target,
|
||||||
self.computer.regs.read(reg).into(),
|
self.computer.regs.read(reg).into(),
|
||||||
CarryUsage::FullRotation,
|
CarryUsage::FullRotation,
|
||||||
RotationDirection::Right,
|
Direction::Right,
|
||||||
)?,
|
)?,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shfit
|
* Shfit
|
||||||
*/
|
*/
|
||||||
Mnemonic::SHL_b(target, b) => self
|
Mnemonic::SHL_b(target, b) => {
|
||||||
.computer
|
self.computer.shift(target, b.into(), Direction::Left)?
|
||||||
.write_modrm(target, self.computer.read_modrm(target)? << b)?,
|
}
|
||||||
Mnemonic::SHR_b(target, b) => self
|
Mnemonic::SHR_b(target, b) => {
|
||||||
.computer
|
self.computer.shift(target, b.into(), Direction::Right)?;
|
||||||
.write_modrm(target, self.computer.read_modrm(target)? >> b)?,
|
// 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::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,
|
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(
|
|
||||||
target,
|
|
||||||
self.computer.read_modrm(target)? >> self.computer.regs.read(reg),
|
|
||||||
)?,
|
)?,
|
||||||
|
Mnemonic::SHR_fromReg(target, reg) => {
|
||||||
|
self.computer.shift(
|
||||||
|
target,
|
||||||
|
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!(),
|
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;
|
type Output = Self;
|
||||||
|
|
||||||
fn shl(self, rhs: u8) -> Self::Output {
|
fn shl(self, rhs: Word) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
Self::Byte(b) => Self::Byte(b << rhs),
|
Self::Byte(b) => Self::Byte(b << rhs),
|
||||||
Self::Word(w) => Self::Word(w << 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;
|
type Output = Self;
|
||||||
|
|
||||||
fn shr(self, rhs: u8) -> Self::Output {
|
fn shr(self, rhs: Word) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
Self::Byte(b) => Self::Byte(b >> rhs),
|
Self::Byte(b) => Self::Byte(b >> rhs),
|
||||||
Self::Word(w) => Self::Word(w >> rhs),
|
Self::Word(w) => Self::Word(w >> rhs),
|
||||||
|
|||||||
Reference in New Issue
Block a user