Massively add to/improve this code.
// instruction.rs
use std::fmt;

/// Defines the CPU registers.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Register {
    R0,
    R1,
    R2,
    R3,
    R4,
    R5,
    R6,
    R7,
    Unknown(u8),
}

impl fmt::Display for Register {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Register::R0 => write!(f, "R0"),
            Register::R1 => write!(f, "R1"),
            Register::R2 => write!(f, "R2"),
            Register::R3 => write!(f, "R3"),
            Register::R4 => write!(f, "R4"),
            Register::R5 => write!(f, "R5"),
            Register::R6 => write!(f, "R6"),
            Register::R7 => write!(f, "R7"),
            Register::Unknown(code) => write!(f, "R{}", code),
        }
    }
}

/// Defines various operand types for instructions.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operand {
    Register(Register),
    Immediate(u16),
    Address(u16),
    // Future extensions can include MemoryAddr, Indirect, etc.
}

impl fmt::Display for Operand {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Operand::Register(reg) => write!(f, "{}", reg),
            Operand::Immediate(val) => write!(f, "0x{:04X}", val),
            Operand::Address(addr) => write!(f, "0x{:04X}", addr),
        }
    }
}

/// Defines the complete set of instructions supported by the CPU.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Instruction {
    /// LOAD Register, Immediate
    Load { register: Register, value: u16 },
    /// ADD Register, Register
    Add { dest: Register, src: Register },
    /// SUB Register, Register
    Sub { dest: Register, src: Register },
    /// MUL Register, Register
    Mul { dest: Register, src: Register },
    /// DIV Register, Register
    Div { dest: Register, src: Register },
    /// AND Register, Register
    And { dest: Register, src: Register },
    /// OR Register, Register
    Or { dest: Register, src: Register },
    /// XOR Register, Register
    Xor { dest: Register, src: Register },
    /// NOT Register
    Not { register: Register },
    /// SHL Register, Immediate
    Shl { register: Register, shift: u8 },
    /// SHR Register, Immediate
    Shr { register: Register, shift: u8 },
    /// MOV Register, Register
    Mov { dest: Register, src: Register },
    /// INC Register
    Inc { register: Register },
    /// DEC Register
    Dec { register: Register },
    /// JMP Address
    Jmp { address: u16 },
    /// CALL Address
    Call { address: u16 },
    /// RET
    Ret,
    /// CMP Register, Register
    Cmp { reg1: Register, reg2: Register },
    /// JE Address
    Je { address: u16 },
    /// JNE Address
    Jne { address: u16 },
    /// PUSH Register
    Push { register: Register },
    /// POP Register
    Pop { register: Register },
    /// PUSHF
    Pushf,
    /// POPF
    Popf,
    /// NOP
    Nop,
    /// HALT
    Halt,
    /// Unknown or invalid instruction
    Unknown { opcode: u8, bytes: Vec<u8> },
}

