Fix the PUSH instruction and add the rest of the instructions

use crate::disassembler::instruction::{Instruction, Operand};
use std::collections::HashMap;

/// Decoder for x86_64 architecture
pub struct Decoder {
    /// Root of the opcode trie
    opcode_trie: OpcodeTrieNode,
}

#[derive(Debug)]
struct OpcodeTrieNode {
    children: HashMap<u8, OpcodeTrieNode>,
    opcode_info: Option<OpcodeInfo>,
}


#[derive(Debug, Clone)]
struct OpcodeInfo {
    mnemonic: &'static str,
    operands: Vec<OperandSpec>,
    opcode_length: usize,
    has_modrm: bool,
    has_sib: bool,
    rex_required: bool,
    is_multibyte: bool,
}

#[derive(Debug, Clone)]
struct OperandSpec {
    operand_type: OperandType,
    size: OperandSize,
}

#[derive(Debug, Clone, PartialEq)]
enum OperandSize {
    Byte,
    Word,
    Dword,
    Qword,
    // Other sizes can be added as needed
}

#[derive(Debug, Clone)]
enum OperandType {
    Register,
    Immediate,
    Memory,
    RelativeAddress,
    SegmentOverride, // For handling segment prefixes
    // Additional types can be added
}

impl Decoder {
    /// Initialize a new Decoder for x86_64
    pub fn new_x86_64() -> Self {
        let mut decoder = Decoder {
            opcode_trie: OpcodeTrieNode::new(),
        };

        // 1. NOP: 0x90
        decoder.add_opcode(vec![0x90], OpcodeInfo {
            mnemonic: "NOP",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

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

        // 2.a. RET imm16: 0xC2
        decoder.add_opcode(vec![0xC2], OpcodeInfo {
            mnemonic: "RET",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Word,
                },
            ],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 3. MOV r64, imm32: 0xB8 - 0xBF
        for rd in 0..8 {
            let opcode = vec![0xB8 + rd];
            let mnemonic = "MOV";
            decoder.add_opcode(opcode, OpcodeInfo {
                mnemonic,
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Register,
                        size: OperandSize::Qword,
                    },
                    OperandSpec {
                        operand_type: OperandType::Immediate,
                        size: OperandSize::Dword,
                    },
                ],
                opcode_length: 1,
                has_modrm: false,
                has_sib: false,
                rex_required: rd >= 8, // REX prefix needed for extended registers
                is_multibyte: false,
            });
        }

        // 4. MOV r/m64, r64: 0x89
        decoder.add_opcode(vec![0x89], OpcodeInfo {
            mnemonic: "MOV",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 5. MOV r64, r/m64: 0x8B
        decoder.add_opcode(vec![0x8B], OpcodeInfo {
            mnemonic: "MOV",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 6. ADD r/m64, r64: 0x01
        decoder.add_opcode(vec![0x01], OpcodeInfo {
            mnemonic: "ADD",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 7. SUB r/m64, r64: 0x29
        decoder.add_opcode(vec![0x29], OpcodeInfo {
            mnemonic: "SUB",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 8. MUL r/m64: 0xF7 /4
        decoder.add_opcode(vec![0xF7], OpcodeInfo {
            mnemonic: "MUL",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /4 indicates MUL
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 9. DIV r/m64: 0xF7 /6
        decoder.add_opcode(vec![0xF7], OpcodeInfo {
            mnemonic: "DIV",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /6 indicates DIV
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 10. INC r64: 0x40 - 0x47
        for rd in 0..8 {
            let opcode = vec![0x40 + rd];
            decoder.add_opcode(opcode, OpcodeInfo {
                mnemonic: "INC",
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Register,
                        size: OperandSize::Qword,
                    },
                ],
                opcode_length: 1,
                has_modrm: false,
                has_sib: false,
                rex_required: rd >= 8,
                is_multibyte: false,
            });
        }

        // 11. DEC r64: 0x48 - 0x4F
        for rd in 0..8 {
            let opcode = vec![0x48 + rd];
            decoder.add_opcode(opcode, OpcodeInfo {
                mnemonic: "DEC",
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Register,
                        size: OperandSize::Qword,
                    },
                ],
                opcode_length: 1,
                has_modrm: false,
                has_sib: false,
                rex_required: rd >= 8,
                is_multibyte: false,
            });
        }

        // 12. JMP rel32: 0xE9
        decoder.add_opcode(vec![0xE9], OpcodeInfo {
            mnemonic: "JMP",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::RelativeAddress,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

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

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

        // 15. PUSH r64: 0x50 - 0x57
        for rd in 0..8 {
            let opcode = vec![0x50 + rd];
            decoder.add_opcode(opcode, OpcodeInfo {
                mnemonic: "PUSH",
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Register,
                        size: OperandSize::Qword,
                    },
                ],
                opcode_length: 1,
                has_modrm: false,
                has_sib: false,
                rex_required: rd >= 8,
                is_multibyte: false,
            });
        }

        // 16. POP r64: 0x58 - 0x5F
        for rd in 0..8 {
            let opcode = vec![0x58 + rd];
            decoder.add_opcode(opcode, OpcodeInfo {
                mnemonic: "POP",
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Register,
                        size: OperandSize::Qword,
                    },
                ],
                opcode_length: 1,
                has_modrm: false,
                has_sib: false,
                rex_required: rd >= 8,
                is_multibyte: false,
            });
        }

        // 17. XOR r/m64, r64: 0x31
        decoder.add_opcode(vec![0x31], OpcodeInfo {
            mnemonic: "XOR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 18. OR r/m64, r64: 0x09
        decoder.add_opcode(vec![0x09], OpcodeInfo {
            mnemonic: "OR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 19. AND r/m64, r64: 0x21
        decoder.add_opcode(vec![0x21], OpcodeInfo {
            mnemonic: "AND",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 20. CMP r/m64, r64: 0x39
        decoder.add_opcode(vec![0x39], OpcodeInfo {
            mnemonic: "CMP",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 21. TEST r/m64, r64: 0x85
        decoder.add_opcode(vec![0x85], OpcodeInfo {
            mnemonic: "TEST",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 22. LEA r64, m: 0x8D
        decoder.add_opcode(vec![0x8D], OpcodeInfo {
            mnemonic: "LEA",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 23. SETcc: 0x0F 0x90 - 0x0F 0x9F
        for cc in 0..16 {
            let opcode = vec![0x0F, 0x90 + cc];
            let mnemonic = format!("SET{}", Self::get_condition_code(cc));
            decoder.add_opcode(opcode, OpcodeInfo {
                mnemonic: "SETcc",
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Register,
                        size: OperandSize::Byte,
                    },
                ],
                opcode_length: 2,
                has_modrm: true,
                has_sib: false,
                rex_required: false,
                is_multibyte: true,
            });
        }

        // 24. CMOVcc: 0x0F 0x40 - 0x0F 0x4F
        for cc in 0..16 {
            let opcode = vec![0x0F, 0x40 + cc];
            let mnemonic = format!("CMOV{}", Self::get_condition_code(cc));
            decoder.add_opcode(opcode, OpcodeInfo {
                mnemonic: "CMOVcc",
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Register,
                        size: OperandSize::Qword,
                    },
                    OperandSpec {
                        operand_type: OperandType::Memory,
                        size: OperandSize::Qword,
                    },
                ],
                opcode_length: 2,
                has_modrm: true,
                has_sib: true,
                rex_required: false,
                is_multibyte: true,
            });
        }

        // 25. SHL r/m64, imm8: 0xC1 /4
        decoder.add_opcode(vec![0xC1], OpcodeInfo {
            mnemonic: "SHL",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /4 indicates SHL
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 26. SHR r/m64, imm8: 0xC1 /5
        decoder.add_opcode(vec![0xC1], OpcodeInfo {
            mnemonic: "SHR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /5 indicates SHR
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 27. ROL r/m64, imm8: 0xC1 /0
        decoder.add_opcode(vec![0xC1], OpcodeInfo {
            mnemonic: "ROL",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates ROL
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 28. ROR r/m64, imm8: 0xC1 /1
        decoder.add_opcode(vec![0xC1], OpcodeInfo {
            mnemonic: "ROR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /1 indicates ROR
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 29. ADD r64, imm8: 0x83 /0
        decoder.add_opcode(vec![0x83], OpcodeInfo {
            mnemonic: "ADD",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates ADD
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 30. SUB r64, imm8: 0x83 /5
        decoder.add_opcode(vec![0x83], OpcodeInfo {
            mnemonic: "SUB",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /5 indicates SUB
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 31. NEG r/m64: 0xF7 /3
        decoder.add_opcode(vec![0xF7], OpcodeInfo {
            mnemonic: "NEG",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /3 indicates NEG
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 32. NOT r/m64: 0xF7 /2
        decoder.add_opcode(vec![0xF7], OpcodeInfo {
            mnemonic: "NOT",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /2 indicates NOT
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 33. AND r/m64, imm8: 0x83 /4
        decoder.add_opcode(vec![0x83], OpcodeInfo {
            mnemonic: "AND",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /4 indicates AND
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 34. OR r/m64, imm8: 0x83 /1
        decoder.add_opcode(vec![0x83], OpcodeInfo {
            mnemonic: "OR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /1 indicates OR
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 35. XOR r/m64, imm8: 0x83 /6
        decoder.add_opcode(vec![0x83], OpcodeInfo {
            mnemonic: "XOR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /6 indicates XOR
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 36. PUSH imm32: 0x68
        decoder.add_opcode(vec![0x68], OpcodeInfo {
            mnemonic: "PUSH",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 37. PUSH imm8: 0x6A
        decoder.add_opcode(vec![0x6A], OpcodeInfo {
            mnemonic: "PUSH",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 38. POP r/m64: 0x8F
        decoder.add_opcode(vec![0x8F], OpcodeInfo {
            mnemonic: "POP",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates POP r/m64
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 39. LEAVE: 0xC9
        decoder.add_opcode(vec![0xC9], OpcodeInfo {
            mnemonic: "LEAVE",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 40. SYSCALL: 0x0F 0x05
        decoder.add_opcode(vec![0x0F, 0x05], OpcodeInfo {
            mnemonic: "SYSCALL",
            operands: vec![],
            opcode_length: 2,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: true,
        });

        // 41. SYSRET: 0x0F 0x07
        decoder.add_opcode(vec![0x0F, 0x07], OpcodeInfo {
            mnemonic: "SYSRET",
            operands: vec![],
            opcode_length: 2,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: true,
        });

        // 42. INT imm8: 0xCD
        decoder.add_opcode(vec![0xCD], OpcodeInfo {
            mnemonic: "INT",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 43. CLC: 0xF8
        decoder.add_opcode(vec![0xF8], OpcodeInfo {
            mnemonic: "CLC",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 44. STC: 0xF9
        decoder.add_opcode(vec![0xF9], OpcodeInfo {
            mnemonic: "STC",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 45. CLD: 0xFC
        decoder.add_opcode(vec![0xFC], OpcodeInfo {
            mnemonic: "CLD",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 46. STD: 0xFD
        decoder.add_opcode(vec![0xFD], OpcodeInfo {
            mnemonic: "STD",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 47. INC r/m64: 0xFF /0
        decoder.add_opcode(vec![0xFF], OpcodeInfo {
            mnemonic: "INC",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates INC
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 48. DEC r/m64: 0xFF /1
        decoder.add_opcode(vec![0xFF], OpcodeInfo {
            mnemonic: "DEC",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /1 indicates DEC
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 49. PUSHF: 0x9C
        decoder.add_opcode(vec![0x9C], OpcodeInfo {
            mnemonic: "PUSHF",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 50. POPF: 0x9D
        decoder.add_opcode(vec![0x9D], OpcodeInfo {
            mnemonic: "POPF",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 51. MOVZX r64, r/m8: 0x0F 0xB6
        decoder.add_opcode(vec![0x0F, 0xB6], OpcodeInfo {
            mnemonic: "MOVZX",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 52. MOVSX r64, r/m8: 0x0F 0xBE
        decoder.add_opcode(vec![0x0F, 0xBE], OpcodeInfo {
            mnemonic: "MOVSX",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 53. MOVSX r64, r/m16: 0x0F 0xBF
        decoder.add_opcode(vec![0x0F, 0xBF], OpcodeInfo {
            mnemonic: "MOVSX",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Word,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 54. MOVZX r64, r/m16: 0x0F 0xB7
        decoder.add_opcode(vec![0x0F, 0xB7], OpcodeInfo {
            mnemonic: "MOVZX",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Word,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 55. LEAVE: 0xC9
        decoder.add_opcode(vec![0xC9], OpcodeInfo {
            mnemonic: "LEAVE",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 56. CMP r64, imm32: 0x81 /7
        decoder.add_opcode(vec![0x81], OpcodeInfo {
            mnemonic: "CMP",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /7 indicates CMP
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 57. TEST r/m64, imm32: 0xF7 /0
        decoder.add_opcode(vec![0xF7], OpcodeInfo {
            mnemonic: "TEST",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates TEST
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 58. PUSH r/m64: 0xFF /6
        decoder.add_opcode(vec![0xFF], OpcodeInfo {
            mnemonic: "PUSH",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /6 indicates PUSH
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 59. POP r/m64: 0x8F /0
        decoder.add_opcode(vec![0x8F], OpcodeInfo {
            mnemonic: "POP",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates POP
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 60. SAR r/m64, imm8: 0xC1 /7
        decoder.add_opcode(vec![0xC1], OpcodeInfo {
            mnemonic: "SAR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /7 indicates SAR
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 61. SUB r64, imm32: 0x81 /5
        decoder.add_opcode(vec![0x81], OpcodeInfo {
            mnemonic: "SUB",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /5 indicates SUB
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 62. INC r/m64: 0xFF /0 (redundant with earlier opcode, ensure uniqueness)
        // Handled earlier

        // 63. DEC r/m64: 0xFF /1 (redundant with earlier opcode, ensure uniqueness)
        // Handled earlier

        // 64. XCHG rax, r/m64: 0x90
        // Note: XCHG rax, r/m64 is same as NOP for 0-byte operands, but to avoid confusion, it's covered under NOP.

        // 65. SYSCALL: 0x0F 0x05
        decoder.add_opcode(vec![0x0F, 0x05], OpcodeInfo {
            mnemonic: "SYSCALL",
            operands: vec![],
            opcode_length: 2,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: true,
        });

        // 66. SYSRET: 0x0F 0x07
        decoder.add_opcode(vec![0x0F, 0x07], OpcodeInfo {
            mnemonic: "SYSRET",
            operands: vec![],
            opcode_length: 2,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: true,
        });

        // 67. CS prefix: 0x2E
        decoder.add_opcode(vec![0x2E], OpcodeInfo {
            mnemonic: "CS:",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false, // Segment override
        });

        // 68. DS prefix: 0x3E
        decoder.add_opcode(vec![0x3E], OpcodeInfo {
            mnemonic: "DS:",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 69. ES prefix: 0x26
        decoder.add_opcode(vec![0x26], OpcodeInfo {
            mnemonic: "ES:",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 70. SS prefix: 0x36
        decoder.add_opcode(vec![0x36], OpcodeInfo {
            mnemonic: "SS:",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 71. FS prefix: 0x64
        decoder.add_opcode(vec![0x64], OpcodeInfo {
            mnemonic: "FS:",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 72. GS prefix: 0x65
        decoder.add_opcode(vec![0x65], OpcodeInfo {
            mnemonic: "GS:",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 73. NOP dword ptr: 0x0F 0x1F 0x44 0x00
        decoder.add_opcode(vec![0x0F, 0x1F, 0x44, 0x00], OpcodeInfo {
            mnemonic: "NOP",
            operands: vec![],
            opcode_length: 4,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: true,
        });

        // 74. ADC r/m64, r64: 0x11
        decoder.add_opcode(vec![0x11], OpcodeInfo {
            mnemonic: "ADC",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 75. SBB r/m64, r64: 0x19
        decoder.add_opcode(vec![0x19], OpcodeInfo {
            mnemonic: "SBB",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 76. CMP r64, imm32: 0x81 /7
        decoder.add_opcode(vec![0x81], OpcodeInfo {
            mnemonic: "CMP",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /7 indicates CMP
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 77. TEST r64, imm32: 0xF7 /0
        decoder.add_opcode(vec![0xF7], OpcodeInfo {
            mnemonic: "TEST",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates TEST
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 78. TEST r/m64, imm8: 0xF6 /0
        decoder.add_opcode(vec![0xF6], OpcodeInfo {
            mnemonic: "TEST",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates TEST
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 79. AND r64, imm32: 0x81 /4
        decoder.add_opcode(vec![0x81], OpcodeInfo {
            mnemonic: "AND",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /4 indicates AND
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 80. OR r64, imm32: 0x81 /1
        decoder.add_opcode(vec![0x81], OpcodeInfo {
            mnemonic: "OR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /1 indicates OR
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 81. ADD r/m64, imm32: 0x81 /0
        decoder.add_opcode(vec![0x81], OpcodeInfo {
            mnemonic: "ADD",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Dword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates ADD
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 82. ADC r/m64, r64: 0x11
        decoder.add_opcode(vec![0x11], OpcodeInfo {
            mnemonic: "ADC",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 83. LOOP label: 0xE2
        decoder.add_opcode(vec![0xE2], OpcodeInfo {
            mnemonic: "LOOP",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::RelativeAddress,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 84. JMP r/m64: 0xFF /4
        decoder.add_opcode(vec![0xFF], OpcodeInfo {
            mnemonic: "JMP",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /4 indicates JMP
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 85. SHL r/m64, imm8: 0xC1 /4
        decoder.add_opcode(vec![0xC1], OpcodeInfo {
            mnemonic: "SHL",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /4 indicates SHL
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 86. SHR r/m64, imm8: 0xC1 /5
        decoder.add_opcode(vec![0xC1], OpcodeInfo {
            mnemonic: "SHR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /5 indicates SHR
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 87. ROL r/m64, imm8: 0xC1 /0
        decoder.add_opcode(vec![0xC1], OpcodeInfo {
            mnemonic: "ROL",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /0 indicates ROL
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 88. ROR r/m64, imm8: 0xC1 /1
        decoder.add_opcode(vec![0xC1], OpcodeInfo {
            mnemonic: "ROR",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Immediate,
                    size: OperandSize::Byte,
                },
            ],
            opcode_length: 1,
            has_modrm: true, // /1 indicates ROR
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 89. INT 3: 0xCC
        decoder.add_opcode(vec![0xCC], OpcodeInfo {
            mnemonic: "INT 3",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 90. NOP with multi-byte variants
        decoder.add_opcode(vec![0x0F, 0x1F, 0x44, 0x00], OpcodeInfo {
            mnemonic: "NOP",
            operands: vec![],
            opcode_length: 4,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: true,
        });

        // 91. BSWAP r64: 0x0F 0xC8 - 0x0F 0xCF
        for rd in 0..8 {
            let opcode = vec![0x0F, 0xC8 + rd];
            let mnemonic = "BSWAP";
            decoder.add_opcode(opcode, OpcodeInfo {
                mnemonic,
                operands: vec![
                    OperandSpec {
                        operand_type: OperandType::Register,
                        size: OperandSize::Dword, // BSWAP is typically used with registers
                    },
                ],
                opcode_length: 2,
                has_modrm: false,
                has_sib: false,
                rex_required: rd >= 8,
                is_multibyte: true,
            });
        }

        // 92. MOVS: 0xA4 (rep movsb)
        decoder.add_opcode(vec![0xA4], OpcodeInfo {
            mnemonic: "MOVS",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false, // Implicit operands
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 93. CMPS: 0xA6 (rep cmpsb)
        decoder.add_opcode(vec![0xA6], OpcodeInfo {
            mnemonic: "CMPS",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false, // Implicit operands
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 94. SCAS: 0xAE (rep scasb)
        decoder.add_opcode(vec![0xAE], OpcodeInfo {
            mnemonic: "SCAS",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false, // Implicit operands
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 95. LODS: 0xAD (rep lodsb)
        decoder.add_opcode(vec![0xAD], OpcodeInfo {
            mnemonic: "LODS",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false, // Implicit operands
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 96. STOS: 0xAA (rep stosb)
        decoder.add_opcode(vec![0xAA], OpcodeInfo {
            mnemonic: "STOS",
            operands: vec![],
            opcode_length: 1,
            has_modrm: false, // Implicit operands
            has_sib: false,
            rex_required: false,
            is_multibyte: false,
        });

        // 97. RDTSC: 0x0F 0x31
        decoder.add_opcode(vec![0x0F, 0x31], OpcodeInfo {
            mnemonic: "RDTSC",
            operands: vec![],
            opcode_length: 2,
            has_modrm: false,
            has_sib: false,
            rex_required: false,
            is_multibyte: true,
        });

        // 98. MOVNTQ m64, mmx: 0x0F 0xE7
        decoder.add_opcode(vec![0x0F, 0xE7], OpcodeInfo {
            mnemonic: "MOVNTQ",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 99. VMOVDQA xmm, xmm/m128: 0x0F 0x7F
        decoder.add_opcode(vec![0x0F, 0x7F], OpcodeInfo {
            mnemonic: "VMOVDQA",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword, // Representing xmm as Qword for simplicity
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 100. VMOVDQU xmm, xmm/m128: 0x0F 0x6F
        decoder.add_opcode(vec![0x0F, 0x6F], OpcodeInfo {
            mnemonic: "VMOVDQU",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 101. VMOVAPS xmm, xmm/m128: 0x0F 0x28
        decoder.add_opcode(vec![0x0F, 0x28], OpcodeInfo {
            mnemonic: "VMOVAPS",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 102. VMOVAPS xmm/m128, xmm: 0x0F 0x29
        decoder.add_opcode(vec![0x0F, 0x29], OpcodeInfo {
            mnemonic: "VMOVAPS",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 103. VMOVUPS xmm, xmm/m128: 0x0F 0x10
        decoder.add_opcode(vec![0x0F, 0x10], OpcodeInfo {
            mnemonic: "VMOVUPS",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 104. VMOVUPS xmm/m128, xmm: 0x0F 0x11
        decoder.add_opcode(vec![0x0F, 0x11], OpcodeInfo {
            mnemonic: "VMOVUPS",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 105. CMPXCHG r/m64, r64: 0x0F 0xB1
        decoder.add_opcode(vec![0x0F, 0xB1], OpcodeInfo {
            mnemonic: "CMPXCHG",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 2,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: true,
        });

        // 106. ADD r64, r/m64: 0x03
        decoder.add_opcode(vec![0x03], OpcodeInfo {
            mnemonic: "ADD",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });

        // 107. SUB r64, r/m64: 0x2B
        decoder.add_opcode(vec![0x2B], OpcodeInfo {
            mnemonic: "SUB",
            operands: vec![
                OperandSpec {
                    operand_type: OperandType::Register,
                    size: OperandSize::Qword,
                },
                OperandSpec {
                    operand_type: OperandType::Memory,
                    size: OperandSize::Qword,
                },
            ],
            opcode_length: 1,
            has_modrm: true,
            has_sib: true,
            rex_required: false,
            is_multibyte: false,
        });            

        // 108. PUSH r64: 0x50 - 0x57 (handled earlier)

        // 109. POP r64: 0x58 - 0x5F (handled earlier)

        // 110. XCHG rax, r64: 0x90 + rd (handled as NOP, but can handle XCHG separately if needed)

        // 111. LEA r64, m: 0x8D (handled earlier)

        // 112. CMOVcc r64, r/m64: 0x0F 0x40 - 0x0F 0x4F (handled earlier)

        // ... (additional opcodes can be added following the same pattern)

        // 113. SYSCALL: 0x0F 0x05 (handled earlier)

        decoder
    }

    /// Helper function to get condition code string based on cc value
    fn get_condition_code(cc: u8) -> &'static str {
        match cc {
            0x0 => "O",   // Overflow
            0x1 => "NO",  // Not Overflow
            0x2 => "B",   // Below (CF=1)
            0x3 => "NB",  // Not Below (CF=0)
            0x4 => "Z",   // Zero (ZF=1)
            0x5 => "NZ",  // Not Zero (ZF=0)
            0x6 => "BE",  // Below or Equal (CF=1 or ZF=1)
            0x7 => "NBE", // Not Below or Equal (CF=0 and ZF=0)
            0x8 => "S",   // Sign (SF=1)
            0x9 => "NS",  // Not Sign (SF=0)
            0xA => "P",   // Parity (PF=1)
            0xB => "NP",  // Not Parity (PF=0)
            0xC => "L",   // Less (SF != OF)
            0xD => "NL",  // Not Less (SF == OF)
            0xE => "LE",  // Less or Equal (ZF=1 or SF != OF)
            0xF => "NLE", // Not Less or Equal (ZF=0 and SF == OF)
            _ => "UNKNOWN",
        }
    }

    /// Add an opcode and its corresponding OpcodeInfo to the trie
    fn add_opcode(&mut self, opcode: Vec<u8>, info: OpcodeInfo) {
        let mut node = &mut self.opcode_trie;
        for &byte in &opcode {
            node = node.children.entry(byte).or_insert_with(OpcodeTrieNode::new);
        }
        node.opcode_info = Some(info);
    }

    /// 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();
        let mut prefixes = Vec::new();
        let mut segment_override: Option<String> = None;

        // Handle possible prefixes (REX, operand-size, address-size, segment overrides, etc.)
        while offset < bytes.len() {
            match bytes[offset] {
                // REX prefixes (0x40-0x4F)
                0x40..=0x4F => {
                    rex_prefix = RexPrefix::from_byte(bytes[offset])?;
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                // Segment overrides and other prefixes
                0x2E => { // CS
                    segment_override = Some("CS".to_string());
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                0x3E => { // DS
                    segment_override = Some("DS".to_string());
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                0x26 => { // ES
                    segment_override = Some("ES".to_string());
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                0x36 => { // SS
                    segment_override = Some("SS".to_string());
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                0x64 => { // FS
                    segment_override = Some("FS".to_string());
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                0x65 => { // GS
                    segment_override = Some("GS".to_string());
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                // Lock and repeat prefixes can be handled here if needed
                0xF0 | 0xF2 | 0xF3 => { // LOCK, REPNE, REP
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                // Operand-size prefix
                0x66 => {
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                // Address-size prefix
                0x67 => {
                    prefixes.push(bytes[offset]);
                    offset += 1;
                }
                _ => break,
            }
        }

        // Match opcode using the trie
        let (opcode_info, opcode_length) = self.match_opcode(&bytes[offset..])?;
        offset += opcode_length;
        let total_opcode_length = opcode_length;

        // Decode operands based on OpcodeInfo
        let mut operands = Vec::new();
        for spec in &opcode_info.operands {
            match spec.operand_type {
                OperandType::Register => {
                    if opcode_info.has_modrm {
                        // Register is encoded in the ModR/M reg field
                        let reg_field = self.get_modrm_reg_field(bytes, offset)?;
                        let reg = self.decode_register_field(reg_field, &rex_prefix)?;
                        operands.push(Operand::Register(reg));
                    } else {
                        // Otherwise, it might be encoded in the opcode
                        let reg = self.decode_register_from_opcode(&bytes[..offset], &opcode_info, &rex_prefix)?;
                        operands.push(Operand::Register(reg));
                    }
                }
                OperandType::Immediate => {
                    let imm = self.read_immediate(bytes, offset, &spec.size)?;
                    operands.push(Operand::Immediate(imm));
                    offset += spec.size.bytes();
                }
                OperandType::RelativeAddress => {
                    let rel = self.read_immediate(bytes, offset, &spec.size)? as i64;
                    let instr_size = offset + spec.size.bytes(); // Total bytes read so far
                    let target = address
                        .wrapping_add(instr_size as u64)
                        .wrapping_add(rel as u64);
                    operands.push(Operand::RelativeAddress(target));
                    offset += spec.size.bytes();
                }
                OperandType::Memory => {
                    if !opcode_info.has_modrm {
                        return Err(DecodeError::MissingModRM);
                    }
                    let (mem_operand, new_offset) = self.decode_memory_operand(bytes, offset, &rex_prefix)?;
                    operands.push(mem_operand);
                    offset = new_offset;
                }
                OperandType::SegmentOverride => {
                    if let Some(seg) = &segment_override {
                        operands.push(Operand::SegmentOverride(seg.clone()));
                    }
                }
            }
        }

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

        // Handle segment overrides (prefixes)
        if let Some(seg) = segment_override {
            // Prepend the segment override to the mnemonic for clarity
            let mnemonic = format!("{} {}", seg, opcode_info.mnemonic);
            return Ok(Instruction {
                mnemonic,
                operands,
                address,
                bytes: instr_bytes,
            });
        }

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

    /// Match the longest possible opcode in the trie and return the corresponding OpcodeInfo and its length
    fn match_opcode(&self, bytes: &[u8]) -> Result<(&OpcodeInfo, usize), DecodeError> {
        let mut node = &self.opcode_trie;
        let mut matched_info: Option<(&OpcodeInfo, usize)> = None;
        let mut current_length = 0;

        for &byte in bytes {
            if let Some(child) = node.children.get(&byte) {
                node = child;
                current_length += 1;
                if let Some(ref info) = node.opcode_info {
                    matched_info = Some((info, current_length));
                }
            } else {
                break;
            }
            // Prevent reading beyond available bytes
            if current_length >= bytes.len() {
                break;
            }
        }

        matched_info.ok_or(DecodeError::UnknownOpcode)
    }

    /// Decode the register operand from the opcode (for instructions like MOV r64, imm32)
    fn decode_register_from_opcode(&self, opcode_bytes: &[u8], info: &OpcodeInfo, rex: &RexPrefix) -> Result<String, DecodeError> {
        // For opcodes like MOV r64, imm32 (0xB8 - 0xBF), the register is encoded in the opcode itself
        // Assuming the last byte of opcode contains the register info
        if opcode_bytes.is_empty() {
            return Err(DecodeError::UnknownOpcode);
        }

        let last_opcode = opcode_bytes[opcode_bytes.len() - 1];
        if (0xB8..=0xBF).contains(&last_opcode) {
            let rd = last_opcode - 0xB8;
            let reg = self.get_register_from_opcode(rd, rex)?;
            return Ok(reg);
        }

        // Placeholder for other opcode-based register decoding
        Ok("unknown".to_string())
    }

    /// Helper to map opcode-based register indices to register names
    fn get_register_from_opcode(&self, rd: u8, rex: &RexPrefix) -> Result<String, DecodeError> {
        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",
        ];
        let index = rd as usize + extended as usize;
        if index >= registers.len() {
            return Err(DecodeError::InvalidRegister);
        }
        Ok(registers[index].to_string())
    }

    /// Decode the ModR/M reg field to get the register
    fn get_modrm_reg_field(&self, bytes: &[u8], offset: usize) -> Result<u8, DecodeError> {
        if offset >= bytes.len() {
            return Err(DecodeError::IncompleteInstruction);
        }
        let modrm = bytes[offset];
        Ok((modrm & 0b00111000) >> 3)
    }

    /// Decode a register field based on REX prefix
    fn decode_register_field(&self, reg_field: u8, rex: &RexPrefix) -> Result<String, DecodeError> {
        let extended = if rex.has_r_extension() { 8 } else { 0 };
        let registers = [
            "rax", "rcx", "rdx", "rbx",
            "rsp", "rbp", "rsi", "rdi",
            "r8", "r9", "r10", "r11",
            "r12", "r13", "r14", "r15",
        ];
        if (reg_field as usize) + extended >= registers.len() {
            return Err(DecodeError::InvalidRegister);
        }
        Ok(registers[(reg_field as usize) + extended].to_string())
    }

    /// Decode the memory operand including ModR/M and SIB bytes
    fn decode_memory_operand(
        &self,
        bytes: &[u8],
        mut offset: usize,
        rex: &RexPrefix,
    ) -> Result<(Operand, usize), DecodeError> {
        if offset >= bytes.len() {
            return Err(DecodeError::IncompleteInstruction);
        }
        let modrm = bytes[offset];
        offset += 1;

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

        let (base, index, scale, displacement) = 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, rex)?
        } else {
            (
                Some(self.decode_register_field(rm_field, rex)?),
                None,
                None,
                match mod_field {
                    0 => None,
                    1 => {
                        if offset >= bytes.len() {
                            return Err(DecodeError::IncompleteInstruction);
                        }
                        let disp = bytes[offset] as i8 as i64;
                        offset += 1;
                        Some(disp)
                    }
                    2 => {
                        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;
                        Some(disp)
                    }
                    _ => None,
                },
            )
        };

        // Handle displacement for mod_field == 0 and rm == 5 (disp32)
        let displacement = match (mod_field, rm_field) {
            (0, 5) => {
                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;
                Some(disp)
            }
            _ => displacement,
        };

        let mem_operand = Operand::Memory {
            segment: None, // Segment overrides are handled separately
            base,
            index,
            scale,
            displacement,
        };

        Ok((mem_operand, offset))
    }

    /// Decode the SIB byte
    fn decode_sib(
        &self,
        sib: u8,
        rex: &RexPrefix,
    ) -> Result<(Option<String>, Option<String>, Option<u8>, Option<i64>), DecodeError> {
        let scale = match (sib & 0b11000000) >> 6 {
            0 => Some(1),
            1 => Some(2),
            2 => Some(4),
            3 => Some(8),
            _ => None,
        };

        let index_field = (sib & 0b00111000) >> 3;
        let base_field = sib & 0b00000111;

        let index = if index_field == 4 {
            None // No index
        } else {
            Some(self.decode_register_field(index_field, rex)?)
        };

        let base = if base_field == 5 {
            None // No base, disp32 follows
        } else {
            Some(self.decode_register_field(base_field, rex)?)
        };

        Ok((base, index, scale, None)) // Displacement handled separately
    }

    /// 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,
        }
    }
}

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

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

    /// Extension for reg field
    fn has_r_extension(&self) -> bool {
        self.r
    }

    /// Extension for r/m or base field
    fn has_b_extension(&self) -> bool {
        self.b
    }

    /// Extension for index field in SIB
    fn has_x_extension(&self) -> bool {
        self.x
    }
}

/// Errors that can occur during decoding
#[derive(Debug)]
pub enum DecodeError {
    UnknownOpcode,
    IncompleteInstruction,
    InvalidRegister,
    MissingModRM,
    InvalidRexPrefix,
    InvalidSIB,
    // 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"),
            DecodeError::InvalidSIB => write!(f, "Invalid SIB byte"),
        }
    }
}

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

impl OpcodeTrieNode {
    fn new() -> Self {
        OpcodeTrieNode {
            children: HashMap::new(),
            opcode_info: None,
        }
    }
}