ft: use instructionwidth instead of immediateoperand

Previously an immediate operand with data of 0 was use to encode
width, now use a dedicated enum for improved clarity.
This commit is contained in:
2025-06-17 19:57:00 +09:00
parent 18cc460d40
commit 7d5f891a93
2 changed files with 45 additions and 34 deletions

View File

@@ -14,6 +14,13 @@ use crate::{modrm_8b_register, modrm_16b_register, modrm_sregister};
use core::fmt; use core::fmt;
use std::{fs::File, io::Read}; use std::{fs::File, io::Read};
#[derive(Debug, Clone)]
/// Select, wheter 8, or 16-bit Registers should be selected.
pub enum InstructionWidth {
Byte,
Word,
}
#[derive(Debug)] #[derive(Debug)]
/// Generic errors, which are encountered during parsing. /// Generic errors, which are encountered during parsing.
pub enum DisasmError { pub enum DisasmError {
@@ -240,7 +247,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: ImmediateOperand, register_width: Option<InstructionWidth>,
) -> Result<(ModRmTarget, RegisterId), DisasmError> { ) -> Result<(ModRmTarget, RegisterId), DisasmError> {
let modrm = self.parse_byte()?; let modrm = self.parse_byte()?;
@@ -292,13 +299,17 @@ impl Disassembler {
log::debug!( log::debug!(
"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 = if let Some(width) = register_width {
ImmediateOperand::Byte(_) => { match width {
ModRmTarget::Register(Register::by_id(ImmediateOperand::Byte(rm))?) InstructionWidth::Byte => {
} ModRmTarget::Register(Register::by_id(ImmediateOperand::Byte(rm))?)
ImmediateOperand::Word(_) => { }
ModRmTarget::Register(Register::by_id(ImmediateOperand::Word(rm as Word))?) InstructionWidth::Word => ModRmTarget::Register(Register::by_id(
ImmediateOperand::Word(rm as Word),
)?),
} }
} else {
panic!("No Register width provided, when it was needed");
}; };
return Ok((target, reg)); return Ok((target, reg));
} }
@@ -359,9 +370,9 @@ impl Disassembler {
fn modrm_reg_to_grp1( fn modrm_reg_to_grp1(
reg: u8, reg: u8,
target: ModRmTarget, target: ModRmTarget,
instruction_width: ImmediateOperand, val: ImmediateOperand,
) -> Result<Mnemonic, DisasmError> { ) -> Result<Mnemonic, DisasmError> {
match instruction_width { match val {
ImmediateOperand::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)),
@@ -432,12 +443,12 @@ impl Disassembler {
&mut self, &mut self,
reg: u8, reg: u8,
target: ModRmTarget, target: ModRmTarget,
width: ImmediateOperand, width: InstructionWidth,
) -> Result<Mnemonic, DisasmError> { ) -> Result<Mnemonic, DisasmError> {
match reg { match reg {
0b000 => match width { 0b000 => match width {
ImmediateOperand::Byte(_) => Ok(Mnemonic::TEST_Ib(target, self.parse_byte()?)), InstructionWidth::Byte => Ok(Mnemonic::TEST_Ib(target, self.parse_byte()?)),
ImmediateOperand::Word(_) => Ok(Mnemonic::TEST_Iv(target, self.parse_word()?)), InstructionWidth::Word => Ok(Mnemonic::TEST_Iv(target, self.parse_word()?)),
}, },
// 0b001 => // unused // 0b001 => // unused
0b010 => Ok(Mnemonic::NOT(target)), 0b010 => Ok(Mnemonic::NOT(target)),
@@ -639,24 +650,24 @@ impl Disassembler {
// Group 1 // Group 1
0x80 => { 0x80 => {
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?; let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
let imm = self.parse_byte()?; let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))? Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
} }
0x81 => { 0x81 => {
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?; let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let imm = self.parse_word()?; let imm = self.parse_word()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::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(ImmediateOperand::Byte(0))?; let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
let imm = self.parse_byte()?; let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::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(ImmediateOperand::Word(0))?; let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let imm = self.parse_byte()?; let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))? Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
} }
@@ -677,7 +688,7 @@ impl Disassembler {
0x8D => modrm_16b_register!(self, LEA), 0x8D => modrm_16b_register!(self, LEA),
0x8F => { 0x8F => {
let (target, _) = self.parse_modrm_byte(ImmediateOperand::Word(0))?; let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let mem = match target { let mem = match target {
ModRmTarget::Memory(idx) => idx, ModRmTarget::Memory(idx) => idx,
_ => { _ => {
@@ -753,24 +764,24 @@ impl Disassembler {
0xC3 => Mnemonic::RET, 0xC3 => Mnemonic::RET,
0xC4 => { 0xC4 => {
let (target, reg_id) = self.parse_modrm_byte(ImmediateOperand::Word(0))?; let (target, reg_id) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let reg = Register::by_id(ImmediateOperand::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(ImmediateOperand::Word(0))?; let (target, reg_id) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let reg = Register::by_id(ImmediateOperand::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(ImmediateOperand::Byte(0))?; let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
Mnemonic::MOV_Ib(target, self.parse_byte()?) Mnemonic::MOV_Ib(target, self.parse_byte()?)
} }
0xC7 => { 0xC7 => {
let (target, _) = self.parse_modrm_byte(ImmediateOperand::Word(0))?; let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
Mnemonic::MOV_Iv(target, self.parse_word()?) Mnemonic::MOV_Iv(target, self.parse_word()?)
} }
@@ -787,19 +798,19 @@ impl Disassembler {
// Group 2 // Group 2
0xD0 => { 0xD0 => {
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?; let (target, reg) = self.parse_modrm_byte(None)?;
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(ImmediateOperand::Word(0))?; let (target, reg) = self.parse_modrm_byte(None)?;
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(ImmediateOperand::Byte(0))?; let (target, reg) = self.parse_modrm_byte(None)?;
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(ImmediateOperand::Word(0))?; let (target, reg) = self.parse_modrm_byte(None)?;
Self::modrm_reg_to_grp2_cl(reg, target)? Self::modrm_reg_to_grp2_cl(reg, target)?
} }
@@ -846,13 +857,13 @@ impl Disassembler {
// Group 3a // Group 3a
0xF6 => { 0xF6 => {
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?; let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
self.modrm_reg_to_grp3(reg, target, ImmediateOperand::Byte(0))? self.modrm_reg_to_grp3(reg, target, InstructionWidth::Byte)?
} }
// Group 3b // Group 3b
0xF7 => { 0xF7 => {
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?; let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
self.modrm_reg_to_grp3(reg, target, ImmediateOperand::Word(0))? self.modrm_reg_to_grp3(reg, target, InstructionWidth::Word)?
} }
0xF8 => Mnemonic::CLC, 0xF8 => Mnemonic::CLC,
@@ -864,7 +875,7 @@ impl Disassembler {
// Group 4 // Group 4
0xFE => { 0xFE => {
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?; let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
match reg { match reg {
0b0 => Mnemonic::INC_Mod(target), 0b0 => Mnemonic::INC_Mod(target),
0b1 => Mnemonic::DEC_Mod(target), 0b1 => Mnemonic::DEC_Mod(target),
@@ -874,7 +885,7 @@ impl Disassembler {
// Group 5 // Group 5
0xFF => { 0xFF => {
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?; let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
match reg { match reg {
0b000 => Mnemonic::INC_Mod(target), 0b000 => Mnemonic::INC_Mod(target),
0b001 => Mnemonic::DEC_Mod(target), 0b001 => Mnemonic::DEC_Mod(target),

View File

@@ -4,7 +4,7 @@
/// 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(ImmediateOperand::Byte(0))?; let (target, reg) = $self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
Mnemonic::$variant(target, Register::by_id(ImmediateOperand::Byte(reg))?) Mnemonic::$variant(target, Register::by_id(ImmediateOperand::Byte(reg))?)
}}; }};
} }
@@ -13,7 +13,7 @@ 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(ImmediateOperand::Word(0))?; let (target, reg) = $self.parse_modrm_byte(Some(InstructionWidth::Word))?;
Mnemonic::$variant(target, Register::by_id(ImmediateOperand::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(ImmediateOperand::Word(0))?; let (target, reg) = $self.parse_modrm_byte(Some(InstructionWidth::Word))?;
Mnemonic::$variant(target, SegmentRegister::by_id(reg)?) Mnemonic::$variant(target, SegmentRegister::by_id(reg)?)
}}; }};
} }