impl fmt::Display for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Instruction::Load { register, value } => write!(f, "LOAD {}, {}", register, value),
            Instruction::Add { dest, src } => write!(f, "ADD {}, {}", dest, src),
            Instruction::Sub { dest, src } => write!(f, "SUB {}, {}", dest, src),
            Instruction::Mul { dest, src } => write!(f, "MUL {}, {}", dest, src),
            Instruction::Div { dest, src } => write!(f, "DIV {}, {}", dest, src),
            Instruction::And { dest, src } => write!(f, "AND {}, {}", dest, src),
            Instruction::Or { dest, src } => write!(f, "OR {}, {}", dest, src),
            Instruction::Xor { dest, src } => write!(f, "XOR {}, {}", dest, src),
            Instruction::Not { register } => write!(f, "NOT {}", register),
            Instruction::Shl { register, shift } => write!(f, "SHL {}, {}", register, shift),
            Instruction::Shr { register, shift } => write!(f, "SHR {}, {}", register, shift),
            Instruction::Mov { dest, src } => write!(f, "MOV {}, {}", dest, src),
            Instruction::Inc { register } => write!(f, "INC {}", register),
            Instruction::Dec { register } => write!(f, "DEC {}", register),
            Instruction::Jmp { address } => write!(f, "JMP {}", address),
            Instruction::Call { address } => write!(f, "CALL {}", address),
            Instruction::Ret => write!(f, "RET"),
            Instruction::Cmp { reg1, reg2 } => write!(f, "CMP {}, {}", reg1, reg2),
            Instruction::Je { address } => write!(f, "JE {}", address),
            Instruction::Jne { address } => write!(f, "JNE {}", address),
            Instruction::Push { register } => write!(f, "PUSH {}", register),
            Instruction::Pop { register } => write!(f, "POP {}", register),
            Instruction::Pushf => write!(f, "PUSHF"),
            Instruction::Popf => write!(f, "POPF"),
            Instruction::Nop => write!(f, "NOP"),
            Instruction::Halt => write!(f, "HALT"),
            Instruction::Unknown { opcode, bytes } => {
                write!(f, "UNKNOWN 0x{:02X} {:?}", opcode, bytes)
            }
        }
    }
}

disassembler.rs:
use crate::instruction::{Instruction, Register};
use std::fmt;

/// Opcode definitions for the instruction set.
mod opcodes {
    pub const LOAD: u8 = 0x01;
    pub const ADD: u8 = 0x02;
    pub const SUB: u8 = 0x03;
    pub const MUL: u8 = 0x04;
    pub const DIV: u8 = 0x05;
    pub const AND: u8 = 0x06;
    pub const OR: u8 = 0x07;
    pub const XOR: u8 = 0x08;
    pub const NOT: u8 = 0x09;
    pub const SHL: u8 = 0x0A;
    pub const SHR: u8 = 0x0B;
    pub const MOV: u8 = 0x0C;
    pub const INC: u8 = 0x0D;
    pub const DEC: u8 = 0x0E;
    pub const JMP: u8 = 0x0F;
    pub const CALL: u8 = 0x10;
    pub const RET: u8 = 0x11;
    pub const CMP: u8 = 0x12;
    pub const JE: u8 = 0x13;
    pub const JNE: u8 = 0x14;
    pub const PUSH: u8 = 0x15;
    pub const POP: u8 = 0x16;
    pub const PUSHF: u8 = 0x17;
    pub const POPF: u8 = 0x18;
    pub const NOP: u8 = 0x19;
    pub const HALT: u8 = 0x1A;
    // Add more opcodes as needed...
}

use opcodes::*;

/// Represents the possible errors during disassembly.
#[derive(Debug, Clone)]
pub enum DisassembleError {
    /// Occurs when there are insufficient bytes to decode an instruction.
    UnexpectedEndOfData {
        address: usize,
        expected: usize,
        found: usize,
    },
    /// Occurs when an unknown opcode is encountered.
    UnknownOpcode {
        address: usize,
        opcode: u8,
    },
}

impl fmt::Display for DisassembleError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DisassembleError::UnexpectedEndOfData { address, expected, found } => {
                write!(
                    f,
                    "Unexpected end of data at address {}: expected {} bytes, found {}",
                    address, expected, found
                )
            }
            DisassembleError::UnknownOpcode { address, opcode } => {
                write!(
                    f,
                    "Unknown opcode 0x{:02X} encountered at address {}",
                    opcode, address
                )
            }
        }
    }
}

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

/// Represents a parsed instruction along with its address and size.
#[derive(Debug, Clone)]
pub struct ParsedInstruction {
    pub address: usize,
    pub instruction: Instruction,
    pub size: usize, // Number of bytes consumed
}

/// Decoding function type. Each opcode has an associated decoding function.
type DecodeFn = fn(&[u8], usize) -> Result<(Instruction, usize), DisassembleError>;

