ft(interpreter): impl SAR
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Args,
|
Args,
|
||||||
@@ -463,29 +462,59 @@ impl Computer {
|
|||||||
Ok(imm)
|
Ok(imm)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shift bits of data, pointed to by a [`ModRMTarget`]
|
/// Shift bits of data, pointed to by a [`ModRMTarget`].
|
||||||
|
/// SHL: Direction::Left, false
|
||||||
|
/// SHR: Direction::Right, false
|
||||||
|
/// SAR: Direction::Right, true
|
||||||
pub fn shift(
|
pub fn shift(
|
||||||
&mut self,
|
&mut self,
|
||||||
target: ModRmTarget,
|
target: ModRmTarget,
|
||||||
shift: ImmediateOperand, // how many shifts
|
shift: ImmediateOperand, // how many shifts
|
||||||
shift_direction: Direction, // direction of shifting
|
shift_direction: Direction, // direction of shifting
|
||||||
|
arithmetic_right: bool, // arithmetic shift yes/no
|
||||||
) -> Result<(), InterpreterError> {
|
) -> Result<(), InterpreterError> {
|
||||||
let result = match shift_direction {
|
let result = match shift_direction {
|
||||||
Direction::Left => {
|
Direction::Left => {
|
||||||
let imm = self.read_modrm(target)? << (shift - 1);
|
let imm = self.read_modrm(target)? << (shift - 1);
|
||||||
|
|
||||||
|
// CF is last bit, which is shifted out
|
||||||
self.flags.cf = imm.msb();
|
self.flags.cf = imm.msb();
|
||||||
let result = imm << 1;
|
let result = imm << 1;
|
||||||
|
|
||||||
|
// OF only affected for 1 bit shifts
|
||||||
|
if shift == 1_u8.into() {
|
||||||
self.flags.of = if result.msb() == self.flags.cf {
|
self.flags.of = if result.msb() == self.flags.cf {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
Direction::Right => {
|
Direction::Right => {
|
||||||
let imm = self.read_modrm(target)? >> (shift - 1);
|
let target_val = self.read_modrm(target)?;
|
||||||
self.flags.cf = imm.msb();
|
let imm = target_val >> (shift - 1);
|
||||||
imm >> 1
|
|
||||||
|
// OF only affected for 1 bit shifts
|
||||||
|
if shift == 1_u8.into() {
|
||||||
|
if arithmetic_right {
|
||||||
|
self.flags.of = false;
|
||||||
|
} else {
|
||||||
|
self.flags.of = target_val.msb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CF is last bit, which is shifted out
|
||||||
|
self.flags.cf = imm.lsb();
|
||||||
|
let result = imm >> 1;
|
||||||
|
|
||||||
|
// preserve sign for SAR
|
||||||
|
if arithmetic_right {
|
||||||
|
result.set_sign(imm.msb())
|
||||||
|
} else {
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.write_modrm(target, result)?;
|
self.write_modrm(target, result)?;
|
||||||
|
|||||||
@@ -770,35 +770,37 @@ impl Interpreter {
|
|||||||
* Shfit
|
* Shfit
|
||||||
*/
|
*/
|
||||||
Mnemonic::SHL_b(target, b) => {
|
Mnemonic::SHL_b(target, b) => {
|
||||||
self.computer.shift(target, b.into(), Direction::Left)?
|
self.computer
|
||||||
|
.shift(target, b.into(), Direction::Left, false)?
|
||||||
}
|
}
|
||||||
Mnemonic::SHR_b(target, b) => {
|
Mnemonic::SHR_b(target, b) => {
|
||||||
self.computer.shift(target, b.into(), Direction::Right)?;
|
self.computer
|
||||||
// For the SHR instruction, the OF flag is set to the most-significant bit of the original operand.
|
.shift(target, b.into(), Direction::Right, false)?;
|
||||||
self.computer.flags.of = self.computer.read_modrm(target)?.msb();
|
|
||||||
}
|
}
|
||||||
Mnemonic::SAR_b(_, _) => todo!(),
|
Mnemonic::SAR_b(target, b) => {
|
||||||
// Mnemonic::SAR_b(_, _) => {
|
self.computer
|
||||||
// For the SAR instruction, the OF flag is cleared for all 1-bit shifts.
|
.shift(target, b.into(), Direction::Right, true)?
|
||||||
// if b == 1 {
|
}
|
||||||
// self.flags.of = 0;
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
Mnemonic::SHL_fromReg(target, reg) => self.computer.shift(
|
Mnemonic::SHL_fromReg(target, reg) => self.computer.shift(
|
||||||
target,
|
target,
|
||||||
self.computer.regs.read(reg).into(),
|
self.computer.regs.read(reg).into(),
|
||||||
Direction::Left,
|
Direction::Left,
|
||||||
|
false,
|
||||||
)?,
|
)?,
|
||||||
Mnemonic::SHR_fromReg(target, reg) => {
|
Mnemonic::SHR_fromReg(target, reg) => self.computer.shift(
|
||||||
self.computer.shift(
|
|
||||||
target,
|
target,
|
||||||
self.computer.regs.read(reg).into(),
|
self.computer.regs.read(reg).into(),
|
||||||
Direction::Right,
|
Direction::Right,
|
||||||
)?;
|
false,
|
||||||
// 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(target, reg) => self.computer.shift(
|
||||||
Mnemonic::SAR_fromReg(_, _) => todo!(),
|
target,
|
||||||
|
self.computer.regs.read(reg).into(),
|
||||||
|
Direction::Right,
|
||||||
|
true,
|
||||||
|
)?,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IN
|
* IN
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use crate::{disasm::DisasmError, register::Register};
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Shl, Shr, Sub},
|
ops::{Add, BitAnd, BitOr, BitXor, Div, Not, Shl, Shr, Sub},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type Byte = u8; // b
|
pub type Byte = u8; // b
|
||||||
@@ -72,6 +72,20 @@ impl ImmediateOperand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets or removes sign.
|
||||||
|
pub fn set_sign(self, sign: bool) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Byte(b) => {
|
||||||
|
let msb = 1 << 7;
|
||||||
|
Self::Byte(if sign { b | msb } else { b & !msb })
|
||||||
|
}
|
||||||
|
Self::Word(w) => {
|
||||||
|
let msb = 1 << 15;
|
||||||
|
Self::Word(if sign { w | msb } else { w & !msb })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if inner value is zero.
|
/// Check if inner value is zero.
|
||||||
pub fn zero(&self) -> bool {
|
pub fn zero(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
@@ -92,7 +106,7 @@ impl ImmediateOperand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if least significant bit is set.
|
/// Check if least significant bit is set.
|
||||||
pub fn _lsb(&self) -> bool {
|
pub fn lsb(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Byte(byte) => return byte & 1 == 1,
|
Self::Byte(byte) => return byte & 1 == 1,
|
||||||
Self::Word(word) => return word & 1 == 1,
|
Self::Word(word) => return word & 1 == 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user