Advance this even further.
disassembler/decoder.rs:
use crate::disassembler::instruction::{Instruction, Operand};
use std::collections::HashMap;

/// Decoder for x86_64 architecture
pub struct Decoder {
    /// Opcode mapping: opcode bytes to [OpcodeInfo]
    opcode_map: HashMap<Vec<u8>, Vec<OpcodeInfo>>,
}

/// Information about an opcode
#[derive(Debug, Clone)]
struct OpcodeInfo {
    mnemonic: &'static str,
    opcode_length: usize, // Number of bytes in the opcode
    operands: Vec<OperandSpec>,
    has_modrm: bool,
    has_sib: bool,
    rex_required: bool,
    // Additional fields can be added as needed (e.g., flags)
}

/// Specification for an operand in an instruction
#[derive(Debug, Clone)]
struct OperandSpec {
    operand_type: OperandType,
    size: OperandSize,
}

/// Sizes of operands
#[derive(Debug, Clone, PartialEq)]
enum OperandSize {
    Byte,
    Word,
    Dword,
    Qword,
}

/// Types of operands for decoding purposes
#[derive(Debug, Clone)]
enum OperandType {
    Register,
    Immediate,
    Memory,
    RelativeAddress,
}

impl Decoder {
    /// Initialize a new Decoder for x86_64
    pub fn new_x86_64() -> Self {
        let mut opcode_map: HashMap<Vec<u8>, Vec<OpcodeInfo>> = HashMap::new();

        // Example: Single-byte opcodes
        // NOP: 0x90
        opcode_map.insert(
            vec![0x90],
            vec![OpcodeInfo {
                mnemonic: "NOP",
                opcode_length: 1,
                operands: vec![],
                has_modrm: false,
                has_sib: false,
                rex_required: false,
            }],
        );

        // RET: 0xC3
        opcode_map.insert(
            vec![0xC3],
            vec![OpcodeInfo {
                mnemonic: "RET",
                opcode_length: 1,
                operands: vec![],
                has_modrm: false,
                has_sib: false,
                rex_required: false,
            }],
        );

        // MOV r64, imm32: 0xB8 + rd
        for rd in 0..8 {
            let opcode = vec![0xB8 + rd];
            opcode_map.entry(opcode.clone()).or_insert_with(Vec::new).push(OpcodeInfo {
                mnemonic: "MOV",
                opcode_length: 1,
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Register,
                        size: OperandSize::Qword,
                    },
                    OperandSpec {
                        operand_type: OperandType::Immediate,
                        size: OperandSize::Dword,
                    },
                ],
                has_modrm: false,
                has_sib: false,
                rex_required: rd >= 4, // REX prefix needed for extended registers
            });
        }

        // CALL rel32: 0xE8
        opcode_map.insert(
            vec![0xE8],
            vec![OpcodeInfo {
                mnemonic: "CALL",
                opcode_length: 1,
                operands: vec![OperandSpec {
                    operand_type: OperandType::RelativeAddress,
                    size: OperandSize::Dword,
                }],
                has_modrm: false,
                has_sib: false,
                rex_required: false,
            }],
        );

        // JMP rel8: 0xEB
        opcode_map.insert(
            vec![0xEB],
            vec![OpcodeInfo {
                mnemonic: "JMP",
                opcode_length: 1,
                operands: vec![OperandSpec {
                    operand_type: OperandType::RelativeAddress,
                    size: OperandSize::Byte,
                }],
                has_modrm: false,
                has_sib: false,
                rex_required: false,
            }],
        );

        // More opcodes can be added here...

        // Multi-byte opcodes (e.g., 0x0F prefix)
        // Example: ADD r/m32, r32: 0x01 /r
        opcode_map.insert(
            vec![0x01],
            vec![OpcodeInfo {
                mnemonic: "ADD",
                opcode_length: 1,
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Memory, // r/m32
                        size: OperandSize::Dword,
                    },
                    OperandSpec {
                        operand_type: OperandType::Register, // r32
                        size: OperandSize::Dword,
                    },
                ],
                has_modrm: true,
                has_sib: false,
                rex_required: false,
            }],
        );

        // Initialize the Decoder with the opcode map
        Decoder { opcode_map }
    }

    /// Decode a single instruction from the given bytes starting at `address`
    pub fn decode(&self, bytes: &[u8], address: u64) -> Result<Instruction, DecodeError> {
        if bytes.is_empty() {
            return Err(DecodeError::IncompleteInstruction);
        }

        let mut offset = 0;
        let mut rex_prefix = RexPrefix::default();
        // Handle possible REX prefix
        if bytes[offset] & 0xF0 == 0x40 {
            rex_prefix = RexPrefix::from_byte(bytes[offset])?;
            offset += 1;
            if offset >= bytes.len() {
                return Err(DecodeError::IncompleteInstruction);
            }
        }

        // Attempt to match opcodes, starting with the longest possible
        let max_opcode_length = self
            .opcode_map
            .keys()
            .map(|k| k.len())
            .max()
            .unwrap_or(1);
        let mut matched_opcode_info: Option<(&OpcodeInfo, usize)> = None;

        for length in (1..=max_opcode_length).rev() {
            if offset + length > bytes.len() {
                continue;
            }
            let opcode_bytes = bytes[offset..offset + length].to_vec();
            if let Some(op_infos) = self.opcode_map.get(&opcode_bytes) {
                // In case of multiple OpcodeInfo (due to overlapping opcodes), select based on REX requirements
                for op_info in op_infos {
                    if op_info.rex_required && !rex_prefix.is_present() {
                        continue;
                    }
                    matched_opcode_info = Some((op_info, length));
                    break;
                }
                if matched_opcode_info.is_some() {
                    break;
                }
            }
        }

        let (opcode_info, opcode_length) = match matched_opcode_info {
            Some(m) => m,
            None => return Err(DecodeError::UnknownOpcode),
        };

        offset += opcode_length;
        let mut operands = Vec::new();

        // Process operands
        for operand_spec in &opcode_info.operands {
            match operand_spec.operand_type {
                OperandType::Register => {
                    // Registers are typically encoded in opcode or ModR/M; simplified here
                    let reg = self.decode_register(&rex_prefix)?;
                    operands.push(Operand::Register(reg));
                }
                OperandType::Immediate => {
                    let imm = self.read_immediate(bytes, offset, &operand_spec.size)?;
                    offset += operand_spec.size.bytes();
                    operands.push(Operand::Immediate(imm));
                }
                OperandType::RelativeAddress => {
                    let rel = self.read_immediate(bytes, offset, &operand_spec.size)? as i64;
                    let instr_size = opcode_length + operand_spec.size.bytes();
                    offset += operand_spec.size.bytes();
                    let target = address
                        .wrapping_add(instr_size as u64)
                        .wrapping_add(rel as u64);
                    operands.push(Operand::RelativeAddress(target));
                }
                OperandType::Memory => {
                    if !opcode_info.has_modrm {
                        return Err(DecodeError::MissingModRM);
                    }
                    let modrm = if offset < bytes.len() {
                        bytes[offset]
                    } else {
                        return Err(DecodeError::IncompleteInstruction);
                    };
                    offset += 1;

                    let mod_field = (modrm & 0b11000000) >> 6;
                    let reg_field = (modrm & 0b00111000) >> 3;
                    let rm_field = modrm & 0b00000111;

                    // Decode SIB if needed
                    let (base, index, scale, displacement, sib_offset) =
                        if rm_field == 4 && mod_field != 3 {
                            // SIB byte is present
                            if offset >= bytes.len() {
                                return Err(DecodeError::IncompleteInstruction);
                            }
                            let sib = bytes[offset];
                            offset += 1;
                            self.decode_sib(sib)?
                        } else {
                            ("".to_string(), "".to_string(), 1, 0, 0)
                        };

                    // Decode displacement
                    let displacement = match mod_field {
                        0 => {
                            if rm_field == 5 {
                                // disp32
                                if offset + 3 >= bytes.len() {
                                    return Err(DecodeError::IncompleteInstruction);
                                }
                                let disp = i32::from_le_bytes([
                                    bytes[offset],
                                    bytes[offset + 1],
                                    bytes[offset + 2],
                                    bytes[offset + 3],
                                ]) as i64;
                                offset += 4;
                                disp
                            } else {
                                0
                            }
                        }
                        1 => {
                            // disp8
                            if offset >= bytes.len() {
                                return Err(DecodeError::IncompleteInstruction);
                            }
                            let disp = bytes[offset] as i8 as i64;
                            offset += 1;
                            disp
                        }
                        2 => {
                            // disp32
                            if offset + 3 >= bytes.len() {
                                return Err(DecodeError::IncompleteInstruction);
                            }
                            let disp = i32::from_le_bytes([
                                bytes[offset],
                                bytes[offset + 1],
                                bytes[offset + 2],
                                bytes[offset + 3],
                            ]) as i64;
                            offset += 4;
                            disp
                        }
                        _ => 0,
                    };

                    // Decode base register
                    let base_reg = if rm_field == 5 && mod_field == 0 {
                        // No base, disp32 is used as absolute address
                        String::from("")
                    } else {
                        self.decode_register_field(rm_field, &rex_prefix)?
                    };

                    // Final memory operand
                    operands.push(Operand::Memory {
                        base: base_reg,
                        index,
                        scale,
                        displacement,
                    });
                }
            }
        }

        // Extract the bytes of the instruction
        let instr_bytes = bytes[..offset].to_vec();

        Ok(Instruction {
            mnemonic: opcode_info.mnemonic.to_string(),
            operands,
            address,
            bytes: instr_bytes,
        })
    }

    /// Decode the register operand based on REX prefix
    fn decode_register(&self, rex: &RexPrefix) -> Result<String, DecodeError> {
        // Placeholder: In a complete implementation, the register is determined by the context (e.g., opcode)
        // Here, returning a generic register for demonstration
        Ok("rax".to_string())
    }

    /// Decode a register field from ModR/M or other encoding
    fn decode_register_field(
        &self,
        reg: u8,
        rex: &RexPrefix,
    ) -> Result<String, DecodeError> {
        // Extended registers with REX.B
        let extended = if rex.has_b_extension() { 8 } else { 0 };
        let registers = [
            "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
            "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
        ];
        if (reg as usize) + extended >= registers.len() {
            return Err(DecodeError::InvalidRegister);
        }
        Ok(registers[(reg as usize) + extended].to_string())
    }

    /// Decode the SIB byte
    fn decode_sib(&self, sib: u8) -> Result<(String, String, i32, i64, usize), DecodeError> {
        let scale = match (sib & 0b11000000) >> 6 {
            0 => 1,
            1 => 2,
            2 => 4,
            3 => 8,
            _ => 1, // Should not happen
        };
        let index = (sib & 0b00111000) >> 3;
        let base = sib & 0b00000111;

        let index_reg = if index == 4 {
            // No index
            "".to_string()
        } else {
            self.decode_sib_register(index)?
        };

        let base_reg = self.decode_register_field(base, &RexPrefix::default())?; // Simplified

        Ok((
            base_reg,
            index_reg,
            scale,
            0, // Placeholder for displacement
            0, // Placeholder for additional offset
        ))
    }

    /// Decode SIB register
    fn decode_sib_register(&self, reg: u8) -> Result<String, DecodeError> {
        let registers = [
            "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
            "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
        ];
        if reg as usize >= registers.len() {
            return Err(DecodeError::InvalidRegister);
        }
        Ok(registers[reg as usize].to_string())
    }

    /// Read immediate value from bytes based on operand size
    fn read_immediate(
        &self,
        bytes: &[u8],
        offset: usize,
        size: &OperandSize,
    ) -> Result<u64, DecodeError> {
        match size {
            OperandSize::Byte => {
                if offset >= bytes.len() {
                    return Err(DecodeError::IncompleteInstruction);
                }
                Ok(bytes[offset] as u64)
            }
            OperandSize::Word => {
                if offset + 1 >= bytes.len() {
                    return Err(DecodeError::IncompleteInstruction);
                }
                Ok(u16::from_le_bytes([bytes[offset], bytes[offset + 1]]) as u64)
            }
            OperandSize::Dword => {
                if offset + 3 >= bytes.len() {
                    return Err(DecodeError::IncompleteInstruction);
                }
                Ok(u32::from_le_bytes([
                    bytes[offset],
                    bytes[offset + 1],
                    bytes[offset + 2],
                    bytes[offset + 3],
                ]) as u64)
            }
            OperandSize::Qword => {
                if offset + 7 >= bytes.len() {
                    return Err(DecodeError::IncompleteInstruction);
                }
                Ok(u64::from_le_bytes([
                    bytes[offset],
                    bytes[offset + 1],
                    bytes[offset + 2],
                    bytes[offset + 3],
                    bytes[offset + 4],
                    bytes[offset + 5],
                    bytes[offset + 6],
                    bytes[offset + 7],
                ]))
            }
        }
    }
}

