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)
}
/// 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
rotations: usize, // how many rotations
carry_usage: CarryUsage, // if carry should be included, or should just receive a copy
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,
}

View File

@@ -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),
)?,
Mnemonic::SHR_fromReg(target, reg) => self.computer.write_modrm(
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.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!(),
/*

View File

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