ft(interpreter): impl shift and rotate
This commit is contained in:
@@ -798,19 +798,19 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 2
|
// Group 2
|
||||||
0xD0 => {
|
0xD0 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(None)?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
|
||||||
Self::modrm_reg_to_grp2_1(reg, target)?
|
Self::modrm_reg_to_grp2_1(reg, target)?
|
||||||
}
|
}
|
||||||
0xD1 => {
|
0xD1 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(None)?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
Self::modrm_reg_to_grp2_1(reg, target)?
|
Self::modrm_reg_to_grp2_1(reg, target)?
|
||||||
}
|
}
|
||||||
0xD2 => {
|
0xD2 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(None)?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
|
||||||
Self::modrm_reg_to_grp2_cl(reg, target)?
|
Self::modrm_reg_to_grp2_cl(reg, target)?
|
||||||
}
|
}
|
||||||
0xD3 => {
|
0xD3 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(None)?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
Self::modrm_reg_to_grp2_cl(reg, target)?
|
Self::modrm_reg_to_grp2_cl(reg, target)?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -235,6 +235,47 @@ impl Computer {
|
|||||||
ModRmTarget::Register(reg) => self.regs.read(reg),
|
ModRmTarget::Register(reg) => self.regs.read(reg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
let mut bits = self.read_modrm(target).bits();
|
||||||
|
match carry_usage {
|
||||||
|
CarryUsage::FullRotation => bits.push(self.flags.cf),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
match rotation_direction {
|
||||||
|
RotationDirection::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 => {
|
||||||
|
bits.rotate_right(rotations);
|
||||||
|
match carry_usage {
|
||||||
|
CarryUsage::ReceiveCopy => self.flags.cf = bits[0],
|
||||||
|
CarryUsage::FullRotation => self.flags.cf = bits.pop().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.write_modrm(target, ImmediateOperand::from(bits));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum RotationDirection {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum CarryUsage {
|
||||||
|
ReceiveCopy, // dont add when rotating, but copy bit that was rotated to other side
|
||||||
|
FullRotation, // include in full rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Computer {
|
impl fmt::Display for Computer {
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ use std::{fmt::Debug, process::exit};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instructions::{Instruction, Mnemonic},
|
instructions::{Instruction, Mnemonic},
|
||||||
interpreter::{interrupt::Mess1, memory::Memory},
|
interpreter::{
|
||||||
|
computer::{CarryUsage, RotationDirection},
|
||||||
|
interrupt::Mess1,
|
||||||
|
memory::Memory,
|
||||||
|
},
|
||||||
operands::{Byte, ImmediateOperand, ModRmTarget, Word},
|
operands::{Byte, ImmediateOperand, ModRmTarget, Word},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -597,8 +601,76 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shift and Rotate
|
* Rotate
|
||||||
*/
|
*/
|
||||||
|
Mnemonic::ROL_b(target, b) => self.computer.rotate(
|
||||||
|
target,
|
||||||
|
b.into(),
|
||||||
|
CarryUsage::ReceiveCopy,
|
||||||
|
RotationDirection::Left,
|
||||||
|
),
|
||||||
|
Mnemonic::ROR_b(target, b) => self.computer.rotate(
|
||||||
|
target,
|
||||||
|
b.into(),
|
||||||
|
CarryUsage::ReceiveCopy,
|
||||||
|
RotationDirection::Right,
|
||||||
|
),
|
||||||
|
Mnemonic::RCL_b(target, b) => self.computer.rotate(
|
||||||
|
target,
|
||||||
|
b.into(),
|
||||||
|
CarryUsage::FullRotation,
|
||||||
|
RotationDirection::Left,
|
||||||
|
),
|
||||||
|
Mnemonic::RCR_b(target, b) => self.computer.rotate(
|
||||||
|
target,
|
||||||
|
b.into(),
|
||||||
|
CarryUsage::FullRotation,
|
||||||
|
RotationDirection::Right,
|
||||||
|
),
|
||||||
|
Mnemonic::ROL_fromReg(target, reg) => self.computer.rotate(
|
||||||
|
target,
|
||||||
|
self.computer.regs.read(reg).into(),
|
||||||
|
CarryUsage::ReceiveCopy,
|
||||||
|
RotationDirection::Left,
|
||||||
|
),
|
||||||
|
Mnemonic::ROR_fromReg(target, reg) => self.computer.rotate(
|
||||||
|
target,
|
||||||
|
self.computer.regs.read(reg).into(),
|
||||||
|
CarryUsage::ReceiveCopy,
|
||||||
|
RotationDirection::Right,
|
||||||
|
),
|
||||||
|
Mnemonic::RCL_fromReg(target, reg) => self.computer.rotate(
|
||||||
|
target,
|
||||||
|
self.computer.regs.read(reg).into(),
|
||||||
|
CarryUsage::FullRotation,
|
||||||
|
RotationDirection::Left,
|
||||||
|
),
|
||||||
|
Mnemonic::RCR_fromReg(target, reg) => self.computer.rotate(
|
||||||
|
target,
|
||||||
|
self.computer.regs.read(reg).into(),
|
||||||
|
CarryUsage::FullRotation,
|
||||||
|
RotationDirection::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::SAR_b(target, b) => todo!(),
|
||||||
|
Mnemonic::SHL_fromReg(target, reg) => self.computer.write_modrm(
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
Mnemonic::SAR_fromReg(target, reg) => todo!(),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IN
|
* IN
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::register::SegmentRegister;
|
|||||||
|
|
||||||
use crate::{disasm::DisasmError, register::Register};
|
use crate::{disasm::DisasmError, register::Register};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Sub};
|
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Shl, Shr, Sub};
|
||||||
|
|
||||||
pub type Byte = u8; // b
|
pub type Byte = u8; // b
|
||||||
pub type IByte = i8; // used for displacements of memory access
|
pub type IByte = i8; // used for displacements of memory access
|
||||||
@@ -28,6 +28,14 @@ pub enum ImmediateOperand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ImmediateOperand {
|
impl ImmediateOperand {
|
||||||
|
/// Return bits of internal value.
|
||||||
|
pub fn bits(self) -> Vec<bool> {
|
||||||
|
match self {
|
||||||
|
ImmediateOperand::Byte(b) => (0..8).map(|i| (b & (1 << i)) != 0).collect(),
|
||||||
|
ImmediateOperand::Word(w) => (0..8).map(|i| (w & (1 << i)) != 0).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 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 {
|
||||||
@@ -98,6 +106,26 @@ impl ImmediateOperand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vec<bool>> for ImmediateOperand {
|
||||||
|
fn from(bits: Vec<bool>) -> Self {
|
||||||
|
if bits.len() == 8 {
|
||||||
|
let val = bits
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.fold(0, |acc, (i, &bit)| acc | ((bit as u8) << i));
|
||||||
|
Self::Byte(val)
|
||||||
|
} else if bits.len() == 16 {
|
||||||
|
let val = bits
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.fold(0, |acc, (i, &bit)| acc | ((bit as u16) << i));
|
||||||
|
Self::Word(val)
|
||||||
|
} else {
|
||||||
|
panic!("Invalid bit length");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Byte> for ImmediateOperand {
|
impl From<Byte> for ImmediateOperand {
|
||||||
fn from(value: Byte) -> Self {
|
fn from(value: Byte) -> Self {
|
||||||
Self::Byte(value)
|
Self::Byte(value)
|
||||||
@@ -252,6 +280,62 @@ impl Mul for ImmediateOperand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Shl for ImmediateOperand {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn shl(self, rhs: Self) -> Self::Output {
|
||||||
|
match self {
|
||||||
|
Self::Byte(b) => match rhs {
|
||||||
|
ImmediateOperand::Byte(sb) => Self::Byte(b << sb),
|
||||||
|
ImmediateOperand::Word(sw) => Self::Byte(b << sw),
|
||||||
|
},
|
||||||
|
Self::Word(w) => match rhs {
|
||||||
|
ImmediateOperand::Byte(sb) => Self::Word(w << sb),
|
||||||
|
ImmediateOperand::Word(sw) => Self::Word(w << sw),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shl<u8> for ImmediateOperand {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn shl(self, rhs: u8) -> Self::Output {
|
||||||
|
match self {
|
||||||
|
Self::Byte(b) => Self::Byte(b << rhs),
|
||||||
|
Self::Word(w) => Self::Word(w << rhs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shr for ImmediateOperand {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn shr(self, rhs: Self) -> Self::Output {
|
||||||
|
match self {
|
||||||
|
Self::Byte(b) => match rhs {
|
||||||
|
ImmediateOperand::Byte(sb) => Self::Byte(b >> sb),
|
||||||
|
ImmediateOperand::Word(sw) => Self::Byte(b >> sw),
|
||||||
|
},
|
||||||
|
Self::Word(w) => match rhs {
|
||||||
|
ImmediateOperand::Byte(sb) => Self::Word(w >> sb),
|
||||||
|
ImmediateOperand::Word(sw) => Self::Word(w >> sw),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shr<u8> for ImmediateOperand {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn shr(self, rhs: u8) -> Self::Output {
|
||||||
|
match self {
|
||||||
|
Self::Byte(b) => Self::Byte(b >> rhs),
|
||||||
|
Self::Word(w) => Self::Word(w >> rhs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Div for ImmediateOperand {
|
impl Div for ImmediateOperand {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user