/// Structure representing the REX prefix
#[derive(Debug, Default)]
struct RexPrefix {
    w: bool, // 64-bit operand
    r: bool, // Extension of ModR/M reg field
    x: bool, // Extension of SIB index field
    b: bool, // Extension of ModR/M r/m field
}

impl OperandSize {
    fn bytes(&self) -> usize {
        match self {
            OperandSize::Byte => 1,
            OperandSize::Word => 2,
            OperandSize::Dword => 4,
            OperandSize::Qword => 8,
            // Add other variants as necessary
        }
    }
}

impl RexPrefix {
    /// Create REX prefix from a byte
    fn from_byte(byte: u8) -> Result<Self, DecodeError> {
        if byte & 0b11001111 != 0x40 {
            return Err(DecodeError::InvalidRexPrefix);
        }
        Ok(RexPrefix {
            w: byte & 0b00001000 != 0,
            r: byte & 0b00000100 != 0,
            x: byte & 0b00000010 != 0,
            b: byte & 0b00000001 != 0,
        })
    }

    /// Check if REX prefix is present
    fn is_present(&self) -> bool {
        self.w || self.r || self.x || self.b
    }

    /// Extension for base registers
    fn has_b_extension(&self) -> bool {
        self.b
    }
}

/// Errors that can occur during decoding
#[derive(Debug)]
pub enum DecodeError {
    UnknownOpcode,
    IncompleteInstruction,
    InvalidRegister,
    MissingModRM,
    InvalidRexPrefix,
    // More error variants can be added as needed
}