/// Lookup table mapping opcodes to their decoding functions.
fn get_opcode_table() -> [Option<DecodeFn>; 256] {
    let mut table: [Option<DecodeFn>; 256] = [None; 256];
    
    table[LOAD as usize] = Some(decode_load);
    table[ADD as usize] = Some(decode_add);
    table[SUB as usize] = Some(decode_sub);
    table[MUL as usize] = Some(decode_mul);
    table[DIV as usize] = Some(decode_div);
    table[AND as usize] = Some(decode_and);
    table[OR as usize] = Some(decode_or);
    table[XOR as usize] = Some(decode_xor);
    table[NOT as usize] = Some(decode_not);
    table[SHL as usize] = Some(decode_shl);
    table[SHR as usize] = Some(decode_shr);
    table[MOV as usize] = Some(decode_mov);
    table[INC as usize] = Some(decode_inc);
    table[DEC as usize] = Some(decode_dec);
    table[JMP as usize] = Some(decode_jmp);
    table[CALL as usize] = Some(decode_call);
    table[RET as usize] = Some(decode_ret);
    table[CMP as usize] = Some(decode_cmp);
    table[JE as usize] = Some(decode_je);
    table[JNE as usize] = Some(decode_jne);
    table[PUSH as usize] = Some(decode_push);
    table[POP as usize] = Some(decode_pop);
    table[PUSHF as usize] = Some(decode_pushf);
    table[POPF as usize] = Some(decode_popf);
    table[NOP as usize] = Some(decode_nop);
    table[HALT as usize] = Some(decode_halt);
    
    table
}

/// Simple label resolver for addresses to labels.
/// In a real-world scenario, this might involve a two-pass disassembly.
struct LabelResolver {
    labels: std::collections::HashMap<u16, String>,
}

impl LabelResolver {
    fn new() -> Self {
        Self {
            labels: std::collections::HashMap::new(),
        }
    }
    
    fn get_label(&self, address: u16) -> String {
        if let Some(label) = self.labels.get(&address) {
            label.clone()
        } else {
            // Generate a new label if it doesn't exist
            format!("label_0x{:04X}", address)
        }
    }
    
    fn add_label(&mut self, address: u16) {
        if !self.labels.contains_key(&address) {
            let label = format!("label_0x{:04X}", address);
            self.labels.insert(address, label);
        }
    }
}

/// Disassembles binary data into a vector of parsed instructions.
///
/// # Arguments
///
/// * `data` - A slice of bytes representing the binary code.
///
/// # Returns
///
/// * A vector of `ParsedInstruction` structs or a disassembly error.
pub fn disassemble(data: &[u8]) -> Result<Vec<ParsedInstruction>, DisassembleError> {
    let mut instructions = Vec::new();
    let mut pc = 0;
    let opcode_table = get_opcode_table();
    let mut label_resolver = LabelResolver::new();

    // First pass: Identify all addresses that are jump/call targets
    let mut temp_pc = 0;
    while temp_pc < data.len() {
        let opcode = data[temp_pc];
        if let Some(decode_fn) = opcode_table[opcode as usize] {
            match decode_fn(data, temp_pc) {
                Ok((instr, bytes_consumed)) => {
                    match &instr {
                        Instruction::Jmp { address }
                        | Instruction::Je { address }
                        | Instruction::Jne { address }
                        | Instruction::Call { address } => {
                            label_resolver.add_label(*address);
                        }
                        _ => {}
                    }
                    temp_pc += bytes_consumed;
                }
                Err(_) => break, // Stop first pass on error
            }
        } else {
            temp_pc += 1; // Skip unknown opcode
        }
    }

    // Second pass: Actual disassembly with labels
    while pc < data.len() {
        let address = pc;
        let opcode = data[pc];
        if let Some(decode_fn) = opcode_table[opcode as usize] {
            match decode_fn(data, pc) {
                Ok((instruction, bytes_consumed)) => {
                    instructions.push(ParsedInstruction {
                        address,
                        instruction,
                        size: bytes_consumed,
                    });
                    pc += bytes_consumed;
                }
                Err(e) => {
                    return Err(e);
                }
            }
        } else {
            // Handle unknown opcode
            instructions.push(ParsedInstruction {
                address,
                instruction: Instruction::Unknown {
                    opcode,
                    bytes: data[pc..].iter().copied().take(1).collect(),
                },
                size: 1,
            });
            pc += 1; // Skip unknown opcode
        }
    }

    Ok(instructions)
}

