Files
8086-rs/src/instructions.rs

597 lines
23 KiB
Rust

//! Internal abstraction of the 8086 instructions.
use crate::{
operands::{Byte, MemoryIndex, ModRmTarget, Pointer16, Pointer32, Word},
register::{Register, SegmentRegister},
};
use core::fmt;
#[derive(Debug, Clone, Eq, PartialEq)]
/// A single 'line' of executable ASM is called an Instruction, which
/// contains the `Mnemonic` that will be executed, alongside its starting offset
/// and the raw parsed bytes
pub struct Instruction {
pub start: usize, // location of the instruction start
pub raw: Vec<u8>, // raw value of instruction
pub opcode: Mnemonic, // actual instruction
}
impl Instruction {
pub fn new() -> Self {
Instruction {
start: 0,
raw: Vec::new(),
opcode: Mnemonic::NOP(),
}
}
}
impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:04x}:\t", self.start).unwrap();
write!(
f,
"{:<16}", // length of longest possible instruction
self.raw
.iter()
.map(|b| format!("{:02x}", b))
.collect::<Vec<String>>()
.join(" ")
)
.unwrap();
write!(f, "\t{}", self.opcode)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
#[allow(non_camel_case_types)]
/// All possible mnemonic variantions.
/// These are sorted by type and are not in hex-encoding order.
// XXX: convert this copy and paste horror in a proc macro like
// enum Opcode {
// #[derive(default_variations)]
// ADD,
// ...
// }
// which then add all variants and also create the matching logic for
// src/disasm.rs decode_instructions()
pub enum Mnemonic {
NOP(),
// ADD
ADD_FromReg(ModRmTarget, Register), // From Register into either Memory or Register
ADD_ToReg(ModRmTarget, Register), // From either Memory or Register into Reigster
ADD_Ib(ModRmTarget, Byte), // From Immediate into either Memory or Register
ADD_Iv(ModRmTarget, Word), // From Immediate into either Memory or Register
ADD_ALIb(Byte),
ADD_AXIv(Word),
// PUSH
PUSH_R(Register),
PUSH_S(SegmentRegister),
PUSH_Mod(ModRmTarget),
// POP
POP_S(SegmentRegister), // POP to Segment Register
POP_R(Register), // POP to Register
POP_M(MemoryIndex), // POP to Memory
// OR
OR_FromReg(ModRmTarget, Register),
OR_ToReg(ModRmTarget, Register),
OR_Ib(ModRmTarget, Byte),
OR_Iv(ModRmTarget, Word),
OR_ALIb(Byte),
OR_AXIv(Word),
// ADC
ADC_FromReg(ModRmTarget, Register),
ADC_ToReg(ModRmTarget, Register),
ADC_Ib(ModRmTarget, Byte),
ADC_Iv(ModRmTarget, Word),
ADC_ALIb(Byte),
ADC_AXIv(Word),
// SBB
SBB_FromReg(ModRmTarget, Register),
SBB_ToReg(ModRmTarget, Register),
SBB_Ib(ModRmTarget, Byte),
SBB_Iv(ModRmTarget, Word),
SBB_ALIb(Byte),
SBB_AXIv(Word),
// AND
AND_FromReg(ModRmTarget, Register),
AND_ToReg(ModRmTarget, Register),
AND_Ib(ModRmTarget, Byte),
AND_Iv(ModRmTarget, Word),
AND_ALIb(Byte),
AND_AXIv(Word),
// Override
OVERRIDE(SegmentRegister),
// Decimal Adjustment
DAA,
DAS,
AAA,
AAS,
// SUB
SUB_FromReg(ModRmTarget, Register),
SUB_ToReg(ModRmTarget, Register),
SUB_Ib(ModRmTarget, Byte),
SUB_Iv(ModRmTarget, Word),
SUB_ALIb(Byte),
SUB_AXIv(Word),
// XOR
XOR_FromReg(ModRmTarget, Register),
XOR_ToReg(ModRmTarget, Register),
XOR_Ib(ModRmTarget, Byte),
XOR_Iv(ModRmTarget, Word),
XOR_ALIb(Byte),
XOR_AXIv(Word),
// CMP
CMP_FromReg(ModRmTarget, Register),
CMP_ToReg(ModRmTarget, Register),
CMP_Ib(ModRmTarget, Byte),
CMP_Iv(ModRmTarget, Word),
CMP_ALIb(Byte),
CMP_AXIv(Word),
// INC
INC_Reg(Register),
INC_Mod(ModRmTarget),
// DEC
DEC_Reg(Register),
DEC_Mod(ModRmTarget),
// Jumps conditional
JO(usize),
JNO(usize),
JB(usize),
JNB(usize),
JZ(usize),
JNZ(usize),
JBE(usize),
JA(usize),
JS(usize),
JNS(usize),
JPE(usize),
JPO(usize),
JL(usize),
JGE(usize),
JLE(usize),
JG(usize),
LOOPNZ(usize),
LOOPZ(usize),
LOOP(usize),
JCXZ(usize),
// TEST
TEST(ModRmTarget, Register),
TEST_Ib(ModRmTarget, Byte),
TEST_Iv(ModRmTarget, Word),
TEST_ALIb(Byte),
TEST_AXIv(Word),
//XHCG
XCHG(ModRmTarget, Register),
XCHG_AX(Register), // from AX
// MOV
MOV_FromReg(ModRmTarget, Register),
MOV_ToReg(ModRmTarget, Register),
MOV_FromSReg(ModRmTarget, SegmentRegister),
MOV_ToSReg(ModRmTarget, SegmentRegister),
MOV_Ib(ModRmTarget, Byte),
MOV_Iv(ModRmTarget, Word),
MOV_AL0b(Byte),
MOV_AX0v(Word),
MOV_0bAL(Byte),
MOV_0vAX(Word),
MOV_ALIb(Byte),
MOV_CLIb(Byte),
MOV_DLIb(Byte),
MOV_BLIb(Byte),
MOV_AHIb(Byte),
MOV_CHIb(Byte),
MOV_DHIb(Byte),
MOV_BHIb(Byte),
MOV_AXIv(Word),
MOV_CXIv(Word),
MOV_DXIv(Word),
MOV_BXIv(Word),
MOV_SPIv(Word),
MOV_BPIv(Word),
MOV_SIIv(Word),
MOV_DIIv(Word),
// LEA
LEA(ModRmTarget, Register),
// Sign extensions
CBW,
CWD,
// CALL
CALL_p(Pointer32),
CALL_v(usize),
CALL_Mod(ModRmTarget),
CALL_Mp(Pointer16),
// JUMP
JMP_p(Pointer32),
JMP_b(usize), // parses IByte, but stores as isize
JMP_v(usize), // parwses IWord, but stores as isize
JMP_Mod(ModRmTarget),
JMP_Mp(Pointer16),
// WAIT
WAIT,
// Push/Pop Flags
PUSHF,
POPF,
SAHF,
LAHF,
// String Byte Operations
MOVSB,
MOVSW,
CMPSB,
CMPSW,
STOSB,
STOSW,
LODSB,
LODSW,
SCASB,
SCASW,
// RET
RET_Iw(Word),
RET,
RETF_Iw(Word),
RETF,
IRET,
// Load ES/DS Register
LES(Register, Pointer16),
LDS(Register, Pointer16),
// NOT
NOT(ModRmTarget),
// NEG
NEG(ModRmTarget),
// MUL
MUL(ModRmTarget),
IMUL(ModRmTarget),
// DIV
DIV(ModRmTarget),
IDIV(ModRmTarget),
// HALT
HLT,
// Shift and Rotate
ROL_b(ModRmTarget, Byte),
ROR_b(ModRmTarget, Byte),
RCL_b(ModRmTarget, Byte),
RCR_b(ModRmTarget, Byte),
SHL_b(ModRmTarget, Byte),
SHR_b(ModRmTarget, Byte),
SAR_b(ModRmTarget, Byte),
ROL_fromReg(ModRmTarget, Register),
ROR_fromReg(ModRmTarget, Register),
RCL_fromReg(ModRmTarget, Register),
RCR_fromReg(ModRmTarget, Register),
SHL_fromReg(ModRmTarget, Register),
SHR_fromReg(ModRmTarget, Register),
SAR_fromReg(ModRmTarget, Register),
// IN
IN_AL(Byte),
IN_AX(Byte),
IN_ALDX,
IN_AXDX,
// OUT
OUT_AL(Byte),
OUT_AX(Byte),
OUT_ALDX,
OUT_AXDX,
// INT
INT(Byte),
INTO,
// Flag Manipulation
CLC,
STC,
CLI,
STI,
CLD,
STD,
CMC,
// Repeat prefix
REPNZ,
REPZ,
// Adjust
AAM(Byte),
AAD(Byte),
// MISC
XLAT,
LOCK,
}
impl fmt::Display for Mnemonic {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::ADD_FromReg(target, reg) => write!(f, "add {target}, {reg}"),
Self::ADD_ToReg(target, reg) => write!(f, "add {reg}, {target}"),
Self::ADD_Ib(target, byte) => match target {
ModRmTarget::Memory(_) => write!(f, "add byte ptr {target}, {byte:#04x}"),
ModRmTarget::Register(_) => write!(f, "add byte {target}, {byte:#04x}"),
},
Self::ADD_Iv(target, word) => match target {
ModRmTarget::Memory(_) => write!(f, "add word ptr {target}, {word:#04x}"),
ModRmTarget::Register(_) => write!(f, "add word {target}, {word:#04x}"),
},
Self::ADD_ALIb(byte) => write!(f, "add {}, {byte:#04x}", Register::AL),
Self::ADD_AXIv(word) => write!(f, "add {}, {word:#04x}", Register::AX),
Self::PUSH_R(reg) => write!(f, "push {reg}"),
Self::PUSH_S(reg) => write!(f, "push {reg}"),
Self::PUSH_Mod(target) => write!(f, "push {target}"),
Self::POP_R(reg) => write!(f, "pop {reg}"),
Self::POP_S(reg) => write!(f, "pop {reg}"),
Self::POP_M(mem) => write!(f, "pop {mem}"),
Self::OR_FromReg(target, reg) => write!(f, "or {target}, {reg}"),
Self::OR_ToReg(target, reg) => write!(f, "or {reg}, {target}"),
Self::OR_Ib(target, byte) => match target {
ModRmTarget::Memory(_) => write!(f, "or byte ptr {target}, {byte:#04x}"),
ModRmTarget::Register(_) => write!(f, "or byte {target}, {byte:#04x}"),
},
Self::OR_Iv(target, word) => match target {
ModRmTarget::Memory(_) => write!(f, "or word ptr {target}, {word:#04x}"),
ModRmTarget::Register(_) => write!(f, "or word {target}, {word:#04x}"),
},
Self::OR_ALIb(byte) => write!(f, "or {}, {byte:#04x}", Register::AL),
Self::OR_AXIv(word) => write!(f, "or {}, {word:#04x}", Register::AX),
Self::ADC_FromReg(target, reg) => write!(f, "adc {target}, {reg}"),
Self::ADC_ToReg(target, reg) => write!(f, "adc {reg}, {target}"),
Self::ADC_Ib(target, byte) => match target {
ModRmTarget::Memory(_) => write!(f, "adc byte ptr {target}, {byte:#04x}"),
ModRmTarget::Register(_) => write!(f, "adc byte {target}, {byte:#04x}"),
},
Self::ADC_Iv(target, word) => match target {
ModRmTarget::Memory(_) => write!(f, "adc word ptr {target}, {word:#04x}"),
ModRmTarget::Register(_) => write!(f, "adc word {target}, {word:#04x}"),
},
Self::ADC_ALIb(byte) => write!(f, "adc {}, {byte:#04x}", Register::AL),
Self::ADC_AXIv(word) => write!(f, "adc {}, {word:#04x}", Register::AX),
Self::SBB_FromReg(target, reg) => write!(f, "sbb {target}, {reg}"),
Self::SBB_ToReg(target, reg) => write!(f, "sbb {reg}, {target}"),
Self::SBB_Ib(target, byte) => match target {
ModRmTarget::Memory(_) => write!(f, "sbb byte ptr {target}, {byte:#04x}"),
ModRmTarget::Register(_) => write!(f, "sbb byte {target}, {byte:#04x}"),
},
Self::SBB_Iv(target, word) => match target {
ModRmTarget::Memory(_) => write!(f, "sbb word ptr {target}, {word:#04x}"),
ModRmTarget::Register(_) => write!(f, "sbb word {target}, {word:#04x}"),
},
Self::SBB_ALIb(byte) => write!(f, "sbb {}, {byte:#04x}", Register::AL),
Self::SBB_AXIv(word) => write!(f, "sbb {}, {word:#04x}", Register::AX),
Self::AND_FromReg(target, reg) => write!(f, "and {target}, {reg}"),
Self::AND_ToReg(target, reg) => write!(f, "and {reg}, {target}"),
Self::AND_Ib(target, byte) => match target {
ModRmTarget::Memory(_) => write!(f, "and byte ptr {target}, {byte:#04x}"),
ModRmTarget::Register(_) => write!(f, "and byte {target}, {byte:#04x}"),
},
Self::AND_Iv(target, word) => match target {
ModRmTarget::Memory(_) => write!(f, "and word ptr {target}, {word:#04x}"),
ModRmTarget::Register(_) => write!(f, "and word {target}, {word:#04x}"),
},
Self::AND_ALIb(byte) => write!(f, "and {}, {byte:#04x}", Register::AL),
Self::AND_AXIv(word) => write!(f, "and {}, {word:#04x}", Register::AX),
Self::OVERRIDE(reg) => write!(f, "{reg}:"),
Self::DAA => write!(f, "daa"),
Self::DAS => write!(f, "das"),
Self::AAA => write!(f, "aaa"),
Self::AAS => write!(f, "aas"),
Self::SUB_FromReg(target, reg) => write!(f, "sub {target}, {reg}"),
Self::SUB_ToReg(target, reg) => write!(f, "sub {reg}, {target}"),
Self::SUB_Ib(target, byte) => match target {
ModRmTarget::Memory(_) => write!(f, "sub byte ptr {target}, {byte:#04x}"),
ModRmTarget::Register(_) => write!(f, "sub byte {target}, {byte:#04x}"),
},
Self::SUB_Iv(target, word) => match target {
ModRmTarget::Memory(_) => write!(f, "sub word ptr {target}, {word:#04x}"),
ModRmTarget::Register(_) => write!(f, "sub word {target}, {word:#04x}"),
},
Self::SUB_ALIb(byte) => write!(f, "sub {}, {byte:#04x}", Register::AL),
Self::SUB_AXIv(word) => write!(f, "sub {}, {word:#04x}", Register::AX),
Self::XOR_FromReg(target, reg) => write!(f, "xor {target}, {reg}"),
Self::XOR_ToReg(target, reg) => write!(f, "xor {reg}, {target}"),
Self::XOR_Ib(target, byte) => match target {
ModRmTarget::Memory(_) => write!(f, "xor byte ptr {target}, {byte:#04x}"),
ModRmTarget::Register(_) => write!(f, "xor byte {target}, {byte:#04x}"),
},
Self::XOR_Iv(target, word) => match target {
ModRmTarget::Memory(_) => write!(f, "xor word ptr {target}, {word:#04x}"),
ModRmTarget::Register(_) => write!(f, "xor word {target}, {word:#04x}"),
},
Self::XOR_ALIb(byte) => write!(f, "xor {}, {byte:#04x}", Register::AL),
Self::XOR_AXIv(word) => write!(f, "xor {}, {word:#04x}", Register::AX),
Self::CMP_FromReg(target, reg) => write!(f, "cmp {target}, {reg}"),
Self::CMP_ToReg(target, reg) => write!(f, "cmp {reg}, {target}"),
Self::CMP_Ib(target, byte) => match target {
ModRmTarget::Memory(_) => write!(f, "cmp byte ptr {target}, {byte:#04x}"),
ModRmTarget::Register(_) => write!(f, "cmp byte {target}, {byte:#04x}"),
},
Self::CMP_Iv(target, word) => match target {
ModRmTarget::Memory(_) => write!(f, "cmp word ptr {target}, {word:#04x}"),
ModRmTarget::Register(_) => write!(f, "cmp word {target}, {word:#04x}"),
},
Self::CMP_ALIb(byte) => write!(f, "cmp {}, {byte:#04x}", Register::AL),
Self::CMP_AXIv(word) => write!(f, "cmp {}, {word:#04x}", Register::AX),
Self::INC_Reg(reg) => write!(f, "inc {reg}"),
Self::INC_Mod(target) => write!(f, "inc {target}"),
Self::DEC_Reg(reg) => write!(f, "dec {reg}"),
Self::DEC_Mod(target) => write!(f, "dec {target}"),
Self::JO(ibyte) => write!(f, "jo {ibyte:#04x}"),
Self::JNO(ibyte) => write!(f, "jno {ibyte:#04x}"),
Self::JB(ibyte) => write!(f, "jb {ibyte:#04x}"),
Self::JNB(ibyte) => write!(f, "jnb {ibyte:#04x}"),
Self::JZ(ibyte) => write!(f, "jz {ibyte:#04x}"),
Self::JNZ(ibyte) => write!(f, "jnz {ibyte:#04x}"),
Self::JBE(ibyte) => write!(f, "jbe {ibyte:#04x}"),
Self::JA(ibyte) => write!(f, "ja {ibyte:#04x}"),
Self::JS(ibyte) => write!(f, "js {ibyte:#04x}"),
Self::JNS(ibyte) => write!(f, "jns {ibyte:#04x}"),
Self::JPE(ibyte) => write!(f, "jpe {ibyte:#04x}"),
Self::JPO(ibyte) => write!(f, "jpo {ibyte:#04x}"),
Self::JL(ibyte) => write!(f, "jl {ibyte:#04x}"),
Self::JGE(ibyte) => write!(f, "jge {ibyte:#04x}"),
Self::JLE(ibyte) => write!(f, "jle {ibyte:#04x}"),
Self::JG(ibyte) => write!(f, "jg {ibyte:#04x}"),
Self::LOOPNZ(ibyte) => write!(f, "loopnz {ibyte:#04x}"),
Self::LOOPZ(ibyte) => write!(f, "loopz {ibyte:#04x}"),
Self::LOOP(ibyte) => write!(f, "loop {ibyte:#04x}"),
Self::JCXZ(ibyte) => write!(f, "jcxz {ibyte:#04x}"),
Self::TEST(target, reg) => write!(f, "test {target}, {reg}"),
Self::TEST_Ib(target, byte) => write!(f, "test byte ptr {target}, {byte:#04x}"),
Self::TEST_Iv(target, word) => write!(f, "test word ptr {target}, {word:#04x}"),
Self::TEST_ALIb(byte) => write!(f, "test {}, {byte:#04x}", Register::AL),
Self::TEST_AXIv(word) => write!(f, "test {}, {word:#04x}", Register::AX),
Self::XCHG(target, reg) => write!(f, "xchg {target}, {reg}"),
Self::XCHG_AX(reg) => write!(f, "xchg, {reg}, {}", Register::AX),
Self::MOV_FromReg(target, reg) => write!(f, "mov {target}, {reg}"),
Self::MOV_ToReg(target, reg) => write!(f, "mov {reg}, {target}"),
Self::MOV_FromSReg(target, reg) => write!(f, "mov {target}, {reg}"),
Self::MOV_ToSReg(target, reg) => write!(f, "mov {reg}, {target}"),
Self::MOV_Ib(target, byte) => match target {
ModRmTarget::Memory(_) => write!(f, "mov byte ptr {target}, {byte:#04x}"),
ModRmTarget::Register(_) => write!(f, "mov byte {target}, {byte:#04x}"),
},
Self::MOV_Iv(target, word) => match target {
ModRmTarget::Memory(_) => write!(f, "mov word ptr {target}, {word:#04x}"),
ModRmTarget::Register(_) => write!(f, "mov word {target}, {word:#04x}"),
},
Self::MOV_AL0b(byte) => write!(f, "mov {}, {byte:#04x}", Register::AL),
Self::MOV_AX0v(word) => write!(f, "mov {}, {word:#04x}", Register::AX),
Self::MOV_0bAL(byte) => write!(f, "mov {byte:#04x}, {}", Register::AL),
Self::MOV_0vAX(word) => write!(f, "mov {word:#04x}, {}", Register::AX),
Self::MOV_ALIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::AL),
Self::MOV_CLIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::CL),
Self::MOV_DLIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::DL),
Self::MOV_BLIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::BL),
Self::MOV_AHIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::AH),
Self::MOV_CHIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::CH),
Self::MOV_DHIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::DH),
Self::MOV_BHIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::BH),
Self::MOV_AXIv(word) => write!(f, "mov {}, {word:#04x}", Register::AX),
Self::MOV_CXIv(word) => write!(f, "mov {}, {word:#04x}", Register::CX),
Self::MOV_DXIv(word) => write!(f, "mov {}, {word:#04x}", Register::DX),
Self::MOV_BXIv(word) => write!(f, "mov {}, {word:#04x}", Register::BX),
Self::MOV_SPIv(word) => write!(f, "mov {}, {word:#04x}", Register::SP),
Self::MOV_BPIv(word) => write!(f, "mov {}, {word:#04x}", Register::BP),
Self::MOV_SIIv(word) => write!(f, "mov {}, {word:#04x}", Register::SI),
Self::MOV_DIIv(word) => write!(f, "mov {}, {word:#04x}", Register::DI),
Self::LEA(mem, reg) => write!(f, "lea {}, {}", reg, mem),
Self::CBW => write!(f, "cbw"),
Self::CWD => write!(f, "cwd"),
Self::CALL_p(ptr) => write!(f, "call {ptr}"),
Self::CALL_v(word) => write!(f, "call {word:#04x}"),
Self::CALL_Mod(target) => write!(f, "call {target}"),
Self::CALL_Mp(ptr) => write!(f, "call {ptr}"),
Self::JMP_p(ptr) => write!(f, "jmp {ptr}"),
Self::JMP_b(byte) => write!(f, "jmp {byte:#04x}"),
Self::JMP_v(word) => write!(f, "jmp {word:#04x}"),
Self::JMP_Mod(target) => write!(f, "jmp {target}"),
Self::JMP_Mp(ptr) => write!(f, "jmp {ptr}"),
Self::WAIT => write!(f, "wait"),
Self::PUSHF => write!(f, "pushf"),
Self::POPF => write!(f, "popf"),
Self::SAHF => write!(f, "sahf"),
Self::LAHF => write!(f, "lahf"),
Self::MOVSB => write!(f, "movsb"),
Self::MOVSW => write!(f, "movsw"),
Self::CMPSB => write!(f, "cmpsb"),
Self::CMPSW => write!(f, "cmpsw"),
Self::STOSB => write!(f, "stosb"),
Self::STOSW => write!(f, "stosw"),
Self::LODSB => write!(f, "lodsb"),
Self::LODSW => write!(f, "lodsw"),
Self::SCASB => write!(f, "scasb"),
Self::SCASW => write!(f, "scasw"),
Self::RET_Iw(word) => write!(f, "ret {word:#04x}"),
Self::RET => write!(f, "ret"),
Self::RETF_Iw(word) => write!(f, "retf {word:#04x}"),
Self::RETF => write!(f, "retf"),
Self::IRET => write!(f, "iret"),
Self::LES(reg, mem) => write!(f, "les {reg}, ptr {mem}"),
Self::LDS(reg, mem) => write!(f, "lds {reg}, ptr {mem}"),
Self::NOT(target) => write!(f, "not {target}"),
Self::NEG(target) => write!(f, "neg {target}"),
Self::MUL(target) => write!(f, "mul {target}"),
Self::IMUL(target) => write!(f, "imul {target}"),
Self::DIV(target) => write!(f, "mdiv {target}"),
Self::IDIV(target) => write!(f, "idiv {target}"),
Self::HLT => write!(f, "hlt"),
Self::ROL_b(target, byte) => write!(f, "rol byte ptr {target}, {byte:#04x}"),
Self::ROR_b(target, byte) => write!(f, "ror byte ptr {target}, {byte:#04x}"),
Self::RCL_b(target, byte) => write!(f, "rcl byte ptr {target}, {byte:#04x}"),
Self::RCR_b(target, byte) => write!(f, "rcr byte ptr {target}, {byte:#04x}"),
Self::SHL_b(target, byte) => write!(f, "shl byte ptr {target}, {byte:#04x}"),
Self::SHR_b(target, byte) => write!(f, "shr byte ptr {target}, {byte:#04x}"),
Self::SAR_b(target, byte) => write!(f, "sar byte ptr {target}, {byte:#04x}"),
Self::ROL_fromReg(target, reg) => write!(f, "rol {target}, {reg}"),
Self::ROR_fromReg(target, reg) => write!(f, "ror {target}, {reg}"),
Self::RCL_fromReg(target, reg) => write!(f, "rcl {target}, {reg}"),
Self::RCR_fromReg(target, reg) => write!(f, "rcr {target}, {reg}"),
Self::SHL_fromReg(target, reg) => write!(f, "shl {target}, {reg}"),
Self::SHR_fromReg(target, reg) => write!(f, "shr {target}, {reg}"),
Self::SAR_fromReg(target, reg) => write!(f, "sar {target}, {reg}"),
Self::IN_AL(byte) => write!(f, "in byte ptr {}, {byte:#04x}", Register::AL),
Self::IN_AX(byte) => write!(f, "in byte ptr {}, {byte:#04x}", Register::AX),
Self::IN_ALDX => write!(f, "in {}, {}", Register::AL, Register::DX),
Self::IN_AXDX => write!(f, "in {}, {}", Register::AX, Register::DX),
Self::OUT_AL(byte) => write!(f, "out byte ptr {}, {byte:#04x}", Register::AL),
Self::OUT_AX(byte) => write!(f, "out byte ptr {}, {byte:#04x}", Register::AX),
Self::OUT_ALDX => write!(f, "out {}, {}", Register::AL, Register::DX),
Self::OUT_AXDX => write!(f, "out {}, {}", Register::AX, Register::DX),
Self::INT(byte) => write!(f, "int {byte:#04x}"),
Self::INTO => write!(f, "into"),
Self::CLC => write!(f, "clc"),
Self::STC => write!(f, "stc"),
Self::CLI => write!(f, "cli"),
Self::STI => write!(f, "sti"),
Self::CLD => write!(f, "cld"),
Self::STD => write!(f, "std"),
Self::CMC => write!(f, "cmc"),
Self::REPNZ => write!(f, "repnz"),
Self::REPZ => write!(f, "repz"),
Self::AAM(byte) => write!(f, "aam {byte:#04x}"),
Self::AAD(byte) => write!(f, "aad {byte:#04x}"),
Self::XLAT => write!(f, "xlat"),
Self::LOCK => write!(f, "lock"),
_ => write!(f, "??? ??, ??"),
}
}
}