impl std::fmt::Display for DecodeError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match &self {
            DecodeError::UnknownOpcode => write!(f, "Unknown opcode"),
            DecodeError::IncompleteInstruction => write!(f, "Incomplete instruction bytes"),
            DecodeError::InvalidRegister => write!(f, "Invalid register encoding"),
            DecodeError::MissingModRM => write!(f, "Missing ModR/M byte for instruction"),
            DecodeError::InvalidRexPrefix => write!(f, "Invalid REX prefix byte"),
        }
    }
}

impl std::error::Error for DecodeError {}

disassembler/instruction.rs:

#[derive(Debug, Clone)]
pub enum Operand {
    Register(String),
    Immediate(u64),
    Memory {
        base: String,
        index: String,
        scale: i32,
        displacement: i64,
    },
    RelativeAddress(u64),
    Label(String),
}

#[derive(Debug, Clone)]
pub struct Instruction {
    pub mnemonic: String,
    pub operands: Vec<Operand>,
    pub address: u64,
    pub bytes: Vec<u8>,
}

disassembler/mod.rs:
pub mod decoder;
pub mod instruction;

use decoder::Decoder;
use instruction::{Instruction, Operand};

/// Disassembler engine
pub struct Disassembler {
    decoder: Decoder,
}

impl Disassembler {
    /// Create a new Disassembler for the specified architecture
    pub fn new(arch: &str) -> Self {
        match arch {
            "x86_64" => Disassembler {
                decoder: Decoder::new_x86_64(),
            },
            _ => {
                panic!("Unsupported architecture: {}", arch);
            }
        }
    }

    /// Disassemble a slice of bytes starting at a given address
    pub fn disassemble(&self, code: &[u8], start_address: u64) -> Vec<Instruction> {
        let mut instructions = Vec::new();
        let mut offset = 0;
        let code_len = code.len();
        let mut current_address = start_address;

        while offset < code_len {
            match self.decoder.decode(&code[offset..], current_address) {
                Ok(instr) => {
                    instructions.push(instr.clone());
                    let instr_len = instr.bytes.len();
                    if instr_len == 0 {
                        // Prevent infinite loop on zero-length instruction
                        break;
                    }
                    offset += instr_len;
                    current_address += instr_len as u64;
                }
                Err(_) => {
                    // Handle unknown opcode as a single byte
                    instructions.push(Instruction {
                        mnemonic: "db".to_string(),
                        operands: vec![Operand::Immediate(code[offset] as u64)],
                        address: current_address,
                        bytes: vec![code[offset]],
                    });
                    offset += 1;
                    current_address += 1;
                }
            }
        }

        instructions
    }
}