From f6447df90e4be1f8b85bcf65313eb21541ff3232 Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Wed, 2 Jul 2025 17:09:43 +0900 Subject: [PATCH] fix(interpreter): set flags correctly for shifts --- src/interpreter/computer.rs | 48 ++++++++++++++++++++++++---- src/interpreter/interpreter.rs | 58 +++++++++++++++++++++------------- src/operands.rs | 8 ++--- 3 files changed, 81 insertions(+), 33 deletions(-) diff --git a/src/interpreter/computer.rs b/src/interpreter/computer.rs index d62ee60..1d7e0ec 100644 --- a/src/interpreter/computer.rs +++ b/src/interpreter/computer.rs @@ -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, } diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index 68ab9ca..5b5c310 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -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!(), /* diff --git a/src/operands.rs b/src/operands.rs index 4ed9a62..0918aad 100644 --- a/src/operands.rs +++ b/src/operands.rs @@ -282,10 +282,10 @@ impl Shl for ImmediateOperand { } } -impl Shl for ImmediateOperand { +impl Shl 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 for ImmediateOperand { +impl Shr 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),