chore: Rename Operand -> ImmediateOperand
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::aout::Aout;
|
use crate::aout::Aout;
|
||||||
use crate::operands::{
|
use crate::operands::{
|
||||||
Byte, DWord, Displacement, IByte, IWord, MemoryIndex, ModRmTarget, Operand, Pointer16,
|
Byte, DWord, Displacement, IByte, IWord, ImmediateOperand, MemoryIndex, ModRmTarget, Pointer16,
|
||||||
Pointer32, Word,
|
Pointer32, Word,
|
||||||
};
|
};
|
||||||
use crate::register::{Register, RegisterId, SegmentRegister};
|
use crate::register::{Register, RegisterId, SegmentRegister};
|
||||||
@@ -238,7 +238,7 @@ impl Disassembler {
|
|||||||
/// or even mnemonic in the group-type instructions.
|
/// or even mnemonic in the group-type instructions.
|
||||||
fn parse_modrm_byte(
|
fn parse_modrm_byte(
|
||||||
&mut self,
|
&mut self,
|
||||||
register_width: Operand,
|
register_width: ImmediateOperand,
|
||||||
) -> Result<(ModRmTarget, RegisterId), DisasmError> {
|
) -> Result<(ModRmTarget, RegisterId), DisasmError> {
|
||||||
let modrm = self.parse_byte()?;
|
let modrm = self.parse_byte()?;
|
||||||
|
|
||||||
@@ -291,9 +291,11 @@ impl Disassembler {
|
|||||||
"ModRM selected Register to Register: ({rm:#b}) to/from RegID ({reg:#b})"
|
"ModRM selected Register to Register: ({rm:#b}) to/from RegID ({reg:#b})"
|
||||||
);
|
);
|
||||||
let target = match register_width {
|
let target = match register_width {
|
||||||
Operand::Byte(_) => ModRmTarget::Register(Register::by_id(Operand::Byte(rm))?),
|
ImmediateOperand::Byte(_) => {
|
||||||
Operand::Word(_) => {
|
ModRmTarget::Register(Register::by_id(ImmediateOperand::Byte(rm))?)
|
||||||
ModRmTarget::Register(Register::by_id(Operand::Word(rm as Word))?)
|
}
|
||||||
|
ImmediateOperand::Word(_) => {
|
||||||
|
ModRmTarget::Register(Register::by_id(ImmediateOperand::Word(rm as Word))?)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return Ok((target, reg));
|
return Ok((target, reg));
|
||||||
@@ -355,10 +357,10 @@ impl Disassembler {
|
|||||||
fn modrm_reg_to_grp1(
|
fn modrm_reg_to_grp1(
|
||||||
reg: u8,
|
reg: u8,
|
||||||
target: ModRmTarget,
|
target: ModRmTarget,
|
||||||
instruction_width: Operand,
|
instruction_width: ImmediateOperand,
|
||||||
) -> Result<Mnemonic, DisasmError> {
|
) -> Result<Mnemonic, DisasmError> {
|
||||||
match instruction_width {
|
match instruction_width {
|
||||||
Operand::Byte(b) => match reg {
|
ImmediateOperand::Byte(b) => match reg {
|
||||||
0b000 => Ok(Mnemonic::ADD_Ib(target, b)),
|
0b000 => Ok(Mnemonic::ADD_Ib(target, b)),
|
||||||
0b001 => Ok(Mnemonic::OR_Ib(target, b)),
|
0b001 => Ok(Mnemonic::OR_Ib(target, b)),
|
||||||
0b010 => Ok(Mnemonic::ADC_Ib(target, b)),
|
0b010 => Ok(Mnemonic::ADC_Ib(target, b)),
|
||||||
@@ -369,7 +371,7 @@ impl Disassembler {
|
|||||||
0b111 => Ok(Mnemonic::CMP_Ib(target, b)),
|
0b111 => Ok(Mnemonic::CMP_Ib(target, b)),
|
||||||
_ => return Err(DisasmError::IllegalGroupMnemonic(1, reg)),
|
_ => return Err(DisasmError::IllegalGroupMnemonic(1, reg)),
|
||||||
},
|
},
|
||||||
Operand::Word(w) => match reg {
|
ImmediateOperand::Word(w) => match reg {
|
||||||
0b000 => Ok(Mnemonic::ADD_Iv(target, w)),
|
0b000 => Ok(Mnemonic::ADD_Iv(target, w)),
|
||||||
0b001 => Ok(Mnemonic::OR_Iv(target, w)),
|
0b001 => Ok(Mnemonic::OR_Iv(target, w)),
|
||||||
0b010 => Ok(Mnemonic::ADC_Iv(target, w)),
|
0b010 => Ok(Mnemonic::ADC_Iv(target, w)),
|
||||||
@@ -428,12 +430,12 @@ impl Disassembler {
|
|||||||
&mut self,
|
&mut self,
|
||||||
reg: u8,
|
reg: u8,
|
||||||
target: ModRmTarget,
|
target: ModRmTarget,
|
||||||
width: Operand,
|
width: ImmediateOperand,
|
||||||
) -> Result<Mnemonic, DisasmError> {
|
) -> Result<Mnemonic, DisasmError> {
|
||||||
match reg {
|
match reg {
|
||||||
0b000 => match width {
|
0b000 => match width {
|
||||||
Operand::Byte(_) => Ok(Mnemonic::TEST_Ib(target, self.parse_byte()?)),
|
ImmediateOperand::Byte(_) => Ok(Mnemonic::TEST_Ib(target, self.parse_byte()?)),
|
||||||
Operand::Word(_) => Ok(Mnemonic::TEST_Iv(target, self.parse_word()?)),
|
ImmediateOperand::Word(_) => Ok(Mnemonic::TEST_Iv(target, self.parse_word()?)),
|
||||||
},
|
},
|
||||||
// 0b001 => // unused
|
// 0b001 => // unused
|
||||||
0b010 => Ok(Mnemonic::NOT(target)),
|
0b010 => Ok(Mnemonic::NOT(target)),
|
||||||
@@ -635,26 +637,26 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 1
|
// Group 1
|
||||||
0x80 => {
|
0x80 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
||||||
let imm = self.parse_byte()?;
|
let imm = self.parse_byte()?;
|
||||||
Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm))?
|
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
|
||||||
}
|
}
|
||||||
0x81 => {
|
0x81 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
let imm = self.parse_word()?;
|
let imm = self.parse_word()?;
|
||||||
Self::modrm_reg_to_grp1(reg, target, Operand::Word(imm))?
|
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Word(imm))?
|
||||||
}
|
}
|
||||||
0x82 => {
|
0x82 => {
|
||||||
// same as 0x80
|
// same as 0x80
|
||||||
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
||||||
let imm = self.parse_byte()?;
|
let imm = self.parse_byte()?;
|
||||||
Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm))?
|
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
|
||||||
}
|
}
|
||||||
0x83 => {
|
0x83 => {
|
||||||
// byte extended version
|
// byte extended version
|
||||||
let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
let imm = self.parse_byte()?;
|
let imm = self.parse_byte()?;
|
||||||
Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm))?
|
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
|
||||||
}
|
}
|
||||||
|
|
||||||
0x84 => modrm_8b_register!(self, TEST),
|
0x84 => modrm_8b_register!(self, TEST),
|
||||||
@@ -673,7 +675,7 @@ impl Disassembler {
|
|||||||
0x8D => modrm_16b_register!(self, LEA),
|
0x8D => modrm_16b_register!(self, LEA),
|
||||||
|
|
||||||
0x8F => {
|
0x8F => {
|
||||||
let (target, _) = self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, _) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
let mem = match target {
|
let mem = match target {
|
||||||
ModRmTarget::Memory(idx) => idx,
|
ModRmTarget::Memory(idx) => idx,
|
||||||
_ => {
|
_ => {
|
||||||
@@ -749,24 +751,24 @@ impl Disassembler {
|
|||||||
0xC3 => Mnemonic::RET,
|
0xC3 => Mnemonic::RET,
|
||||||
|
|
||||||
0xC4 => {
|
0xC4 => {
|
||||||
let (target, reg_id) = self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, reg_id) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
let reg = Register::by_id(Operand::Word(reg_id as Word))?;
|
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
|
||||||
let ptr = Pointer16::try_from(target)?;
|
let ptr = Pointer16::try_from(target)?;
|
||||||
Mnemonic::LES(reg, ptr)
|
Mnemonic::LES(reg, ptr)
|
||||||
}
|
}
|
||||||
0xC5 => {
|
0xC5 => {
|
||||||
let (target, reg_id) = self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, reg_id) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
let reg = Register::by_id(Operand::Word(reg_id as Word))?;
|
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
|
||||||
let ptr = Pointer16::try_from(target)?;
|
let ptr = Pointer16::try_from(target)?;
|
||||||
Mnemonic::LDS(reg, ptr)
|
Mnemonic::LDS(reg, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
0xC6 => {
|
0xC6 => {
|
||||||
let (target, _) = self.parse_modrm_byte(Operand::Byte(0))?;
|
let (target, _) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
||||||
Mnemonic::MOV_Ib(target, self.parse_byte()?)
|
Mnemonic::MOV_Ib(target, self.parse_byte()?)
|
||||||
}
|
}
|
||||||
0xC7 => {
|
0xC7 => {
|
||||||
let (target, _) = self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, _) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
Mnemonic::MOV_Iv(target, self.parse_word()?)
|
Mnemonic::MOV_Iv(target, self.parse_word()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,19 +785,19 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 2
|
// Group 2
|
||||||
0xD0 => {
|
0xD0 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
||||||
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(Operand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
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(Operand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
||||||
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(Operand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
Self::modrm_reg_to_grp2_cl(reg, target)?
|
Self::modrm_reg_to_grp2_cl(reg, target)?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -842,13 +844,13 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 3a
|
// Group 3a
|
||||||
0xF6 => {
|
0xF6 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
||||||
self.modrm_reg_to_grp3(reg, target, Operand::Byte(0))?
|
self.modrm_reg_to_grp3(reg, target, ImmediateOperand::Byte(0))?
|
||||||
}
|
}
|
||||||
// Group 3b
|
// Group 3b
|
||||||
0xF7 => {
|
0xF7 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
self.modrm_reg_to_grp3(reg, target, Operand::Word(0))?
|
self.modrm_reg_to_grp3(reg, target, ImmediateOperand::Word(0))?
|
||||||
}
|
}
|
||||||
|
|
||||||
0xF8 => Mnemonic::CLC,
|
0xF8 => Mnemonic::CLC,
|
||||||
@@ -860,7 +862,7 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 4
|
// Group 4
|
||||||
0xFE => {
|
0xFE => {
|
||||||
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
||||||
match reg {
|
match reg {
|
||||||
0b0 => Mnemonic::INC_Mod(target),
|
0b0 => Mnemonic::INC_Mod(target),
|
||||||
0b1 => Mnemonic::DEC_Mod(target),
|
0b1 => Mnemonic::DEC_Mod(target),
|
||||||
@@ -870,7 +872,7 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 5
|
// Group 5
|
||||||
0xFF => {
|
0xFF => {
|
||||||
let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
match reg {
|
match reg {
|
||||||
0b000 => Mnemonic::INC_Mod(target),
|
0b000 => Mnemonic::INC_Mod(target),
|
||||||
0b001 => Mnemonic::DEC_Mod(target),
|
0b001 => Mnemonic::DEC_Mod(target),
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
/// Generate a Mnemonic for an 8-bit Register from a ModRM byte.
|
/// Generate a Mnemonic for an 8-bit Register from a ModRM byte.
|
||||||
macro_rules! modrm_8b_register {
|
macro_rules! modrm_8b_register {
|
||||||
($self:ident, $variant:ident) => {{
|
($self:ident, $variant:ident) => {{
|
||||||
let (target, reg) = $self.parse_modrm_byte(Operand::Byte(0))?;
|
let (target, reg) = $self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
||||||
Mnemonic::$variant(target, Register::by_id(Operand::Byte(reg))?)
|
Mnemonic::$variant(target, Register::by_id(ImmediateOperand::Byte(reg))?)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,8 +13,8 @@ macro_rules! modrm_8b_register {
|
|||||||
/// Generate a Mnemonic for a 16-bit Register from a ModRM byte.
|
/// Generate a Mnemonic for a 16-bit Register from a ModRM byte.
|
||||||
macro_rules! modrm_16b_register {
|
macro_rules! modrm_16b_register {
|
||||||
($self:ident, $variant:ident) => {{
|
($self:ident, $variant:ident) => {{
|
||||||
let (target, reg) = $self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, reg) = $self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
Mnemonic::$variant(target, Register::by_id(Operand::Word(reg.into()))?)
|
Mnemonic::$variant(target, Register::by_id(ImmediateOperand::Word(reg.into()))?)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ macro_rules! modrm_16b_register {
|
|||||||
/// Generate a Mnemonic for a 16-bit Segment Register from a ModRM byte.
|
/// Generate a Mnemonic for a 16-bit Segment Register from a ModRM byte.
|
||||||
macro_rules! modrm_sregister {
|
macro_rules! modrm_sregister {
|
||||||
($self:ident, $variant:ident) => {{
|
($self:ident, $variant:ident) => {{
|
||||||
let (target, reg) = $self.parse_modrm_byte(Operand::Word(0))?;
|
let (target, reg) = $self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
||||||
Mnemonic::$variant(target, SegmentRegister::by_id(reg)?)
|
Mnemonic::$variant(target, SegmentRegister::by_id(reg)?)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use crate::operands::{ModRmTarget, Operand};
|
use crate::operands::{ImmediateOperand, ModRmTarget};
|
||||||
|
|
||||||
use super::{flags::Flags, memory::Memory, register::Register};
|
use super::{flags::Flags, memory::Memory, register::Register};
|
||||||
|
|
||||||
/// Wrapper for easier argument passing of arithmetic operations.
|
/// Wrapper for easier argument passing of arithmetic operations.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Argument {
|
pub enum Operand {
|
||||||
Operand(crate::operands::Operand),
|
Immediate(crate::operands::ImmediateOperand),
|
||||||
ModRmTarget(ModRmTarget),
|
ModRmTarget(ModRmTarget),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,10 +30,10 @@ impl Computer {
|
|||||||
/// Adds two [`Argument`]s, saves it to `dest` and sets flags, if necessary.
|
/// Adds two [`Argument`]s, saves it to `dest` and sets flags, if necessary.
|
||||||
/// A value can never be saved to an immediate Operand, so `dest` can only
|
/// A value can never be saved to an immediate Operand, so `dest` can only
|
||||||
/// be a [`ModRmTarget`].
|
/// be a [`ModRmTarget`].
|
||||||
pub fn add(&mut self, dest: ModRmTarget, src: Argument) {
|
pub fn add(&mut self, dest: ModRmTarget, src: Operand) {
|
||||||
match src {
|
match src {
|
||||||
Argument::ModRmTarget(src_target) => self.add_modrm(dest, src_target),
|
Operand::ModRmTarget(src_target) => self.add_modrm(dest, src_target),
|
||||||
Argument::Operand(src_operand) => self.add_imm(dest, src_operand),
|
Operand::Immediate(src_operand) => self.add_imm(dest, src_operand),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,11 +45,10 @@ impl Computer {
|
|||||||
ModRmTarget::Memory(_) => panic!("Cannot add Memory to Memory!"),
|
ModRmTarget::Memory(_) => panic!("Cannot add Memory to Memory!"),
|
||||||
// mem, reg
|
// mem, reg
|
||||||
ModRmTarget::Register(src_register) => {
|
ModRmTarget::Register(src_register) => {
|
||||||
let lhs = self.memory.read_from_memidx(&self.regs, dest_memory_idx);
|
let lhs = self.memory.read(&self.regs, dest_memory_idx);
|
||||||
let rhs = self.regs.read(src_register);
|
let rhs = self.regs.read(src_register);
|
||||||
let result = lhs + rhs;
|
let result = lhs + rhs;
|
||||||
self.memory
|
self.memory.write(&self.regs, dest_memory_idx, result);
|
||||||
.write_from_memidx(&self.regs, dest_memory_idx, result);
|
|
||||||
// unsigned overflow
|
// unsigned overflow
|
||||||
self.flags.of = result < rhs;
|
self.flags.of = result < rhs;
|
||||||
}
|
}
|
||||||
@@ -58,7 +57,7 @@ impl Computer {
|
|||||||
// reg, mem
|
// reg, mem
|
||||||
ModRmTarget::Memory(src_memory_index) => {
|
ModRmTarget::Memory(src_memory_index) => {
|
||||||
let lhs = self.regs.read(dest_register);
|
let lhs = self.regs.read(dest_register);
|
||||||
let rhs = self.memory.read_from_memidx(&self.regs, src_memory_index);
|
let rhs = self.memory.read(&self.regs, src_memory_index);
|
||||||
let result = lhs + rhs;
|
let result = lhs + rhs;
|
||||||
self.regs.write(dest_register, result);
|
self.regs.write(dest_register, result);
|
||||||
// unsigned overflow
|
// unsigned overflow
|
||||||
@@ -78,16 +77,16 @@ impl Computer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an immediate [`Operand`] to a location pointed to by a
|
/// Adds an [`ImmediateOperand`] to a location pointed to by a
|
||||||
/// [`ModRmTarget`], saves it to dest and sets flags, if necessary.
|
/// [`ModRmTarget`], saves it to dest and sets flags, if necessary.
|
||||||
fn add_imm(&mut self, dest: ModRmTarget, src: Operand) {
|
fn add_imm(&mut self, dest: ModRmTarget, src: ImmediateOperand) {
|
||||||
match dest {
|
match dest {
|
||||||
ModRmTarget::Memory(dest_mem) => {
|
ModRmTarget::Memory(dest_mem) => {
|
||||||
let lhs = self.memory.read_from_memidx(&self.regs, dest_mem);
|
let lhs = self.memory.read(&self.regs, dest_mem);
|
||||||
let result = lhs + src;
|
let result = lhs + src;
|
||||||
// unsigned overflow
|
// unsigned overflow
|
||||||
self.flags.of = result < src;
|
self.flags.of = result < src;
|
||||||
self.memory.write_from_memidx(&self.regs, dest_mem, result);
|
self.memory.write(&self.regs, dest_mem, result);
|
||||||
}
|
}
|
||||||
ModRmTarget::Register(dest_reg) => {
|
ModRmTarget::Register(dest_reg) => {
|
||||||
let lhs = self.regs.read(dest_reg);
|
let lhs = self.regs.read(dest_reg);
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ use std::{fmt::Debug, process::exit};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instructions::{Instruction, Mnemonic},
|
instructions::{Instruction, Mnemonic},
|
||||||
operands::{Byte, ModRmTarget, Operand, Word},
|
operands::{Byte, ImmediateOperand, ModRmTarget, Word},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::computer::{Argument, Computer};
|
use super::computer::{Computer, Operand};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum InterpreterError {
|
pub enum InterpreterError {
|
||||||
@@ -56,23 +56,23 @@ impl Interpreter {
|
|||||||
*/
|
*/
|
||||||
Mnemonic::ADD_FromReg(dest, src) => self
|
Mnemonic::ADD_FromReg(dest, src) => self
|
||||||
.computer
|
.computer
|
||||||
.add(dest, Argument::ModRmTarget(ModRmTarget::Register(src))),
|
.add(dest, Operand::ModRmTarget(ModRmTarget::Register(src))),
|
||||||
Mnemonic::ADD_ToReg(src, dest) => self
|
Mnemonic::ADD_ToReg(src, dest) => self
|
||||||
.computer
|
.computer
|
||||||
.add(ModRmTarget::Register(dest), Argument::ModRmTarget(src)),
|
.add(ModRmTarget::Register(dest), Operand::ModRmTarget(src)),
|
||||||
Mnemonic::ADD_Ib(dest, src) => self
|
Mnemonic::ADD_Ib(dest, src) => self
|
||||||
.computer
|
.computer
|
||||||
.add(dest, Argument::Operand(Operand::Byte(src))),
|
.add(dest, Operand::Immediate(ImmediateOperand::Byte(src))),
|
||||||
Mnemonic::ADD_Iv(dest, src) => self
|
Mnemonic::ADD_Iv(dest, src) => self
|
||||||
.computer
|
.computer
|
||||||
.add(dest, Argument::Operand(Operand::Word(src))),
|
.add(dest, Operand::Immediate(ImmediateOperand::Word(src))),
|
||||||
Mnemonic::ADD_ALIb(src_byte) => self.computer.add(
|
Mnemonic::ADD_ALIb(src_byte) => self.computer.add(
|
||||||
ModRmTarget::Register(crate::register::Register::AL),
|
ModRmTarget::Register(crate::register::Register::AL),
|
||||||
Argument::Operand(Operand::Byte(src_byte)),
|
Operand::Immediate(ImmediateOperand::Byte(src_byte)),
|
||||||
),
|
),
|
||||||
Mnemonic::ADD_AXIv(src_word) => self.computer.add(
|
Mnemonic::ADD_AXIv(src_word) => self.computer.add(
|
||||||
ModRmTarget::Register(crate::register::Register::AX),
|
ModRmTarget::Register(crate::register::Register::AX),
|
||||||
Argument::Operand(Operand::Word(src_word)),
|
Operand::Immediate(ImmediateOperand::Word(src_word)),
|
||||||
),
|
),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::operands::{Byte, Displacement, MemoryIndex, Operand, Word};
|
use crate::operands::{Byte, Displacement, ImmediateOperand, MemoryIndex, Word};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
@@ -10,23 +10,23 @@ impl Memory {
|
|||||||
Self { memory: [0; 65536] }
|
Self { memory: [0; 65536] }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write an [`Operand`] to a memory location indexed by a [`MemoryIndex`].
|
// Write an [`ImmediateOperand`] to a memory location indexed by a [`MemoryIndex`].
|
||||||
pub fn write(
|
pub fn write(
|
||||||
&mut self,
|
&mut self,
|
||||||
regs: &crate::interpreter::register::Register,
|
regs: &crate::interpreter::register::Register,
|
||||||
idx: MemoryIndex,
|
idx: MemoryIndex,
|
||||||
val: Operand,
|
val: ImmediateOperand,
|
||||||
) {
|
) {
|
||||||
match Memory::calc_memidx(regs, idx) {
|
match Memory::calc_memidx(regs, idx) {
|
||||||
Operand::Byte(idx_byte) => match val {
|
ImmediateOperand::Byte(idx_byte) => match val {
|
||||||
Operand::Byte(value) => {
|
ImmediateOperand::Byte(value) => {
|
||||||
log::debug!("Writing byte {value:#04x} to memory location {idx_byte:#04x}");
|
log::debug!("Writing byte {value:#04x} to memory location {idx_byte:#04x}");
|
||||||
self.memory[idx_byte as usize] = value
|
self.memory[idx_byte as usize] = value
|
||||||
}
|
}
|
||||||
Operand::Word(_) => panic!("Cannot add Word to Byte Memory Index"),
|
ImmediateOperand::Word(_) => panic!("Cannot add Word to Byte Memory Index"),
|
||||||
},
|
},
|
||||||
Operand::Word(idx_word) => match val {
|
ImmediateOperand::Word(idx_word) => match val {
|
||||||
Operand::Word(value) => {
|
ImmediateOperand::Word(value) => {
|
||||||
let byte1 = idx_word / 2;
|
let byte1 = idx_word / 2;
|
||||||
let byte2 = idx_word / 2 + 1;
|
let byte2 = idx_word / 2 + 1;
|
||||||
let [low, high]: [u8; 2] = value.to_le_bytes();
|
let [low, high]: [u8; 2] = value.to_le_bytes();
|
||||||
@@ -36,7 +36,7 @@ impl Memory {
|
|||||||
self.memory[byte1 as usize] = low;
|
self.memory[byte1 as usize] = low;
|
||||||
self.memory[byte1 as usize] = high;
|
self.memory[byte1 as usize] = high;
|
||||||
}
|
}
|
||||||
Operand::Byte(value) => {
|
ImmediateOperand::Byte(value) => {
|
||||||
self.memory[(idx_word * 2) as usize] = value;
|
self.memory[(idx_word * 2) as usize] = value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -44,17 +44,21 @@ impl Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read into memory with a [`MemoryIndex`] as index.
|
/// Read into memory with a [`MemoryIndex`] as index.
|
||||||
pub fn read(&self, regs: &crate::interpreter::register::Register, idx: MemoryIndex) -> Operand {
|
pub fn read(
|
||||||
|
&self,
|
||||||
|
regs: &crate::interpreter::register::Register,
|
||||||
|
idx: MemoryIndex,
|
||||||
|
) -> ImmediateOperand {
|
||||||
match Memory::calc_memidx(regs, idx) {
|
match Memory::calc_memidx(regs, idx) {
|
||||||
Operand::Byte(byte) => {
|
ImmediateOperand::Byte(byte) => {
|
||||||
log::debug!("Reading byte {byte:#04x} from memory");
|
log::debug!("Reading byte {byte:#04x} from memory");
|
||||||
Operand::Byte(self.memory[byte as usize])
|
ImmediateOperand::Byte(self.memory[byte as usize])
|
||||||
}
|
}
|
||||||
Operand::Word(word) => {
|
ImmediateOperand::Word(word) => {
|
||||||
let byte1 = word / 2;
|
let byte1 = word / 2;
|
||||||
let byte2 = word / 2 + 1;
|
let byte2 = word / 2 + 1;
|
||||||
log::debug!("Reading bytes {byte1:#04x} and {byte2:#04x} from memory");
|
log::debug!("Reading bytes {byte1:#04x} and {byte2:#04x} from memory");
|
||||||
Operand::Word(Word::from_le_bytes([
|
ImmediateOperand::Word(Word::from_le_bytes([
|
||||||
self.memory[byte1 as usize],
|
self.memory[byte1 as usize],
|
||||||
self.memory[byte2 as usize],
|
self.memory[byte2 as usize],
|
||||||
]))
|
]))
|
||||||
@@ -63,9 +67,12 @@ impl Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the absolute Memory Index from a [`MemoryIndex`] struct.
|
/// Calculate the absolute Memory Index from a [`MemoryIndex`] struct.
|
||||||
fn calc_memidx(regs: &crate::interpreter::register::Register, idx: MemoryIndex) -> Operand {
|
fn calc_memidx(
|
||||||
let mut base = Operand::Word(0);
|
regs: &crate::interpreter::register::Register,
|
||||||
let mut index = Operand::Word(0);
|
idx: MemoryIndex,
|
||||||
|
) -> ImmediateOperand {
|
||||||
|
let mut base = ImmediateOperand::Word(0);
|
||||||
|
let mut index = ImmediateOperand::Word(0);
|
||||||
let mut disp = Displacement::IWord(0);
|
let mut disp = Displacement::IWord(0);
|
||||||
|
|
||||||
if let Some(base_reg) = idx.base {
|
if let Some(base_reg) = idx.base {
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use crate::operands::{Byte, Operand, Word};
|
use crate::operands::{Byte, ImmediateOperand, Word};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use super::flags::Flags;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Register {
|
pub struct Register {
|
||||||
pub ax: AX,
|
pub ax: AX,
|
||||||
@@ -30,31 +28,31 @@ impl Register {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read value from a [`crate::register::Register`].
|
/// Read value from a [`crate::register::Register`].
|
||||||
pub fn read(&self, reg: crate::register::Register) -> Operand {
|
pub fn read(&self, reg: crate::register::Register) -> ImmediateOperand {
|
||||||
match reg {
|
match reg {
|
||||||
crate::register::Register::AX => Operand::Word(self.ax.read()),
|
crate::register::Register::AX => ImmediateOperand::Word(self.ax.read()),
|
||||||
crate::register::Register::BX => Operand::Word(self.bx.read()),
|
crate::register::Register::BX => ImmediateOperand::Word(self.bx.read()),
|
||||||
crate::register::Register::CX => Operand::Word(self.cx.read()),
|
crate::register::Register::CX => ImmediateOperand::Word(self.cx.read()),
|
||||||
crate::register::Register::DX => Operand::Word(self.dx.read()),
|
crate::register::Register::DX => ImmediateOperand::Word(self.dx.read()),
|
||||||
crate::register::Register::AH => Operand::Byte(self.ax.upper),
|
crate::register::Register::AH => ImmediateOperand::Byte(self.ax.upper),
|
||||||
crate::register::Register::AL => Operand::Byte(self.ax.lower),
|
crate::register::Register::AL => ImmediateOperand::Byte(self.ax.lower),
|
||||||
crate::register::Register::BH => Operand::Byte(self.bx.upper),
|
crate::register::Register::BH => ImmediateOperand::Byte(self.bx.upper),
|
||||||
crate::register::Register::BL => Operand::Byte(self.bx.lower),
|
crate::register::Register::BL => ImmediateOperand::Byte(self.bx.lower),
|
||||||
crate::register::Register::CH => Operand::Byte(self.cx.upper),
|
crate::register::Register::CH => ImmediateOperand::Byte(self.cx.upper),
|
||||||
crate::register::Register::CL => Operand::Byte(self.cx.lower),
|
crate::register::Register::CL => ImmediateOperand::Byte(self.cx.lower),
|
||||||
crate::register::Register::DH => Operand::Byte(self.dx.upper),
|
crate::register::Register::DH => ImmediateOperand::Byte(self.dx.upper),
|
||||||
crate::register::Register::DL => Operand::Byte(self.dx.lower),
|
crate::register::Register::DL => ImmediateOperand::Byte(self.dx.lower),
|
||||||
crate::register::Register::DI => Operand::Word(self.di),
|
crate::register::Register::DI => ImmediateOperand::Word(self.di),
|
||||||
crate::register::Register::SI => Operand::Word(self.si),
|
crate::register::Register::SI => ImmediateOperand::Word(self.si),
|
||||||
crate::register::Register::BP => Operand::Word(self.bp),
|
crate::register::Register::BP => ImmediateOperand::Word(self.bp),
|
||||||
crate::register::Register::SP => Operand::Word(self.sp),
|
crate::register::Register::SP => ImmediateOperand::Word(self.sp),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write an [`Operand`] to a [`crate::register::Register`].
|
/// Write an [`ImmediateOperand`] to a [`crate::register::Register`].
|
||||||
pub fn write(&mut self, reg: crate::register::Register, op: Operand) {
|
pub fn write(&mut self, reg: crate::register::Register, op: ImmediateOperand) {
|
||||||
match op {
|
match op {
|
||||||
Operand::Byte(byte) => match reg {
|
ImmediateOperand::Byte(byte) => match reg {
|
||||||
crate::register::Register::AX => self.ax.lower = byte,
|
crate::register::Register::AX => self.ax.lower = byte,
|
||||||
crate::register::Register::BX => self.bx.lower = byte,
|
crate::register::Register::BX => self.bx.lower = byte,
|
||||||
crate::register::Register::CX => self.cx.lower = byte,
|
crate::register::Register::CX => self.cx.lower = byte,
|
||||||
@@ -72,7 +70,7 @@ impl Register {
|
|||||||
crate::register::Register::BP => self.bp = Word::from_le_bytes([0x0, byte]),
|
crate::register::Register::BP => self.bp = Word::from_le_bytes([0x0, byte]),
|
||||||
crate::register::Register::SP => self.sp = Word::from_le_bytes([0x0, byte]),
|
crate::register::Register::SP => self.sp = Word::from_le_bytes([0x0, byte]),
|
||||||
},
|
},
|
||||||
Operand::Word(word) => {
|
ImmediateOperand::Word(word) => {
|
||||||
match reg {
|
match reg {
|
||||||
crate::register::Register::AX => self.ax.write(word),
|
crate::register::Register::AX => self.ax.write(word),
|
||||||
crate::register::Register::BX => self.bx.write(word),
|
crate::register::Register::BX => self.bx.write(word),
|
||||||
|
|||||||
@@ -20,70 +20,75 @@ pub type DWord = u32;
|
|||||||
/// Also sometimes used to decide if an instruction is Byte- or Word-sized,
|
/// Also sometimes used to decide if an instruction is Byte- or Word-sized,
|
||||||
/// which is usually indicated by using a value of 0 and the disregarding
|
/// which is usually indicated by using a value of 0 and the disregarding
|
||||||
/// the value when read.
|
/// the value when read.
|
||||||
pub enum Operand {
|
pub enum ImmediateOperand {
|
||||||
Byte(Byte),
|
Byte(Byte),
|
||||||
Word(Word),
|
Word(Word),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add for Operand {
|
impl Add for ImmediateOperand {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn add(self, other: Self) -> Self {
|
fn add(self, other: Self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Operand::Byte(lhsb) => match other {
|
ImmediateOperand::Byte(lhsb) => match other {
|
||||||
Operand::Byte(rhsb) => Operand::Byte(lhsb.wrapping_add(rhsb)),
|
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_add(rhsb)),
|
||||||
_ => panic!("Cannot add Word to Byte"),
|
_ => panic!("Cannot add Word to Byte"),
|
||||||
},
|
},
|
||||||
Operand::Word(lhsw) => match other {
|
ImmediateOperand::Word(lhsw) => match other {
|
||||||
Operand::Word(rhsw) => Operand::Word(lhsw.wrapping_add(rhsw)),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_add(rhsw)),
|
||||||
Operand::Byte(rhsb) => Operand::Word(lhsw.wrapping_add(rhsb as Word)),
|
ImmediateOperand::Byte(rhsb) => {
|
||||||
|
ImmediateOperand::Word(lhsw.wrapping_add(rhsb as Word))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add<Displacement> for Operand {
|
impl Add<Displacement> for ImmediateOperand {
|
||||||
type Output = Operand;
|
type Output = ImmediateOperand;
|
||||||
|
|
||||||
fn add(self, disp: Displacement) -> Self::Output {
|
fn add(self, disp: Displacement) -> Self::Output {
|
||||||
// XXX: ugly hack to add Operand with Displacement
|
// Warning: this gets rid of the sign, which is fine as long as it is
|
||||||
|
// used for a memory index, which can never be negative.
|
||||||
match disp {
|
match disp {
|
||||||
Displacement::IByte(byte) => {
|
Displacement::IByte(byte) => {
|
||||||
if byte < 0 {
|
if byte < 0 {
|
||||||
return self - Operand::Byte((byte * -1) as Byte);
|
return self - ImmediateOperand::Byte((byte * -1) as Byte);
|
||||||
} else {
|
} else {
|
||||||
return self + Operand::Byte(byte as Byte);
|
return self + ImmediateOperand::Byte(byte as Byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Displacement::IWord(word) => {
|
Displacement::IWord(word) => {
|
||||||
if word < 0 {
|
if word < 0 {
|
||||||
return self - Operand::Word((word * -1) as Word);
|
return self - ImmediateOperand::Word((word * -1) as Word);
|
||||||
} else {
|
} else {
|
||||||
return self + Operand::Word(word as Word);
|
return self + ImmediateOperand::Word(word as Word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sub for Operand {
|
impl Sub for ImmediateOperand {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn sub(self, other: Self) -> Self {
|
fn sub(self, other: Self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Operand::Byte(lhsb) => match other {
|
ImmediateOperand::Byte(lhsb) => match other {
|
||||||
Operand::Byte(rhsb) => Operand::Byte(lhsb.wrapping_sub(rhsb)),
|
ImmediateOperand::Byte(rhsb) => ImmediateOperand::Byte(lhsb.wrapping_sub(rhsb)),
|
||||||
_ => panic!("Cannot substract Word from Byte"),
|
_ => panic!("Cannot substract Word from Byte"),
|
||||||
},
|
},
|
||||||
Operand::Word(lhsw) => match other {
|
ImmediateOperand::Word(lhsw) => match other {
|
||||||
Operand::Word(rhsw) => Operand::Word(lhsw.wrapping_sub(rhsw)),
|
ImmediateOperand::Word(rhsw) => ImmediateOperand::Word(lhsw.wrapping_sub(rhsw)),
|
||||||
Operand::Byte(rhsb) => Operand::Word(lhsw.wrapping_sub(rhsb as Word)),
|
ImmediateOperand::Byte(rhsb) => {
|
||||||
|
ImmediateOperand::Word(lhsw.wrapping_sub(rhsb as Word))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Operand {
|
impl fmt::Display for ImmediateOperand {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Byte(byte) => write!(f, "{}", byte),
|
Self::Byte(byte) => write!(f, "{}", byte),
|
||||||
@@ -92,7 +97,7 @@ impl fmt::Display for Operand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::LowerHex for Operand {
|
impl fmt::LowerHex for ImmediateOperand {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Byte(b) => fmt::LowerHex::fmt(b, f),
|
Self::Byte(b) => fmt::LowerHex::fmt(b, f),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Internal abstraction of all 8086 registers for disassembly.
|
//! Internal abstraction of all 8086 registers for disassembly.
|
||||||
|
|
||||||
use crate::{disasm::DisasmError, operands::Operand};
|
use crate::{disasm::DisasmError, operands::ImmediateOperand};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
||||||
@@ -34,9 +34,9 @@ pub type RegisterId = u8;
|
|||||||
|
|
||||||
impl Register {
|
impl Register {
|
||||||
/// Find the register corresponding to the 8086 bytecode ID
|
/// Find the register corresponding to the 8086 bytecode ID
|
||||||
pub fn by_id(id: Operand) -> Result<Self, DisasmError> {
|
pub fn by_id(id: ImmediateOperand) -> Result<Self, DisasmError> {
|
||||||
match id {
|
match id {
|
||||||
Operand::Byte(b) => match b {
|
ImmediateOperand::Byte(b) => match b {
|
||||||
0b000 => Ok(Self::AL),
|
0b000 => Ok(Self::AL),
|
||||||
0b001 => Ok(Self::CL),
|
0b001 => Ok(Self::CL),
|
||||||
0b010 => Ok(Self::DL),
|
0b010 => Ok(Self::DL),
|
||||||
@@ -47,7 +47,7 @@ impl Register {
|
|||||||
0b111 => Ok(Self::BH),
|
0b111 => Ok(Self::BH),
|
||||||
_ => Err(DisasmError::UnknownRegister(b as usize)),
|
_ => Err(DisasmError::UnknownRegister(b as usize)),
|
||||||
},
|
},
|
||||||
Operand::Word(w) => match w {
|
ImmediateOperand::Word(w) => match w {
|
||||||
0b000 => Ok(Self::AX),
|
0b000 => Ok(Self::AX),
|
||||||
0b001 => Ok(Self::CX),
|
0b001 => Ok(Self::CX),
|
||||||
0b010 => Ok(Self::DX),
|
0b010 => Ok(Self::DX),
|
||||||
|
|||||||
Reference in New Issue
Block a user