ft(interpreter): set flags for arithmatic operations

This commit is contained in:
2025-06-11 15:55:33 +09:00
parent c9bf8fdc46
commit 11a365a8b1
3 changed files with 47 additions and 17 deletions

View File

@@ -47,28 +47,52 @@ impl Computer {
/// Perform binary `dest` = `dest` - `src`. Sets flags. /// Perform binary `dest` = `dest` - `src`. Sets flags.
pub fn sub(&mut self, dest: ModRmTarget, src: Operand) { pub fn sub(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs - rhs; 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); self.op(op, flag_set, true, dest, src);
} }
/// Perform binary `dest` = `dest` | `src`. Sets flags. /// Perform binary `dest` = `dest` | `src`. Sets flags.
pub fn or(&mut self, dest: ModRmTarget, src: Operand) { pub fn or(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs | rhs; 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); self.op(op, flag_set, true, dest, src);
} }
/// Perform binary `dest` = `dest` & `src`. Sets flags. /// Perform binary `dest` = `dest` & `src`. Sets flags.
pub fn and(&mut self, dest: ModRmTarget, src: Operand) { pub fn and(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs & rhs; 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); self.op(op, flag_set, true, dest, src);
} }
/// Perform binary `dest` = `dest` ^ `src`. Sets flags. /// Perform binary `dest` = `dest` ^ `src`. Sets flags.
pub fn xor(&mut self, dest: ModRmTarget, src: Operand) { pub fn xor(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs ^ rhs; 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); self.op(op, flag_set, true, dest, src);
} }
@@ -76,7 +100,13 @@ impl Computer {
/// saving the result and only setting [`Self::flags`]. /// saving the result and only setting [`Self::flags`].
pub fn cmp(&mut self, dest: ModRmTarget, src: Operand) { pub fn cmp(&mut self, dest: ModRmTarget, src: Operand) {
let op: fn(Lhs, Rhs) -> Result = |lhs, rhs| lhs - rhs; 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); self.op(op, flag_set, false, dest, src);
} }
@@ -196,5 +226,5 @@ impl fmt::Display for Computer {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; // use super::*;
} }

View File

@@ -1,5 +1,5 @@
use core::fmt; use core::fmt;
use std::{fmt::Debug, process::exit, slice::Iter}; use std::{fmt::Debug, process::exit};
use crate::{ use crate::{
instructions::{Instruction, Mnemonic}, instructions::{Instruction, Mnemonic},
@@ -319,10 +319,10 @@ impl Interpreter {
/* /*
* Long jumps and calls * Long jumps and calls
*/ */
Mnemonic::JMP_p(ptr) => { Mnemonic::JMP_p(_) => {
todo!() todo!()
} }
Mnemonic::JMP_Mp(ptr) => { Mnemonic::JMP_Mp(_) => {
todo!() todo!()
} }
Mnemonic::JMP_Mod(target) => match target { Mnemonic::JMP_Mod(target) => match target {
@@ -491,7 +491,7 @@ impl Interpreter {
fn find_instruction<'a>( fn find_instruction<'a>(
items: &'a Vec<Instruction>, items: &'a Vec<Instruction>,
addr: usize, addr: usize,
) -> Option<InstructionPointer> { ) -> Option<InstructionPointer<'a>> {
items items
.iter() .iter()
.position(|i| i.start == addr) .position(|i| i.start == addr)

View File

@@ -27,8 +27,8 @@ pub enum ImmediateOperand {
} }
impl ImmediateOperand { impl ImmediateOperand {
// Sign-extend [`Self::Byte`] into [`Self::Word`]. /// Sign-extend [`Self::Byte`] into [`Self::Word`].
// Returns [`Self::Word`], if already a word. /// Returns [`Self::Word`], if already a word.
pub fn sign_extend(self) -> Self { pub fn sign_extend(self) -> Self {
match self { match self {
Self::Byte(_) => { Self::Byte(_) => {
@@ -42,8 +42,8 @@ impl ImmediateOperand {
} }
} }
// Interprets [`Self::Byte`] as [`Self::Word`]. /// Interprets [`Self::Byte`] as [`Self::Word`].
// Returns word, if already a [`Self::Word`]. /// Returns word, if already a [`Self::Word`].
pub fn as_word(self) -> Self { pub fn as_word(self) -> Self {
match self { match self {
Self::Byte(b) => Self::Word(b as Word), 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 { pub fn flip_sign(self) -> Self {
match self { match self {
Self::Byte(b) => Self::Byte(b ^ (1 << 7)), 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 { pub fn zero(&self) -> bool {
match self { match self {
Self::Byte(byte) => return *byte == 0, 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 { pub fn parity(&self) -> bool {
match self { match self {
Self::Byte(byte) => return byte.count_ones() % 2 != 0, Self::Byte(byte) => return byte.count_ones() % 2 != 0,