fix(interpreter): set flags correctly for shifts

This commit is contained in:
2025-07-02 17:09:43 +09:00
parent 3ce0a461ca
commit f6447df90e
3 changed files with 81 additions and 33 deletions

View File

@@ -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,
} }

View File

@@ -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!(),
/* /*

View File

@@ -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),