/// Decodes the LOAD instruction.
///
/// Format: LOAD Register, Immediate
fn decode_load(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // LOAD is 1 byte opcode + 1 byte register + 2 bytes immediate
    let expected_length = 4;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    let imm = u16::from_be_bytes([data[pc + 2], data[pc + 3]]);
    Ok((
        Instruction::Load {
            register: reg,
            value: imm,
        },
        expected_length,
    ))
}

/// Decodes the ADD instruction.
///
/// Format: ADD Register, Register
fn decode_add(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // ADD is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Add { dest, src },
        expected_length,
    ))
}

/// Decodes the SUB instruction.
///
/// Format: SUB Register, Register
fn decode_sub(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // SUB is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Sub { dest, src },
        expected_length,
    ))
}

/// Decodes the MUL instruction.
///
/// Format: MUL Register, Register
fn decode_mul(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // MUL is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Mul { dest, src },
        expected_length,
    ))
}

/// Decodes the DIV instruction.
///
/// Format: DIV Register, Register
fn decode_div(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // DIV is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Div { dest, src },
        expected_length,
    ))
}

/// Decodes the AND instruction.
///
/// Format: AND Register, Register
fn decode_and(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // AND is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::And { dest, src },
        expected_length,
    ))
}

/// Decodes the OR instruction.
///
/// Format: OR Register, Register
fn decode_or(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // OR is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Or { dest, src },
        expected_length,
    ))
}

/// Decodes the XOR instruction.
///
/// Format: XOR Register, Register
fn decode_xor(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // XOR is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Xor { dest, src },
        expected_length,
    ))
}

/// Decodes the NOT instruction.
///
/// Format: NOT Register
fn decode_not(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // NOT is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Not { register: reg },
        expected_length,
    ))
}

/// Decodes the SHL instruction.
///
/// Format: SHL Register, Immediate (shift amount)
fn decode_shl(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // SHL is 1 byte opcode + 1 byte register + 1 byte shift amount
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let shift = data[pc + 2];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Shl {
            register: reg,
            shift,
        },
        expected_length,
    ))
}

/// Decodes the SHR instruction.
///
/// Format: SHR Register, Immediate (shift amount)
fn decode_shr(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // SHR is 1 byte opcode + 1 byte register + 1 byte shift amount
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let shift = data[pc + 2];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Shr {
            register: reg,
            shift,
        },
        expected_length,
    ))
}

/// Decodes the MOV instruction.
///
/// Format: MOV Register, Register
fn decode_mov(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // MOV is 1 byte opcode + 1 byte dest + 1 byte src
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let dest_code = data[pc + 1];
    let src_code = data[pc + 2];
    let dest = decode_register(dest_code);
    let src = decode_register(src_code);
    Ok((
        Instruction::Mov { dest, src },
        expected_length,
    ))
}

/// Decodes the INC instruction.
///
/// Format: INC Register
fn decode_inc(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // INC is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Inc { register: reg },
        expected_length,
    ))
}

/// Decodes the DEC instruction.
///
/// Format: DEC Register
fn decode_dec(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // DEC is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Dec { register: reg },
        expected_length,
    ))
}

