ft(interpreter): set flags for arithmatic operations
This commit is contained in:
@@ -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::*;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user