From 11a365a8b1a6b8586a6fb2d860d53a4ecfa9e58a Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Wed, 11 Jun 2025 15:55:33 +0900 Subject: [PATCH] ft(interpreter): set flags for arithmatic operations --- src/interpreter/computer.rs | 42 +++++++++++++++++++++++++++++----- src/interpreter/interpreter.rs | 8 +++---- src/operands.rs | 14 ++++++------ 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/interpreter/computer.rs b/src/interpreter/computer.rs index 635a006..cd99062 100644 --- a/src/interpreter/computer.rs +++ b/src/interpreter/computer.rs @@ -47,28 +47,52 @@ impl Computer { /// Perform binary `dest` = `dest` - `src`. Sets flags. pub fn sub(&mut self, dest: ModRmTarget, src: Operand) { let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs - rhs; - let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| (); + let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |flags, result, lhs, rhs| { + flags.cf = lhs < rhs; + flags.of = lhs.msb() != rhs.msb() && lhs.msb() != result.msb(); + flags.zf = result.zero(); + flags.sf = result.msb(); + flags.pf = result.parity(); + }; self.op(op, flag_set, true, dest, src); } /// Perform binary `dest` = `dest` | `src`. Sets flags. pub fn or(&mut self, dest: ModRmTarget, src: Operand) { let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs | rhs; - let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| (); + let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |flags, result, _, _| { + flags.cf = false; + flags.of = false; + flags.zf = result.zero(); + flags.sf = result.msb(); + flags.pf = result.parity(); + }; self.op(op, flag_set, true, dest, src); } /// Perform binary `dest` = `dest` & `src`. Sets flags. pub fn and(&mut self, dest: ModRmTarget, src: Operand) { let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs & rhs; - let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| (); + let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |flags, result, _, _rhs| { + flags.cf = false; + flags.of = false; + flags.zf = result.zero(); + flags.sf = result.msb(); + flags.pf = result.parity(); + }; self.op(op, flag_set, true, dest, src); } /// Perform binary `dest` = `dest` ^ `src`. Sets flags. pub fn xor(&mut self, dest: ModRmTarget, src: Operand) { let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs ^ rhs; - let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| (); + let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |flags, result, _, _| { + flags.cf = false; + flags.of = false; + flags.zf = result.zero(); + flags.sf = result.msb(); + flags.pf = result.parity(); + }; self.op(op, flag_set, true, dest, src); } @@ -76,7 +100,13 @@ impl Computer { /// saving the result and only setting [`Self::flags`]. pub fn cmp(&mut self, dest: ModRmTarget, src: Operand) { let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs - rhs; - let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |_, _, _, _| (); + let flag_set: fn(&mut Flags, Result, Lhs, Rhs) = |flags, result, lhs, rhs| { + flags.cf = lhs < rhs; + flags.of = lhs.msb() != rhs.msb() && lhs.msb() != result.msb(); + flags.zf = result.zero(); + flags.sf = result.msb(); + flags.pf = result.parity(); + }; self.op(op, flag_set, false, dest, src); } @@ -196,5 +226,5 @@ impl fmt::Display for Computer { #[cfg(test)] mod tests { - use super::*; + // use super::*; } diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index 76e71f9..2273277 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -1,5 +1,5 @@ use core::fmt; -use std::{fmt::Debug, process::exit, slice::Iter}; +use std::{fmt::Debug, process::exit}; use crate::{ instructions::{Instruction, Mnemonic}, @@ -319,10 +319,10 @@ impl Interpreter { /* * Long jumps and calls */ - Mnemonic::JMP_p(ptr) => { + Mnemonic::JMP_p(_) => { todo!() } - Mnemonic::JMP_Mp(ptr) => { + Mnemonic::JMP_Mp(_) => { todo!() } Mnemonic::JMP_Mod(target) => match target { @@ -491,7 +491,7 @@ impl Interpreter { fn find_instruction<'a>( items: &'a Vec, addr: usize, - ) -> Option { + ) -> Option> { items .iter() .position(|i| i.start == addr) diff --git a/src/operands.rs b/src/operands.rs index aee0a72..96e8059 100644 --- a/src/operands.rs +++ b/src/operands.rs @@ -27,8 +27,8 @@ pub enum ImmediateOperand { } impl ImmediateOperand { - // Sign-extend [`Self::Byte`] into [`Self::Word`]. - // Returns [`Self::Word`], if already a word. + /// Sign-extend [`Self::Byte`] into [`Self::Word`]. + /// Returns [`Self::Word`], if already a word. pub fn sign_extend(self) -> Self { match self { Self::Byte(_) => { @@ -42,8 +42,8 @@ impl ImmediateOperand { } } - // Interprets [`Self::Byte`] as [`Self::Word`]. - // Returns word, if already a [`Self::Word`]. + /// Interprets [`Self::Byte`] as [`Self::Word`]. + /// Returns word, if already a [`Self::Word`]. pub fn as_word(self) -> Self { match self { Self::Byte(b) => Self::Word(b as Word), @@ -51,7 +51,7 @@ impl ImmediateOperand { } } - // Flip most significant bit. + /// Flip most significant bit. pub fn flip_sign(self) -> Self { match self { Self::Byte(b) => Self::Byte(b ^ (1 << 7)), @@ -59,7 +59,7 @@ impl ImmediateOperand { } } - // Check if value is zero. + /// Check if inner value is zero. pub fn zero(&self) -> bool { match self { Self::Byte(byte) => return *byte == 0, @@ -67,7 +67,7 @@ impl ImmediateOperand { } } - // Check if leasy significant byte has even number of 1's. + /// Check if leasy significant byte has even number of 1's. pub fn parity(&self) -> bool { match self { Self::Byte(byte) => return byte.count_ones() % 2 != 0,