/// Decodes the JMP instruction.
///
/// Format: JMP Address
fn decode_jmp(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // JMP is 1 byte opcode + 2 bytes address
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let addr = u16::from_be_bytes([data[pc + 1], data[pc + 2]]);
    Ok((
        Instruction::Jmp { address: addr },
        expected_length,
    ))
}

/// Decodes the CALL instruction.
///
/// Format: CALL Address
fn decode_call(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // CALL is 1 byte opcode + 2 bytes address
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let addr = u16::from_be_bytes([data[pc + 1], data[pc + 2]]);
    Ok((
        Instruction::Call { address: addr },
        expected_length,
    ))
}

/// Decodes the RET instruction.
///
/// Format: RET
fn decode_ret(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // RET is 1 byte opcode
    Ok((Instruction::Ret, 1))
}

/// Decodes the CMP instruction.
///
/// Format: CMP Register, Register
fn decode_cmp(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // CMP is 1 byte opcode + 1 byte reg1 + 1 byte reg2
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg1_code = data[pc + 1];
    let reg2_code = data[pc + 2];
    let reg1 = decode_register(reg1_code);
    let reg2 = decode_register(reg2_code);
    Ok((
        Instruction::Cmp { reg1, reg2 },
        expected_length,
    ))
}

/// Decodes the JE instruction.
///
/// Format: JE Address
fn decode_je(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // JE is 1 byte opcode + 2 bytes address
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let addr = u16::from_be_bytes([data[pc + 1], data[pc + 2]]);
    Ok((
        Instruction::Je { address: addr },
        expected_length,
    ))
}

/// Decodes the JNE instruction.
///
/// Format: JNE Address
fn decode_jne(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // JNE is 1 byte opcode + 2 bytes address
    let expected_length = 3;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let addr = u16::from_be_bytes([data[pc + 1], data[pc + 2]]);
    Ok((
        Instruction::Jne { address: addr },
        expected_length,
    ))
}

/// Decodes the PUSH instruction.
///
/// Format: PUSH Register
fn decode_push(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // PUSH is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Push { register: reg },
        expected_length,
    ))
}

/// Decodes the POP instruction.
///
/// Format: POP Register
fn decode_pop(data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // POP is 1 byte opcode + 1 byte register
    let expected_length = 2;
    if pc + expected_length > data.len() {
        return Err(DisassembleError::UnexpectedEndOfData {
            address: pc,
            expected: expected_length,
            found: data.len() - pc,
        });
    }
    let reg_code = data[pc + 1];
    let reg = decode_register(reg_code);
    Ok((
        Instruction::Pop { register: reg },
        expected_length,
    ))
}

/// Decodes the PUSHF instruction.
///
/// Format: PUSHF
fn decode_pushf(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // PUSHF is 1 byte opcode
    Ok((Instruction::Pushf, 1))
}

/// Decodes the POPF instruction.
///
/// Format: POPF
fn decode_popf(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // POPF is 1 byte opcode
    Ok((Instruction::Popf, 1))
}

/// Decodes the NOP instruction.
///
/// Format: NOP
fn decode_nop(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // NOP is 1 byte opcode
    Ok((Instruction::Nop, 1))
}

/// Decodes the HALT instruction.
///
/// Format: HALT
fn decode_halt(_data: &[u8], pc: usize) -> Result<(Instruction, usize), DisassembleError> {
    // HALT is 1 byte opcode
    Ok((Instruction::Halt, 1))
}

/// Decodes a register code into a `Register` enum.
///
/// # Arguments
///
/// * `code` - The register code as a `u8`.
///
/// # Returns
///
/// * A `Register` enum variant.
fn decode_register(code: u8) -> Register {
    match code {
        0x00 => Register::R0,
        0x01 => Register::R1,
        0x02 => Register::R2,
        0x03 => Register::R3,
        0x04 => Register::R4,
        0x05 => Register::R5,
        0x06 => Register::R6,
        0x07 => Register::R7,
        unknown => Register::Unknown(unknown),
    }
}