diff options
| -rw-r--r-- | src/lib.rs | 2037 | 
1 files changed, 1314 insertions, 723 deletions
| @@ -770,196 +770,935 @@ const BITWISE_OPCODE_MAP: [Opcode; 8] = [      Opcode::SAL,      Opcode::SAR  ]; -fn read_opcode_660f_map<T: Iterator<Item=u8>>(_bytes_iter: &mut T, _instruction: &mut Instruction, _length: &mut u8) -> Result<OperandCode, String> { -    Err("660f opcode map unsupported".to_string()) +fn read_opcode_660f_map<T: Iterator<Item=u8>>(_bytes_iter: &mut T, _instruction: &mut Instruction) -> Option<OperandCode> { +    panic!("660f opcode map unsupported".to_string());  } -fn read_opcode_f20f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction, length: &mut u8) -> Result<OperandCode, String> { + +#[derive(Copy, Clone)] +struct OpcodeInstructionRecord(Opcode, OperandCode); + +const OPCODE_F20F_MAP: [OpcodeInstructionRecord; 256] = [ +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0x10 +    OpcodeInstructionRecord(Opcode::MOVSD, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::MOVSD, OperandCode::E_G_xmm), +    OpcodeInstructionRecord(Opcode::MOVDDUP, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0x20 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::CVTSI2SD, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::CVTTSD2SI, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::CVTSD2SI, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0x30 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0x40 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0x50 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::SQRTSD, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::ADDSD, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::MULSD, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::CVTSD2SS, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::SUBSD, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::MINSD, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::DIVSD, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::MAXSD, OperandCode::G_E_xmm), +// 0x60 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0x70 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::HADDPS, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::HSUBPS, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0x80 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0x90 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0xa0 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0xb0 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0xc0 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0xd0 +    OpcodeInstructionRecord(Opcode::ADDSUBPS, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0xe0 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0xf0 +    OpcodeInstructionRecord(Opcode::LDDQU, OperandCode::G_E_xmm), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +]; + +fn read_opcode_f20f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction) -> Option<OperandCode> {      match bytes_iter.next() {          Some(b) => { -            *length += 1; -            match b { -                0x10 => { instruction.opcode = Opcode::MOVSD; Ok(OperandCode::G_E_xmm) }, -                0x11 => { instruction.opcode = Opcode::MOVSD; Ok(OperandCode::E_G_xmm) }, -                0x12 => { instruction.opcode = Opcode::MOVDDUP; Ok(OperandCode::G_E_xmm) }, -                0x2a => { instruction.opcode = Opcode::CVTSI2SD; Ok(OperandCode::G_E_xmm) }, -                0x2c => { instruction.opcode = Opcode::CVTTSD2SI; Ok(OperandCode::G_E_xmm) }, -                0x2d => { instruction.opcode = Opcode::CVTSD2SI; Ok(OperandCode::G_E_xmm) }, -                0x38 => { -                    /* -                     * There are a handful of instruction variants here, but -                     * in the f20f opcode map, only the CRC32 instruction is valid -                     */ -                    Err("x86_64 CRC32 not currently supported".to_string()) -                } -                0x51 => { instruction.opcode = Opcode::SQRTSD; Ok(OperandCode::G_E_xmm) }, -                0x58 => { instruction.opcode = Opcode::ADDSD; Ok(OperandCode::G_E_xmm) }, -                0x59 => { instruction.opcode = Opcode::MULSD; Ok(OperandCode::G_E_xmm) }, -                0x5a => { instruction.opcode = Opcode::CVTSD2SS; Ok(OperandCode::G_E_xmm) }, -                0x5c => { instruction.opcode = Opcode::SUBSD; Ok(OperandCode::G_E_xmm) }, -                0x5d => { instruction.opcode = Opcode::MINSD; Ok(OperandCode::G_E_xmm) }, -                0x5e => { instruction.opcode = Opcode::DIVSD; Ok(OperandCode::G_E_xmm) }, -                0x5f => { instruction.opcode = Opcode::MAXSD; Ok(OperandCode::G_E_xmm) }, -                0x7c => { instruction.opcode = Opcode::HADDPS; Ok(OperandCode::G_E_xmm) }, -                0x7d => { instruction.opcode = Opcode::HSUBPS; Ok(OperandCode::G_E_xmm) }, -                0xD0 => { instruction.opcode = Opcode::ADDSUBPS; Ok(OperandCode::G_E_xmm) }, -                0xf0 => { instruction.opcode = Opcode::LDDQU; Ok(OperandCode::G_E_xmm) }, -                /* -                0x70 PSHUFLW -                0xc2 CMPSD -                0xd6 MOVDQ2Q -                0xe6 CVTPD2DQ -                */ -                _ => { -                    instruction.opcode = Opcode::Invalid; -                    Err("Invalid opcode".to_string()) -                } -            } +            instruction.length += 1; +            let record = OPCODE_F20F_MAP[b as usize]; +            instruction.opcode = record.0; +            Some(record.1)          }          None => { -            Err("No more bytes".to_owned()) +            None          }      }  } -fn read_opcode_f30f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction, length: &mut u8) -> Result<OperandCode, String> { +fn read_opcode_f30f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction) -> Option<OperandCode> {      match bytes_iter.next() {          Some(b) => { -            *length += 1; +            instruction.length += 1;              match b { -                0x10 => { instruction.opcode = Opcode::MOVSS; Ok(OperandCode::G_E_xmm) }, -                0x11 => { instruction.opcode = Opcode::MOVSS; Ok(OperandCode::E_G_xmm) }, -                0x12 => { instruction.opcode = Opcode::MOVSLDUP; Ok(OperandCode::G_E_xmm) }, -                0x2a => { instruction.opcode = Opcode::CVTSI2SS; Ok(OperandCode::G_E_xmm) }, -                0x2c => { instruction.opcode = Opcode::CVTTSS2SI; Ok(OperandCode::G_E_xmm) }, -                0x2d => { instruction.opcode = Opcode::CVTSS2SI; Ok(OperandCode::G_E_xmm) }, -                0x51 => { instruction.opcode = Opcode::SQRTSS; Ok(OperandCode::G_E_xmm) }, -                0x58 => { instruction.opcode = Opcode::ADDSS; Ok(OperandCode::G_E_xmm) }, -                0x59 => { instruction.opcode = Opcode::MULSS; Ok(OperandCode::G_E_xmm) }, -                0x5a => { instruction.opcode = Opcode::CVTSS2SD; Ok(OperandCode::G_E_xmm) }, -                0x5c => { instruction.opcode = Opcode::SUBSS; Ok(OperandCode::G_E_xmm) }, -                0x5d => { instruction.opcode = Opcode::MINSS; Ok(OperandCode::G_E_xmm) }, -                0x5e => { instruction.opcode = Opcode::DIVSS; Ok(OperandCode::G_E_xmm) }, -                0x5f => { instruction.opcode = Opcode::MAXSS; Ok(OperandCode::G_E_xmm) }, +                0x10 => { instruction.opcode = Opcode::MOVSS; Some(OperandCode::G_E_xmm) }, +                0x11 => { instruction.opcode = Opcode::MOVSS; Some(OperandCode::E_G_xmm) }, +                0x12 => { instruction.opcode = Opcode::MOVSLDUP; Some(OperandCode::G_E_xmm) }, +                0x2a => { instruction.opcode = Opcode::CVTSI2SS; Some(OperandCode::G_E_xmm) }, +                0x2c => { instruction.opcode = Opcode::CVTTSS2SI; Some(OperandCode::G_E_xmm) }, +                0x2d => { instruction.opcode = Opcode::CVTSS2SI; Some(OperandCode::G_E_xmm) }, +                0x51 => { instruction.opcode = Opcode::SQRTSS; Some(OperandCode::G_E_xmm) }, +                0x58 => { instruction.opcode = Opcode::ADDSS; Some(OperandCode::G_E_xmm) }, +                0x59 => { instruction.opcode = Opcode::MULSS; Some(OperandCode::G_E_xmm) }, +                0x5a => { instruction.opcode = Opcode::CVTSS2SD; Some(OperandCode::G_E_xmm) }, +                0x5c => { instruction.opcode = Opcode::SUBSS; Some(OperandCode::G_E_xmm) }, +                0x5d => { instruction.opcode = Opcode::MINSS; Some(OperandCode::G_E_xmm) }, +                0x5e => { instruction.opcode = Opcode::DIVSS; Some(OperandCode::G_E_xmm) }, +                0x5f => { instruction.opcode = Opcode::MAXSS; Some(OperandCode::G_E_xmm) },                  _ => {                      instruction.opcode = Opcode::Invalid; -                    Err("Invalid opcode".to_string()) +                    Some(OperandCode::Nothing)                  }              }          }          None => { -            Err("No more bytes".to_owned()) +            None          }      }  } -fn read_opcode_0f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction, length: &mut u8) -> Result<OperandCode, String> { +const OPCODE_0F_MAP: [OpcodeInstructionRecord; 256] = [ +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::ModRM_0x0f00), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::ModRM_0x0f01), +    OpcodeInstructionRecord(Opcode::LAR, OperandCode::Gv_M), +    OpcodeInstructionRecord(Opcode::LSL, OperandCode::Gv_M), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::SYSCALL, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::CLTS, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::SYSRET, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::INVD, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::WBINVD, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::UD2, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::NOP, OperandCode::Ev), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0x10 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::NOP, OperandCode::Ev), +// 0x20 +    OpcodeInstructionRecord(Opcode::MOV, OperandCode::Rq_Cq_0), +    OpcodeInstructionRecord(Opcode::MOV, OperandCode::Rq_Dq_0), +    OpcodeInstructionRecord(Opcode::MOV, OperandCode::Cq_Rq_0), +    OpcodeInstructionRecord(Opcode::MOV, OperandCode::Dq_Rq_0), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), + +// 0x30 +    OpcodeInstructionRecord(Opcode::WRMSR, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::RDTSC, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::RDMSR, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::RDPMC, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), + +// 0x40 +    OpcodeInstructionRecord(Opcode::CMOVO, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVNO, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVB, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVNB, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVZ, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVNZ, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVNA, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVA, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVS, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVNS, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVP, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVNP, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVL, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVGE, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVLE, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::CMOVG, OperandCode::Gv_Ev), + +// 0x50 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), + +// 0x60 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), + +// 0x70 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), + +// 0x80 +    OpcodeInstructionRecord(Opcode::JO, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JNO, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JB, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JNB, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JZ, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JNZ, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JNA, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JA, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JS, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JNS, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JP, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JNP, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JL, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JGE, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JLE, OperandCode::Jvds), +    OpcodeInstructionRecord(Opcode::JG, OperandCode::Jvds), + +// 0x90 +    OpcodeInstructionRecord(Opcode::SETO, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETNO, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETB, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETAE, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETZ, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETNZ, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETBE, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETA, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETS, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETNS, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETP, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETNP, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETL, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETGE, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETLE, OperandCode::Eb_R0), +    OpcodeInstructionRecord(Opcode::SETG, OperandCode::Eb_R0), + +// 0xa0 +    OpcodeInstructionRecord(Opcode::PUSH, OperandCode::FS), +    OpcodeInstructionRecord(Opcode::POP, OperandCode::GS), +    OpcodeInstructionRecord(Opcode::CPUID, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::BT, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::PUSH, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::PUSH, OperandCode::GS), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::ModRM_0x0fae), +    OpcodeInstructionRecord(Opcode::IMUL, OperandCode::Gv_Ev), + +// 0xb0 +    OpcodeInstructionRecord(Opcode::CMPXCHG, OperandCode::Eb_Gb), +    OpcodeInstructionRecord(Opcode::CMPXCHG, OperandCode::Ev_Gv), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::MOVZX_b, OperandCode::Gv_Eb), +    OpcodeInstructionRecord(Opcode::MOVZX_w, OperandCode::Gv_Ew), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::ModRM_0x0fba), +    OpcodeInstructionRecord(Opcode::BTC, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::BSF, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::BSR, OperandCode::Gv_Ev), +    OpcodeInstructionRecord(Opcode::MOVSX_b, OperandCode::Gv_Eb), +    OpcodeInstructionRecord(Opcode::MOVSX_w, OperandCode::Gv_Ew), + +// 0xc0 +    OpcodeInstructionRecord(Opcode::XADD, OperandCode::Eb_Gb), +    OpcodeInstructionRecord(Opcode::XADD, OperandCode::Ev_Gv), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), + +// 0xd0 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), + +// 0xe0 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +// 0xf0 +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +    OpcodeInstructionRecord(Opcode::Invalid, OperandCode::Nothing), +]; +fn read_opcode_0f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction) -> Option<OperandCode> {      match bytes_iter.next() {          Some(b) => { -            *length += 1; -            match b { -                0x00 => { instruction.opcode = Opcode::Invalid; Ok(OperandCode::ModRM_0x0f00) }, -                0x01 => { instruction.opcode = Opcode::Invalid; Ok(OperandCode::ModRM_0x0f01) }, -                0x02 => { instruction.opcode = Opcode::LAR; Ok(OperandCode::Gv_M) }, -                0x03 => { instruction.opcode = Opcode::LSL; Ok(OperandCode::Gv_M) }, -                0x05 => { instruction.opcode = Opcode::SYSCALL; Ok(OperandCode::Nothing) }, -                0x06 => { instruction.opcode = Opcode::CLTS; Ok(OperandCode::Nothing) }, -                0x07 => { instruction.opcode = Opcode::SYSRET; Ok(OperandCode::Nothing) }, -                0x08 => { instruction.opcode = Opcode::INVD; Ok(OperandCode::Nothing) }, -                0x09 => { instruction.opcode = Opcode::WBINVD; Ok(OperandCode::Nothing) }, -                0x0b => { instruction.opcode = Opcode::UD2; Ok(OperandCode::Nothing) }, -                0x0d => { instruction.opcode = Opcode::NOP; Ok(OperandCode::Ev) }, -                0x1f => { instruction.opcode = Opcode::NOP; Ok(OperandCode::Ev) }, -                0x20 => { instruction.opcode = Opcode::MOV; Ok(OperandCode::Rq_Cq_0) }, -                0x21 => { instruction.opcode = Opcode::MOV; Ok(OperandCode::Rq_Dq_0) }, -                0x22 => { instruction.opcode = Opcode::MOV; Ok(OperandCode::Cq_Rq_0) }, -                0x23 => { instruction.opcode = Opcode::MOV; Ok(OperandCode::Dq_Rq_0) }, -                0x30 => { instruction.opcode = Opcode::WRMSR; Ok(OperandCode::Nothing) }, -                0x31 => { instruction.opcode = Opcode::RDTSC; Ok(OperandCode::Nothing) }, -                0x32 => { instruction.opcode = Opcode::RDMSR; Ok(OperandCode::Nothing) }, -                0x33 => { instruction.opcode = Opcode::RDPMC; Ok(OperandCode::Nothing) }, -                0x40 => { instruction.opcode = Opcode::CMOVO; Ok(OperandCode::Gv_Ev) }, -                0x41 => { instruction.opcode = Opcode::CMOVNO; Ok(OperandCode::Gv_Ev) }, -                0x42 => { instruction.opcode = Opcode::CMOVB; Ok(OperandCode::Gv_Ev) }, -                0x43 => { instruction.opcode = Opcode::CMOVNB; Ok(OperandCode::Gv_Ev) }, -                0x44 => { instruction.opcode = Opcode::CMOVZ; Ok(OperandCode::Gv_Ev) }, -                0x45 => { instruction.opcode = Opcode::CMOVNZ; Ok(OperandCode::Gv_Ev) }, -                0x46 => { instruction.opcode = Opcode::CMOVNA; Ok(OperandCode::Gv_Ev) }, -                0x47 => { instruction.opcode = Opcode::CMOVA; Ok(OperandCode::Gv_Ev) }, -                0x48 => { instruction.opcode = Opcode::CMOVS; Ok(OperandCode::Gv_Ev) }, -                0x49 => { instruction.opcode = Opcode::CMOVNS; Ok(OperandCode::Gv_Ev) }, -                0x4a => { instruction.opcode = Opcode::CMOVP; Ok(OperandCode::Gv_Ev) }, -                0x4b => { instruction.opcode = Opcode::CMOVNP; Ok(OperandCode::Gv_Ev) }, -                0x4c => { instruction.opcode = Opcode::CMOVL; Ok(OperandCode::Gv_Ev) }, -                0x4d => { instruction.opcode = Opcode::CMOVGE; Ok(OperandCode::Gv_Ev) }, -                0x4e => { instruction.opcode = Opcode::CMOVLE; Ok(OperandCode::Gv_Ev) }, -                0x4f => { instruction.opcode = Opcode::CMOVG; Ok(OperandCode::Gv_Ev) }, -                0x80 => { instruction.opcode = Opcode::JO; Ok(OperandCode::Jvds) }, -                0x81 => { instruction.opcode = Opcode::JNO; Ok(OperandCode::Jvds) }, -                0x82 => { instruction.opcode = Opcode::JB; Ok(OperandCode::Jvds) }, -                0x83 => { instruction.opcode = Opcode::JNB; Ok(OperandCode::Jvds) }, -                0x84 => { instruction.opcode = Opcode::JZ; Ok(OperandCode::Jvds) }, -                0x85 => { instruction.opcode = Opcode::JNZ; Ok(OperandCode::Jvds) }, -                0x86 => { instruction.opcode = Opcode::JNA; Ok(OperandCode::Jvds) }, -                0x87 => { instruction.opcode = Opcode::JA; Ok(OperandCode::Jvds) }, -                0x88 => { instruction.opcode = Opcode::JS; Ok(OperandCode::Jvds) }, -                0x89 => { instruction.opcode = Opcode::JNS; Ok(OperandCode::Jvds) }, -                0x8a => { instruction.opcode = Opcode::JP; Ok(OperandCode::Jvds) }, -                0x8b => { instruction.opcode = Opcode::JNP; Ok(OperandCode::Jvds) }, -                0x8c => { instruction.opcode = Opcode::JL; Ok(OperandCode::Jvds) }, -                0x8d => { instruction.opcode = Opcode::JGE; Ok(OperandCode::Jvds) }, -                0x8e => { instruction.opcode = Opcode::JLE; Ok(OperandCode::Jvds) }, -                0x8f => { instruction.opcode = Opcode::JG; Ok(OperandCode::Jvds) }, -                x if x < 0xa0 => { -                    let op = [ -                        Opcode::SETO, -                        Opcode::SETNO, -                        Opcode::SETB, -                        Opcode::SETAE, -                        Opcode::SETZ, -                        Opcode::SETNZ, -                        Opcode::SETBE, -                        Opcode::SETA, -                        Opcode::SETS, -                        Opcode::SETNS, -                        Opcode::SETP, -                        Opcode::SETNP, -                        Opcode::SETL, -                        Opcode::SETGE, -                        Opcode::SETLE, -                        Opcode::SETG -                    ][(x & 0xf) as usize]; -                    instruction.opcode = op; Ok(OperandCode::Eb_R0) -                } -                0xa0 => { instruction.opcode = Opcode::PUSH; Ok(OperandCode::FS) }, -                0xa1 => { instruction.opcode = Opcode::POP; Ok(OperandCode::GS) }, -                0xa2 => { instruction.opcode = Opcode::CPUID; Ok(OperandCode::Nothing) }, -                0xa3 => { instruction.opcode = Opcode::BT; Ok(OperandCode::Gv_Ev) }, -                0xa8 => { instruction.opcode = Opcode::PUSH; Ok(OperandCode::Nothing) }, -                0xa9 => { instruction.opcode = Opcode::PUSH; Ok(OperandCode::GS) }, -                0xae => { instruction.opcode = Opcode::Invalid; Ok(OperandCode::ModRM_0x0fae) }, -                0xaf => { instruction.opcode = Opcode::IMUL; Ok(OperandCode::Gv_Ev) }, -                0xb0 => { instruction.opcode = Opcode::CMPXCHG; Ok(OperandCode::Eb_Gb) }, -                0xb1 => { instruction.opcode = Opcode::CMPXCHG; Ok(OperandCode::Ev_Gv) }, -                0xb6 => { instruction.opcode = Opcode::MOVZX_b; Ok(OperandCode::Gv_Eb) }, -                0xb7 => { instruction.opcode = Opcode::MOVZX_w; Ok(OperandCode::Gv_Ew) }, -                0xba => { instruction.opcode = Opcode::Invalid; Ok(OperandCode::ModRM_0x0fba) }, -                0xbb => { instruction.opcode = Opcode::BTC; Ok(OperandCode::Gv_Ev) }, -                0xbc => { instruction.opcode = Opcode::BSF; Ok(OperandCode::Gv_Ev) }, -                0xbd => { instruction.opcode = Opcode::BSR; Ok(OperandCode::Gv_Ev) }, -                0xbe => { instruction.opcode = Opcode::MOVSX_b; Ok(OperandCode::Gv_Eb) }, -                0xbf => { instruction.opcode = Opcode::MOVSX_w; Ok(OperandCode::Gv_Ew) }, -                0xc0 => { instruction.opcode = Opcode::XADD; Ok(OperandCode::Eb_Gb) }, -                0xc1 => { instruction.opcode = Opcode::XADD; Ok(OperandCode::Ev_Gv) }, -                _ => { -                    Err(format!("Unknown opcode: 0f{:x}", b)) -                } -            } -        }, +            instruction.length += 1; +            let record = OPCODE_0F_MAP[b as usize]; +            instruction.opcode = record.0; +            Some(record.1) +        }          None => { -            Err("No more bytes".to_owned()) +            None          }      }  } -fn read_opcode<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction, length: &mut u8) -> Result<OperandCode, String> { +#[derive(Copy, Clone, PartialEq, Eq)] +enum Interpretation { +    Instruction, +    Prefix, +} + +#[derive(Copy, Clone)] +// this should be a 32-byte struct.. +struct OpcodeRecord(Opcode, Interpretation, OperandCode); + +const OPCODES: [OpcodeRecord; 256] = [ +    OpcodeRecord(Opcode::ADD, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::ADD, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::ADD, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::ADD, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::ADD, Interpretation::Instruction, OperandCode::AL_Ib), +    OpcodeRecord(Opcode::ADD, Interpretation::Instruction, OperandCode::AX_Ivd), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::OR, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::OR, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::OR, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::OR, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::OR, Interpretation::Instruction, OperandCode::AL_Ib), +    OpcodeRecord(Opcode::OR, Interpretation::Instruction, OperandCode::AX_Ivd), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::ADC, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::ADC, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::ADC, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::ADC, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::ADC, Interpretation::Instruction, OperandCode::AL_Ib), +    OpcodeRecord(Opcode::ADC, Interpretation::Instruction, OperandCode::AX_Ivd), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::SBB, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::SBB, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::SBB, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::SBB, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::SBB, Interpretation::Instruction, OperandCode::AL_Ib), +    OpcodeRecord(Opcode::SBB, Interpretation::Instruction, OperandCode::AX_Ivd), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::AND, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::AND, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::AND, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::AND, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::AND, Interpretation::Instruction, OperandCode::AL_Ib), +    OpcodeRecord(Opcode::AND, Interpretation::Instruction, OperandCode::AX_Ivd), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::SUB, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::SUB, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::SUB, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::SUB, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::SUB, Interpretation::Instruction, OperandCode::AL_Ib), +    OpcodeRecord(Opcode::SUB, Interpretation::Instruction, OperandCode::AX_Ivd), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::XOR, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::XOR, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::XOR, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::XOR, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::XOR, Interpretation::Instruction, OperandCode::AL_Ib), +    OpcodeRecord(Opcode::XOR, Interpretation::Instruction, OperandCode::AX_Ivd), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::CMP, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::CMP, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::CMP, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::CMP, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::CMP, Interpretation::Instruction, OperandCode::AL_Ib), +    OpcodeRecord(Opcode::CMP, Interpretation::Instruction, OperandCode::AX_Ivd), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +// 0x40: +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +// 0x50: +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Zv(0)), +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Zv(1)), +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Zv(2)), +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Zv(3)), +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Zv(4)), +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Zv(5)), +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Zv(6)), +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Zv(7)), +    OpcodeRecord(Opcode::POP, Interpretation::Instruction, OperandCode::Zv(0)), +    OpcodeRecord(Opcode::POP, Interpretation::Instruction, OperandCode::Zv(1)), +    OpcodeRecord(Opcode::POP, Interpretation::Instruction, OperandCode::Zv(2)), +    OpcodeRecord(Opcode::POP, Interpretation::Instruction, OperandCode::Zv(3)), +    OpcodeRecord(Opcode::POP, Interpretation::Instruction, OperandCode::Zv(4)), +    OpcodeRecord(Opcode::POP, Interpretation::Instruction, OperandCode::Zv(5)), +    OpcodeRecord(Opcode::POP, Interpretation::Instruction, OperandCode::Zv(6)), +    OpcodeRecord(Opcode::POP, Interpretation::Instruction, OperandCode::Zv(7)), +// 0x60 +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::MOVSXD, Interpretation::Instruction, OperandCode::Gv_Ed), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Ivs), +    OpcodeRecord(Opcode::IMUL, Interpretation::Instruction, OperandCode::Gv_Ev_Iv), +    OpcodeRecord(Opcode::PUSH, Interpretation::Instruction, OperandCode::Ibs), +    OpcodeRecord(Opcode::IMUL, Interpretation::Instruction, OperandCode::Gb_Eb_Ib), +    OpcodeRecord(Opcode::INS, Interpretation::Instruction, OperandCode::Yb_DX), +    OpcodeRecord(Opcode::INS, Interpretation::Instruction, OperandCode::Yv_DX), +    OpcodeRecord(Opcode::OUTS, Interpretation::Instruction, OperandCode::DX_Xb), +    OpcodeRecord(Opcode::OUTS, Interpretation::Instruction, OperandCode::DX_Xv), +// 0x70 +    OpcodeRecord(Opcode::JO, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JNO, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JB, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JNB, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JZ, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JNZ, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JNA, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JA, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JS, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JNS, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JP, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JNP, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JL, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JGE, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JLE, Interpretation::Instruction, OperandCode::Jbs), +    OpcodeRecord(Opcode::JG, Interpretation::Instruction, OperandCode::Jbs), +// 0x80 +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0x80_Eb_Ib), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0x81_Ev_Ivs), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0x83_Ev_Ibs), +    OpcodeRecord(Opcode::TEST, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::TEST, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::XCHG, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::XCHG, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Eb_Gb), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Ev_Gv), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Gb_Eb), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Gv_Ev), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Ew_Sw), +    OpcodeRecord(Opcode::LEA, Interpretation::Instruction, OperandCode::Gv_M), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Sw_Ew), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0x8f_Ev), +    OpcodeRecord(Opcode::NOP, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::XCHG, Interpretation::Instruction, OperandCode::Zv_AX(1)), +    OpcodeRecord(Opcode::XCHG, Interpretation::Instruction, OperandCode::Zv_AX(2)), +    OpcodeRecord(Opcode::XCHG, Interpretation::Instruction, OperandCode::Zv_AX(3)), +    OpcodeRecord(Opcode::XCHG, Interpretation::Instruction, OperandCode::Zv_AX(4)), +    OpcodeRecord(Opcode::XCHG, Interpretation::Instruction, OperandCode::Zv_AX(5)), +    OpcodeRecord(Opcode::XCHG, Interpretation::Instruction, OperandCode::Zv_AX(6)), +    OpcodeRecord(Opcode::XCHG, Interpretation::Instruction, OperandCode::Zv_AX(7)), +    OpcodeRecord(Opcode::CBW, Interpretation::Instruction, OperandCode::AX_AL), +    OpcodeRecord(Opcode::CBW, Interpretation::Instruction, OperandCode::DX_AX), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::WAIT, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::PUSHF, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::POPF, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::SAHF, Interpretation::Instruction, OperandCode::AH), +    OpcodeRecord(Opcode::LAHF, Interpretation::Instruction, OperandCode::AH), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::AL_Ob), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::AX_Ov), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Ob_AL), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Ov_AX), +    OpcodeRecord(Opcode::MOVS, Interpretation::Instruction, OperandCode::Yb_Xb), +    OpcodeRecord(Opcode::MOVS, Interpretation::Instruction, OperandCode::Yv_Xv), +    OpcodeRecord(Opcode::CMPS, Interpretation::Instruction, OperandCode::Yb_Xb), +    OpcodeRecord(Opcode::CMPS, Interpretation::Instruction, OperandCode::Yv_Xv), +    OpcodeRecord(Opcode::TEST, Interpretation::Instruction, OperandCode::AL_Ib), +    OpcodeRecord(Opcode::TEST, Interpretation::Instruction, OperandCode::AX_Ivd), +    OpcodeRecord(Opcode::STOS, Interpretation::Instruction, OperandCode::Yb_AL), +    OpcodeRecord(Opcode::STOS, Interpretation::Instruction, OperandCode::Yv_AX), +    OpcodeRecord(Opcode::LODS, Interpretation::Instruction, OperandCode::AL_Xb), +    OpcodeRecord(Opcode::LODS, Interpretation::Instruction, OperandCode::AX_Xv), +    OpcodeRecord(Opcode::SCAS, Interpretation::Instruction, OperandCode::Yb_AL), +    OpcodeRecord(Opcode::SCAS, Interpretation::Instruction, OperandCode::Yv_AX), +// 0xb0 +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zb_Ib(0)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zb_Ib(1)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zb_Ib(2)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zb_Ib(3)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zb_Ib(4)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zb_Ib(5)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zb_Ib(6)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zb_Ib(7)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zv_Ivq(0)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zv_Ivq(1)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zv_Ivq(2)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zv_Ivq(3)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zv_Ivq(4)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zv_Ivq(5)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zv_Ivq(6)), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::Zv_Ivq(7)), +// 0xc0 +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xc0_Eb_Ib), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xc1_Ev_Ib), +    OpcodeRecord(Opcode::RETURN, Interpretation::Instruction, OperandCode::Iw), +    OpcodeRecord(Opcode::RETURN, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::ModRM_0xc6_Eb_Ib), +    OpcodeRecord(Opcode::MOV, Interpretation::Instruction, OperandCode::ModRM_0xc7_Ev_Iv), +    OpcodeRecord(Opcode::ENTER, Interpretation::Instruction, OperandCode::Iw_Ib), +    OpcodeRecord(Opcode::LEAVE, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::RETF, Interpretation::Instruction, OperandCode::Iw), +    OpcodeRecord(Opcode::RETF, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::INT, Interpretation::Instruction, OperandCode::I_3), +    OpcodeRecord(Opcode::INT, Interpretation::Instruction, OperandCode::Ib), +    OpcodeRecord(Opcode::INTO, Interpretation::Instruction, OperandCode::Fw), +    OpcodeRecord(Opcode::IRET, Interpretation::Instruction, OperandCode::Fw), +// 0xd0 +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xd0_Eb_1), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xd1_Ev_1), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xd2_Eb_CL), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xd3_Ev_CL), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // XLAT +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // x86 d8 +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // x86 d9 +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // x86 da +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // x86 db +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // x86 dc +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // x86 dd +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // x86 de +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // x86 df +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +// 0xe0 +    // LOOPNZ +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // LOOPZ +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // LOOP +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // JECXZ +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // IN +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // IN +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // OUT +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // OUT +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +// 0xe8 +    OpcodeRecord(Opcode::CALL, Interpretation::Instruction, OperandCode::Jvds), +    OpcodeRecord(Opcode::JMP, Interpretation::Instruction, OperandCode::Jvds), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::JMP, Interpretation::Instruction, OperandCode::Jbs), +    // IN +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // IN +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // OUT +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    // OUT +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +// 0xf0 +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    // ICEBP? +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Prefix, OperandCode::Nothing), +// 0xf4 +    OpcodeRecord(Opcode::HLT, Interpretation::Instruction, OperandCode::Nothing), +    // CMC +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xf6), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xf7), +    OpcodeRecord(Opcode::CLC, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::STC, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::CLI, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::STI, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::CLD, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::STD, Interpretation::Instruction, OperandCode::Nothing), +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xfe_Eb), +    // TODO: test 0xff /3 +    OpcodeRecord(Opcode::Invalid, Interpretation::Instruction, OperandCode::ModRM_0xff_Ev), +]; + +fn read_opcode<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction) -> Option<OperandCode> {      let mut alternate_opcode_map: Option<OpcodeMap> = None;      use std::hint::unreachable_unchecked;  //    use std::intrinsics::unlikely; @@ -967,410 +1706,149 @@ fn read_opcode<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instr      loop {          match bytes_iter.next() {              Some(b) => { -                *length += 1; -                match b { -                    0x00 => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::Eb_Gb); }, -                    0x01 => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::Ev_Gv); }, -                    0x02 => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::Gb_Eb); }, -                    0x03 => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::Gv_Ev); }, -                    0x04 => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::AL_Ib); }, -                    0x05 => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::AX_Ivd); }, -                    0x06 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x07 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x08 => { instruction.opcode = Opcode::OR; return Ok(OperandCode::Eb_Gb); }, -                    0x09 => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::Ev_Gv); }, -                    0x0a => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::Gb_Eb); }, -                    0x0b => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::Gv_Ev); }, -                    0x0c => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::AL_Ib); }, -                    0x0d => { instruction.opcode = Opcode::ADD; return Ok(OperandCode::AX_Ivd); }, -                    0x0e => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x0f => { -                        return match alternate_opcode_map { -                            Some(OpcodeMap::Map66) => { -                                read_opcode_660f_map(bytes_iter, instruction, length) -                            }, -                            Some(OpcodeMap::MapF2) => { -                                read_opcode_f20f_map(bytes_iter, instruction, length) -                            }, -                            Some(OpcodeMap::MapF3) => { -                                read_opcode_f30f_map(bytes_iter, instruction, length) -                            }, -                            None => { -                                read_opcode_0f_map(bytes_iter, instruction, length) -                            } -                        }; -                    }, -                    0x10 => { instruction.opcode = Opcode::ADC; return Ok(OperandCode::Eb_Gb); }, -                    0x11 => { instruction.opcode = Opcode::ADC; return Ok(OperandCode::Ev_Gv); }, -                    0x12 => { instruction.opcode = Opcode::ADC; return Ok(OperandCode::Gb_Eb); }, -                    0x13 => { instruction.opcode = Opcode::ADC; return Ok(OperandCode::Gv_Ev); }, -                    0x14 => { instruction.opcode = Opcode::ADC; return Ok(OperandCode::AL_Ib); }, -                    0x15 => { instruction.opcode = Opcode::ADC; return Ok(OperandCode::AX_Ivd); }, -                    0x16 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x17 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x18 => { instruction.opcode = Opcode::SBB; return Ok(OperandCode::Eb_Gb); }, -                    0x19 => { instruction.opcode = Opcode::SBB; return Ok(OperandCode::Ev_Gv); }, -                    0x1a => { instruction.opcode = Opcode::SBB; return Ok(OperandCode::Gb_Eb); }, -                    0x1b => { instruction.opcode = Opcode::SBB; return Ok(OperandCode::Gv_Ev); }, -                    0x1c => { instruction.opcode = Opcode::SBB; return Ok(OperandCode::AL_Ib); }, -                    0x1d => { instruction.opcode = Opcode::SBB; return Ok(OperandCode::AX_Ivd); }, -                    0x1e => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x1f => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x20 => { instruction.opcode = Opcode::AND; return Ok(OperandCode::Eb_Gb); }, -                    0x21 => { instruction.opcode = Opcode::AND; return Ok(OperandCode::Ev_Gv); }, -                    0x22 => { instruction.opcode = Opcode::AND; return Ok(OperandCode::Gb_Eb); }, -                    0x23 => { instruction.opcode = Opcode::AND; return Ok(OperandCode::Gv_Ev); }, -                    0x24 => { instruction.opcode = Opcode::AND; return Ok(OperandCode::AL_Ib); }, -                    0x25 => { instruction.opcode = Opcode::AND; return Ok(OperandCode::AX_Ivd); }, -                    0x26 => { -                        instruction.prefixes.set_es(); -                        alternate_opcode_map = None; -                    }, -                    0x27 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x28 => { instruction.opcode = Opcode::SUB; return Ok(OperandCode::Eb_Gb); }, -                    0x29 => { instruction.opcode = Opcode::SUB; return Ok(OperandCode::Ev_Gv); }, -                    0x2a => { instruction.opcode = Opcode::SUB; return Ok(OperandCode::Gb_Eb); }, -                    0x2b => { instruction.opcode = Opcode::SUB; return Ok(OperandCode::Gv_Ev); }, -                    0x2c => { instruction.opcode = Opcode::SUB; return Ok(OperandCode::AL_Ib); }, -                    0x2d => { instruction.opcode = Opcode::SUB; return Ok(OperandCode::AX_Ivd); }, -                    0x2e => { -                        instruction.prefixes.set_cs(); -                        alternate_opcode_map = None; -                    }, -                    0x2f => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x30 => { instruction.opcode = Opcode::XOR; return Ok(OperandCode::Eb_Gb); }, -                    0x31 => { instruction.opcode = Opcode::XOR; return Ok(OperandCode::Ev_Gv); }, -                    0x32 => { instruction.opcode = Opcode::XOR; return Ok(OperandCode::Gb_Eb); }, -                    0x33 => { instruction.opcode = Opcode::XOR; return Ok(OperandCode::Gv_Ev); }, -                    0x34 => { instruction.opcode = Opcode::XOR; return Ok(OperandCode::AL_Ib); }, -                    0x35 => { instruction.opcode = Opcode::XOR; return Ok(OperandCode::AX_Ivd); }, -                    0x36 => { -                        instruction.prefixes.set_ss(); -                        alternate_opcode_map = None; -                    }, -                    0x37 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    0x38 => { instruction.opcode = Opcode::CMP; return Ok(OperandCode::Eb_Gb); }, -                    0x39 => { instruction.opcode = Opcode::CMP; return Ok(OperandCode::Ev_Gv); }, -                    0x3a => { instruction.opcode = Opcode::CMP; return Ok(OperandCode::Gb_Eb); }, -                    0x3b => { instruction.opcode = Opcode::CMP; return Ok(OperandCode::Gv_Ev); }, -                    0x3c => { instruction.opcode = Opcode::CMP; return Ok(OperandCode::AL_Ib); }, -                    0x3d => { instruction.opcode = Opcode::CMP; return Ok(OperandCode::AX_Ivd); }, -                    0x3e => { -                        instruction.prefixes.set_ds(); -                        alternate_opcode_map = None; -                    }, -                    0x3f => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                    /* -                    x if x < 0x40 => { -                        if x % 8 > 5 { -                            // for x86_32 this is push/pop prefixes and 0x0f escape -                            // for x86_64 this is mostly invalid -                            match x { -                                0x0f => { -                                    return match alternate_opcode_map { -                                        Some(OpcodeMap::Map66) => { -                                            read_opcode_660f_map(bytes_iter, instruction, length) -                                        }, -                                        Some(OpcodeMap::MapF2) => { -                                            read_opcode_f20f_map(bytes_iter, instruction, length) -                                        }, -                                        Some(OpcodeMap::MapF3) => { -                                            read_opcode_f30f_map(bytes_iter, instruction, length) -                                        }, -                                        None => { -                                            read_opcode_0f_map(bytes_iter, instruction, length) -                                        } -                                    }; -                                }, -                                0x26 => { -                                    instruction.prefixes.set_es(); -                                    alternate_opcode_map = None; -                                }, -                                0x2e => { -                                    instruction.prefixes.set_cs(); -                                    alternate_opcode_map = None; +                instruction.length += 1; +                let record = OPCODES[b as usize]; +                if record.1 == Interpretation::Instruction { +                    instruction.opcode = record.0; +                    return Some(record.2); +                } else { +                    match b { +                        0x0f => { +                            return match alternate_opcode_map { +                                Some(OpcodeMap::Map66) => { +                                    read_opcode_660f_map(bytes_iter, instruction)                                  }, -                                0x36 => { -                                    instruction.prefixes.set_ss(); -                                    alternate_opcode_map = None; +                                Some(OpcodeMap::MapF2) => { +                                    read_opcode_f20f_map(bytes_iter, instruction)                                  }, -                                0x3e => { -                                    instruction.prefixes.set_ds(); -                                    alternate_opcode_map = None; +                                Some(OpcodeMap::MapF3) => { +                                    read_opcode_f30f_map(bytes_iter, instruction)                                  }, -                                0x06 -                                | 0x07 -                                | 0x0e -                                | 0x16 -                                | 0x17 -                                | 0x1e -                                | 0x1f -                                | 0x27 -                                | 0x2f -                                | 0x37 -                                | 0x3f => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::Nothing); }, -                                _ => { unsafe { unreachable_unchecked(); } } -                            } -                            continue; -                        } -                        let op = base_opcode_map(x / 8); -                        let operand_code = match x % 8 { -                            0 => OperandCode::Eb_Gb, -                            1 => OperandCode::Ev_Gv, -                            2 => OperandCode::Gb_Eb, -                            3 => OperandCode::Gv_Ev, -                            4 => OperandCode::AL_Ib, -                            5 => OperandCode::AX_Ivd, -                            _ => { unsafe { unreachable_unchecked(); } } -                        }; - -                        instruction.opcode = op; return Ok(operand_code); -                    }, -                    */ -                    x if x < 0x50 => { -                        // x86_32 inc/dec -                        // x86_64 rex -                        instruction.prefixes.rex_mut().from(x); -                    }, -                    x if x < 0x60 => { -                        let op = if x < 0x58 { Opcode::PUSH } else { Opcode::POP }; -                        instruction.opcode = op; return Ok(OperandCode::Zv(x)); -                    }, -                    0x63 => { instruction.opcode = Opcode::MOVSXD; return Ok(OperandCode::Gv_Ed); } -                    0x64 => { -                        instruction.prefixes.set_fs(); -                        alternate_opcode_map = None; -                    }, -                    0x65 => { -                        instruction.prefixes.set_gs(); -                        alternate_opcode_map = None; -                    }, -                    0x66 => { -                        instruction.prefixes.set_operand_size(); -                        alternate_opcode_map = Some(OpcodeMap::Map66); -                    }, -                    0x67 => { -                        instruction.prefixes.set_address_size(); -                        alternate_opcode_map = None; -                    }, -                    0x68 => { instruction.opcode = Opcode::PUSH; return Ok(OperandCode::Ivs); }, -                    0x69 => { instruction.opcode = Opcode::IMUL; return Ok(OperandCode::Gv_Ev_Iv); }, -                    0x6a => { instruction.opcode = Opcode::PUSH; return Ok(OperandCode::Ibs); }, -                    0x6b => { instruction.opcode = Opcode::IMUL; return Ok(OperandCode::Gb_Eb_Ib); }, -                    0x6c => { instruction.opcode = Opcode::INS; return Ok(OperandCode::Yb_DX); }, -                    0x6d => { instruction.opcode = Opcode::INS; return Ok(OperandCode::Yv_DX); }, -                    0x6e => { instruction.opcode = Opcode::OUTS; return Ok(OperandCode::DX_Xb); }, -                    0x6f => { instruction.opcode = Opcode::OUTS; return Ok(OperandCode::DX_Xv); }, -                    x if x < 0x80 => { -                        instruction.opcode = match x { -                            0x70 => Opcode::JO, -                            0x71 => Opcode::JNO, -                            0x72 => Opcode::JB, -                            0x73 => Opcode::JNB, -                            0x74 => Opcode::JZ, -                            0x75 => Opcode::JNZ, -                            0x76 => Opcode::JNA, -                            0x77 => Opcode::JA, -                            0x78 => Opcode::JS, -                            0x79 => Opcode::JNS, -                            0x7a => Opcode::JP, -                            0x7b => Opcode::JNP, -                            0x7c => Opcode::JL, -                            0x7d => Opcode::JGE, -                            0x7e => Opcode::JLE, -                            0x7f => Opcode::JG, -                            _ => { unsafe { unreachable_unchecked(); } }, -                        }; -                        return Ok(OperandCode::Jbs); -                    } -                    0x80 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0x80_Eb_Ib); }, -                    0x81 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0x81_Ev_Ivs); }, -                    0x82 => { return Err("invalid opcode".to_owned()); }, -                    0x83 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0x83_Ev_Ibs); }, -                    0x84 => { instruction.opcode = Opcode::TEST; return Ok(OperandCode::Eb_Gb); }, -                    0x85 => { instruction.opcode = Opcode::TEST; return Ok(OperandCode::Ev_Gv); }, -                    0x86 => { instruction.opcode = Opcode::XCHG; return Ok(OperandCode::Gb_Eb); }, -                    0x87 => { instruction.opcode = Opcode::XCHG; return Ok(OperandCode::Gv_Ev); }, -                    0x88 => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::Eb_Gb); }, -                    0x89 => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::Ev_Gv); }, -                    0x8a => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::Gb_Eb); }, -                    0x8b => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::Gv_Ev); }, -                    0x8c => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::Ew_Sw); }, -                    0x8d => { instruction.opcode = Opcode::LEA; return Ok(OperandCode::Gv_M); }, -                    0x8e => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::Sw_Ew); }, -                    0x8f => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0x8f_Ev); }, -                    0x90 => { instruction.opcode = Opcode::NOP; return Ok(OperandCode::Nothing); }, -                    0x91 => { instruction.opcode = Opcode::XCHG; return Ok(OperandCode::Zv_AX(0x91)); }, -                    0x92 => { instruction.opcode = Opcode::XCHG; return Ok(OperandCode::Zv_AX(0x92)); }, -                    0x93 => { instruction.opcode = Opcode::XCHG; return Ok(OperandCode::Zv_AX(0x93)); }, -                    0x94 => { instruction.opcode = Opcode::XCHG; return Ok(OperandCode::Zv_AX(0x94)); }, -                    0x95 => { instruction.opcode = Opcode::XCHG; return Ok(OperandCode::Zv_AX(0x95)); }, -                    0x96 => { instruction.opcode = Opcode::XCHG; return Ok(OperandCode::Zv_AX(0x96)); }, -                    0x97 => { instruction.opcode = Opcode::XCHG; return Ok(OperandCode::Zv_AX(0x97)); }, -                    0x98 => { instruction.opcode = Opcode::CBW; return Ok(OperandCode::AX_AL); }, -                    0x99 => { instruction.opcode = Opcode::CBW; return Ok(OperandCode::DX_AX); }, -                    0x9a => { return Err("invalid opcode".to_owned()); }, -                    0x9b => { instruction.opcode = Opcode::WAIT; return Ok(OperandCode::Nothing); }, -                    0x9c => { instruction.opcode = Opcode::PUSHF; return Ok(OperandCode::Nothing); }, -                    0x9d => { instruction.opcode = Opcode::POPF; return Ok(OperandCode::Nothing); }, -                    0x9e => { instruction.opcode = Opcode::SAHF; return Ok(OperandCode::AH); }, -                    0x9f => { instruction.opcode = Opcode::LAHF; return Ok(OperandCode::AH); }, -                    0xa0 => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::AL_Ob); }, -                    0xa1 => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::AX_Ov); }, -                    0xa2 => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::Ob_AL); }, -                    0xa3 => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::Ov_AX); }, -                    0xa4 => { instruction.opcode = Opcode::MOVS; return Ok(OperandCode::Yb_Xb); }, -                    0xa5 => { instruction.opcode = Opcode::MOVS; return Ok(OperandCode::Yv_Xv); }, -                    0xa6 => { instruction.opcode = Opcode::CMPS; return Ok(OperandCode::Yb_Xb); }, -                    0xa7 => { instruction.opcode = Opcode::CMPS; return Ok(OperandCode::Yv_Xv); }, -                    0xa8 => { instruction.opcode = Opcode::TEST; return Ok(OperandCode::AL_Ib); }, -                    0xa9 => { instruction.opcode = Opcode::TEST; return Ok(OperandCode::AX_Ivd); }, -                    0xaa => { instruction.opcode = Opcode::STOS; return Ok(OperandCode::Yb_AL); }, -                    0xab => { instruction.opcode = Opcode::STOS; return Ok(OperandCode::Yv_AX); }, -                    0xac => { instruction.opcode = Opcode::LODS; return Ok(OperandCode::AL_Xb); }, -                    0xad => { instruction.opcode = Opcode::LODS; return Ok(OperandCode::AX_Xv); }, -                    0xae => { instruction.opcode = Opcode::SCAS; return Ok(OperandCode::Yb_AL); }, -                    0xaf => { instruction.opcode = Opcode::SCAS; return Ok(OperandCode::Yv_AX); }, -                    x if x < 0xc0 => { -                        let operand = if x < 0xb8 { -                            OperandCode::Zb_Ib(x) -                        } else { -                            OperandCode::Zv_Ivq(x) -                        }; -                        instruction.opcode = Opcode::MOV; -                        return Ok(operand); -                    }, -                    0xc0 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xc0_Eb_Ib); }, -                    0xc1 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xc1_Ev_Ib); }, -                    0xc2 => { instruction.opcode = Opcode::RETURN; return Ok(OperandCode::Iw); }, -                    0xc3 => { instruction.opcode = Opcode::RETURN; return Ok(OperandCode::Nothing); }, -                    0xc4  | 0xc5 => { -                        return Err("invalid opcode".to_owned()); -                    }, -                    0xc6 => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::ModRM_0xc6_Eb_Ib); }, -                    0xc7 => { instruction.opcode = Opcode::MOV; return Ok(OperandCode::ModRM_0xc7_Ev_Iv); }, -                    0xc8 => { instruction.opcode = Opcode::ENTER; return Ok(OperandCode::Iw_Ib); }, -                    0xc9 => { instruction.opcode = Opcode::LEAVE; return Ok(OperandCode::Nothing); }, -                    0xca => { instruction.opcode = Opcode::RETF; return Ok(OperandCode::Iw); }, -                    0xcb => { instruction.opcode = Opcode::RETF; return Ok(OperandCode::Nothing); }, -                    0xcc => { instruction.opcode = Opcode::INT; return Ok(OperandCode::I_3); }, -                    0xcd => { instruction.opcode = Opcode::INT; return Ok(OperandCode::Ib); }, -                    0xce => { instruction.opcode = Opcode::INTO; return Ok(OperandCode::Fw); }, -                    0xcf => { instruction.opcode = Opcode::IRET; return Ok(OperandCode::Fw); }, -                    0xd0 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xd0_Eb_1); }, -                    0xd1 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xd1_Ev_1); }, -                    0xd2 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xd2_Eb_CL); }, -                    0xd3 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xd3_Ev_CL); }, -                    0xdc => { -                        // TODO: WRONG -                        // x87 instructions -                        instruction.opcode = Opcode::NOP; -                        let _ = read_imm_unsigned(bytes_iter, 2, length)?; -                        return Ok(OperandCode::Nothing); -                    } -                    0xdd => { -                        // x87 instructions -                        // TODO: WRONG -                        instruction.opcode = Opcode::NOP; -                        let _ = read_imm_unsigned(bytes_iter, 2, length)?; -                        return Ok(OperandCode::Nothing); -                    } -                    // TODO: GAP -                    0xe8 => { instruction.opcode = Opcode::CALL; return Ok(OperandCode::Jvds); }, -                    0xe9 => { instruction.opcode = Opcode::JMP; return Ok(OperandCode::Jvds); }, -                    0xeb => { instruction.opcode = Opcode::JMP; return Ok(OperandCode::Jbs); }, -                    0xf0 => { -                        instruction.prefixes.set_lock(); -                    }, -                    0xf2 => { -                        instruction.prefixes.set_repnz(); -                        alternate_opcode_map = Some(OpcodeMap::MapF2); -                    }, -                    0xf3 => { -                        instruction.prefixes.set_rep(); -                        alternate_opcode_map = Some(OpcodeMap::MapF3); -                    }, -                    0xf4 => { instruction.opcode = Opcode::HLT; return Ok(OperandCode::Nothing); }, -                    0xf6 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xf6); }, -                    0xf7 => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xf7); }, -                    0xf8 => { instruction.opcode = Opcode::CLC; return Ok(OperandCode::Nothing); }, -                    0xf9 => { instruction.opcode = Opcode::STC; return Ok(OperandCode::Nothing); }, -                    0xfa => { instruction.opcode = Opcode::CLI; return Ok(OperandCode::Nothing); }, -                    0xfb => { instruction.opcode = Opcode::STI; return Ok(OperandCode::Nothing); }, -                    0xfc => { instruction.opcode = Opcode::CLD; return Ok(OperandCode::Nothing); }, -                    0xfd => { instruction.opcode = Opcode::STD; return Ok(OperandCode::Nothing); }, -                    0xfe => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xfe_Eb); }, -                    // TODO: test 0xff /3 -                    0xff => { instruction.opcode = Opcode::Invalid; return Ok(OperandCode::ModRM_0xff_Ev); }, -                    _ => { -                        return Err("unsupported opcode".to_owned()); +                                None => { +                                    read_opcode_0f_map(bytes_iter, instruction) +                                } +                            }; +                        }, +                        0x26 => { +                            instruction.prefixes.set_es(); +                            alternate_opcode_map = None; +                        }, +                        0x2e => { +                            instruction.prefixes.set_cs(); +                            alternate_opcode_map = None; +                        }, +                        0x36 => { +                            instruction.prefixes.set_ss(); +                            alternate_opcode_map = None; +                        }, +                        0x3e => { +                            instruction.prefixes.set_ds(); +                            alternate_opcode_map = None; +                        }, +                        x if x < 0x50 => { +                            // x86_32 inc/dec +                            // x86_64 rex +                            instruction.prefixes.rex_mut().from(x); +                        }, +                        0x64 => { +                            instruction.prefixes.set_fs(); +                            alternate_opcode_map = None; +                        }, +                        0x65 => { +                            instruction.prefixes.set_gs(); +                            alternate_opcode_map = None; +                        }, +                        0x66 => { +                            instruction.prefixes.set_operand_size(); +                            alternate_opcode_map = Some(OpcodeMap::Map66); +                        }, +                        0x67 => { +                            instruction.prefixes.set_address_size(); +                            alternate_opcode_map = None; +                        }, +                        0xf0 => { +                            instruction.prefixes.set_lock(); +                        }, +                        0xf2 => { +                            instruction.prefixes.set_repnz(); +                            alternate_opcode_map = Some(OpcodeMap::MapF2); +                        }, +                        0xf3 => { +                            instruction.prefixes.set_rep(); +                            alternate_opcode_map = Some(OpcodeMap::MapF3); +                        }, +                        _ => { unsafe { unreachable_unchecked(); } }                      }                  }              },              None => { -                return Err("no more bytes".to_owned()); +                return None;              }          }      }  }  #[allow(non_snake_case)] -fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, prefixes: &Prefixes, m: u8, modbits: u8, width: u8, result: &mut Operand, length: &mut u8) -> Result<(), String> { -    read_E_anybank(bytes_iter, prefixes, m, modbits, width, result, length, width_to_gp_reg_bank(width, prefixes.rex().present())) +fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, result: usize) -> Option<()> { +    let bank = width_to_gp_reg_bank(width, instr.prefixes.rex().present()); +    read_E_anybank(bytes_iter, instr, modrm, width, result, bank)  }  #[allow(non_snake_case)] -fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, prefixes: &Prefixes, m: u8, modbits: u8, width: u8, result: &mut Operand, length: &mut u8) -> Result<(), String> { -    read_E_anybank(bytes_iter, prefixes, m, modbits, width, result, length, RegisterBank::X) +fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, result: usize) -> Option<()> { +    read_E_anybank(bytes_iter, instr, modrm, width, result, RegisterBank::X)  }  #[allow(non_snake_case)] -fn read_E_anybank<T: Iterator<Item=u8>>(bytes_iter: &mut T, prefixes: &Prefixes, m: u8, modbits: u8, _width: u8, result: &mut Operand, length: &mut u8, reg_bank: RegisterBank) -> Result<(), String> { -    let addr_width = if prefixes.address_size() { 4 } else { 8 }; +fn read_E_anybank<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, _width: u8, result: usize, reg_bank: RegisterBank) -> Option<()> { +    let modbits = (modrm >> 6); +    let m = modrm & 7; +    let addr_width = if instr.prefixes.address_size() { 4 } else { 8 };      if modbits == 0b11 { -        *result = Operand::Register(RegSpec::from_parts(m, prefixes.rex().b(), reg_bank)) +        instr.operands[result] = Operand::Register(RegSpec::from_parts(m, instr.prefixes.rex().b(), reg_bank))      } else if m == 5 && modbits == 0b00 { -        let disp = read_num(bytes_iter, 4, length); -        *result = Operand::RegDisp( +        let disp = read_num(bytes_iter, 4, &mut instr.length); +        instr.operands[result] = Operand::RegDisp(              if addr_width == 8 { RegSpec::RIP() } else { RegSpec::EIP() },              disp as i32          );      } else if m == 4 {          let sibbyte = match bytes_iter.next() {              Some(b) => b, -            None => return Err("Out of bytes".to_string()) +            None => { return None; } //Err("Out of bytes".to_string())          }; -        *length += 1; -        let (ss, index, base) = octets_of(sibbyte); +        instr.length += 1; +//         let (ss, index, base) = octets_of(sibbyte);  //            println!("scale: {:b}, index: {:b}, base: {:b}", ss, index, base); -        if base == 0b101 { +        if (sibbyte & 7) == 0b101 {              let disp = if modbits == 0b00 { -                read_num(bytes_iter, 4, length) as i32 +                read_num(bytes_iter, 4, &mut instr.length) as i32              } else if modbits == 0b01 { -                read_num(bytes_iter, 1, length) as i8 as i32 +                read_num(bytes_iter, 1, &mut instr.length) as i8 as i32              } else { -                read_num(bytes_iter, 4, length) as i32 +                read_num(bytes_iter, 4, &mut instr.length) as i32              }; -            if index == 0b100 { -                if modbits == 0b00 && !prefixes.rex().x() { -                    *result = Operand::DisplacementU32(disp as u32); +            if ((sibbyte >> 3) & 7) == 0b100 { +                if modbits == 0b00 && !instr.prefixes.rex().x() { +                    instr.operands[result] = Operand::DisplacementU32(disp as u32);                  } else { -                    let reg = RegSpec::gp_from_parts(0b100, prefixes.rex().x(), addr_width, prefixes.rex().present()); +                    let reg = RegSpec::gp_from_parts(0b100, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present());                      if disp == 0 { -                        *result = Operand::RegDeref(reg); +                        instr.operands[result] = Operand::RegDeref(reg);                      } else { -                        *result = Operand::RegDisp(reg, disp as i32); +                        instr.operands[result] = Operand::RegDisp(reg, disp as i32);                      }                  }              } else { -                let base_reg = RegSpec::gp_from_parts(5, prefixes.rex().b(), addr_width, prefixes.rex().present()); +                let base_reg = RegSpec::gp_from_parts(5, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present()); -                let index_reg = RegSpec::gp_from_parts(index, prefixes.rex().x(), addr_width, prefixes.rex().present()); +                let index_reg = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); +                let scale = 1u8 << (sibbyte >> 6); -                *result = match (ss, modbits, disp) { +                instr.operands[result] = match (scale, modbits, disp) {                      (0, 0b00, 0) => {                          Operand::RegDeref(index_reg)                      }, @@ -1384,78 +1862,178 @@ fn read_E_anybank<T: Iterator<Item=u8>>(bytes_iter: &mut T, prefixes: &Prefixes,                          Operand::RegIndexBaseDisp(base_reg, index_reg, disp as i32)                      },                      (_, 0b00, 0) => { -                        Operand::RegScale(index_reg, 1u8 << ss) +                        Operand::RegScale(index_reg, scale)                      },                      (_, 0b00, _) => { -                        Operand::RegScaleDisp(index_reg, 1u8 << ss, disp as i32) +                        Operand::RegScaleDisp(index_reg, scale, disp as i32)                      },                      (_, _, 0) => { -                        Operand::RegIndexBaseScale(base_reg, index_reg, 1u8 << ss) +                        Operand::RegIndexBaseScale(base_reg, index_reg, scale)                      },                      (_, _, _) => { -                        Operand::RegIndexBaseScaleDisp(base_reg, index_reg, 1u8 << ss, disp as i32) +                        Operand::RegIndexBaseScaleDisp(base_reg, index_reg, scale, disp as i32)                      }                  };              }          } else { -            let base_reg = RegSpec::gp_from_parts(base, prefixes.rex().b(), addr_width, prefixes.rex().present()); +            let base_reg = RegSpec::gp_from_parts((sibbyte & 7), instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present());              let disp = if modbits == 0b00 {                  0              } else if modbits == 0b01 { -                read_num(bytes_iter, 1, length) as i8 as i32 +                read_num(bytes_iter, 1, &mut instr.length) as i8 as i32              } else { -                read_num(bytes_iter, 4, length) as i32 +                read_num(bytes_iter, 4, &mut instr.length) as i32              }; -            if index == 0b100 { +            if ((sibbyte >> 3) & 7) == 0b100 {                  if disp == 0 { -                    *result = Operand::RegDeref(base_reg); +                    instr.operands[result] = Operand::RegDeref(base_reg);                  } else { -                    *result = Operand::RegDisp(base_reg, disp as i32); +                    instr.operands[result] = Operand::RegDisp(base_reg, disp as i32);                  }              } else { -                let index_reg = RegSpec::gp_from_parts(index, prefixes.rex().x(), addr_width, prefixes.rex().present()); +                let index_reg = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); +                let scale = 1u8 << (sibbyte >> 6);                  if disp == 0 { -                    if ss == 0 { -                        *result = Operand::RegIndexBase(base_reg, index_reg) +                    if scale == 0 { +                        instr.operands[result] = Operand::RegIndexBase(base_reg, index_reg)                      } else { -                        *result = Operand::RegIndexBaseScale(base_reg, index_reg, 1u8 << ss); +                        instr.operands[result] = Operand::RegIndexBaseScale(base_reg, index_reg, scale);                      }                  } else { -                    if ss == 0 { +                    if scale == 0 { -                        *result = Operand::RegIndexBaseDisp(base_reg, index_reg, disp as i32); +                        instr.operands[result] = Operand::RegIndexBaseDisp(base_reg, index_reg, disp as i32);                      } else { -                        *result = Operand::RegIndexBaseScaleDisp(base_reg, index_reg, 1u8 << ss, disp as i32); +                        instr.operands[result] = Operand::RegIndexBaseScaleDisp(base_reg, index_reg, scale, disp as i32);                      }                  }              }          }      } else { -        let reg = RegSpec::gp_from_parts(m, prefixes.rex().b(), addr_width, prefixes.rex().present()); +        let reg = RegSpec::gp_from_parts(m, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present());          if modbits == 0b00 { -            *result = Operand::RegDeref(reg); +            instr.operands[result] = Operand::RegDeref(reg);          } else {              let disp = if modbits == 0b01 { -                read_num(bytes_iter, 1, length) as i8 as i32 +                read_num(bytes_iter, 1, &mut instr.length) as i8 as i32              } else { -                read_num(bytes_iter, 4, length) as i32 +                read_num(bytes_iter, 4, &mut instr.length) as i32              }; -            *result = Operand::RegDisp(reg, disp); +            instr.operands[result] = Operand::RegDisp(reg, disp);          }      } -    Ok(()) +    Some(())  }  #[inline] -fn read_operands<T: Iterator<Item=u8>>( -    bytes_iter: &mut T, -    instruction: &mut Instruction, -    operand_code: OperandCode, -    length: &mut u8 -) -> Result<(), String> { +fn width_to_gp_reg_bank(width: u8, rex: bool) -> RegisterBank { +    use std::hint::unreachable_unchecked; +    match width { +        1 => return if rex { RegisterBank::rB } else { RegisterBank::B }, +        2 => return RegisterBank::W, +        4 => return RegisterBank::D, +        8 => return RegisterBank::Q, +        _ => unsafe { unreachable_unchecked(); } +    } +} + +pub fn read_instr<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction) -> Option<()> { +    let mut alternate_opcode_map: Option<OpcodeMap> = None; +    use std::hint::unreachable_unchecked; +//    use std::intrinsics::unlikely; +    instruction.prefixes = Prefixes::new(0); +    let operand_code = loop { +        match bytes_iter.next() { +            Some(b) => { +                instruction.length += 1; +                let record = OPCODES[b as usize]; +                if record.1 == Interpretation::Instruction { +                    instruction.opcode = record.0; +                    break record.2; +                } else { +                    match b { +                        0x0f => { +                            let opc = match alternate_opcode_map { +                                Some(OpcodeMap::Map66) => { +                                    read_opcode_660f_map(bytes_iter, instruction) +                                }, +                                Some(OpcodeMap::MapF2) => { +                                    read_opcode_f20f_map(bytes_iter, instruction) +                                }, +                                Some(OpcodeMap::MapF3) => { +                                    read_opcode_f30f_map(bytes_iter, instruction) +                                }, +                                None => { +                                    read_opcode_0f_map(bytes_iter, instruction) +                                } +                            }; +                            match opc { +                                Some(o) => { +                                    break o; +                                }, +                                None => { return None; } +                            } +                        }, +                        0x26 => { +                            instruction.prefixes.set_es(); +                            alternate_opcode_map = None; +                        }, +                        0x2e => { +                            instruction.prefixes.set_cs(); +                            alternate_opcode_map = None; +                        }, +                        0x36 => { +                            instruction.prefixes.set_ss(); +                            alternate_opcode_map = None; +                        }, +                        0x3e => { +                            instruction.prefixes.set_ds(); +                            alternate_opcode_map = None; +                        }, +                        x if x < 0x50 => { +                            // x86_32 inc/dec +                            // x86_64 rex +                            instruction.prefixes.rex_mut().from(x); +                        }, +                        0x64 => { +                            instruction.prefixes.set_fs(); +                            alternate_opcode_map = None; +                        }, +                        0x65 => { +                            instruction.prefixes.set_gs(); +                            alternate_opcode_map = None; +                        }, +                        0x66 => { +                            instruction.prefixes.set_operand_size(); +                            alternate_opcode_map = Some(OpcodeMap::Map66); +                        }, +                        0x67 => { +                            instruction.prefixes.set_address_size(); +                            alternate_opcode_map = None; +                        }, +                        0xf0 => { +                            instruction.prefixes.set_lock(); +                        }, +                        0xf2 => { +                            instruction.prefixes.set_repnz(); +                            alternate_opcode_map = Some(OpcodeMap::MapF2); +                        }, +                        0xf3 => { +                            instruction.prefixes.set_rep(); +                            alternate_opcode_map = Some(OpcodeMap::MapF3); +                        }, +                        _ => { unsafe { unreachable_unchecked(); } } +                    } +                } +            }, +            None => { +                return None; +            } +        } +    };      match operand_code {          /*          Gv_Ev_Iv, @@ -1505,21 +2083,21 @@ fn read_operands<T: Iterator<Item=u8>>(          */          OperandCode::Eb_R0 => {              let opwidth = 1; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            if r != 0 { +            if (modrm & 0b00111000) != 0 {                  instruction.opcode = Opcode::Invalid; -                return Err("Invalid modr/m for opcode 0xc6".to_owned()); +                return None; // Err("Invalid modr/m for opcode 0xc6".to_owned());              } -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();          },          OperandCode::AL_Ob => {              let _addr_width = if instruction.prefixes.address_size() { 4 } else { 8 };              // stupid RCT thing:              let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 };              let opwidth = 1; -            let imm = read_num(bytes_iter, addr_width, length); +            let imm = read_num(bytes_iter, addr_width, &mut instruction.length);              instruction.operands = [                  Operand::Register(RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())),                  if instruction.prefixes.address_size() { @@ -1534,7 +2112,7 @@ fn read_operands<T: Iterator<Item=u8>>(              // stupid RCT thing:              let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 };              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let imm = read_num(bytes_iter, addr_width, length); +            let imm = read_num(bytes_iter, addr_width, &mut instruction.length);              instruction.operands = [                  Operand::Register(RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())),                  if instruction.prefixes.address_size() { @@ -1549,7 +2127,7 @@ fn read_operands<T: Iterator<Item=u8>>(              // stupid RCT thing:              let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 };              let opwidth = 1; -            let imm = read_num(bytes_iter, addr_width, length); +            let imm = read_num(bytes_iter, addr_width, &mut instruction.length);              instruction.operands = [                  if instruction.prefixes.address_size() {                      Operand::DisplacementU32(imm as u32) @@ -1564,7 +2142,7 @@ fn read_operands<T: Iterator<Item=u8>>(              // stupid RCT thing:              let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 };              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let imm = read_num(bytes_iter, addr_width, length); +            let imm = read_num(bytes_iter, addr_width, &mut instruction.length);              instruction.operands = [                  if instruction.prefixes.address_size() {                      Operand::DisplacementU32(imm as u32) @@ -1576,90 +2154,90 @@ fn read_operands<T: Iterator<Item=u8>>(          }          OperandCode::ModRM_0x80_Eb_Ib => {              let opwidth = 1; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            let num = read_num(bytes_iter, 1, length) as i8; -            instruction.opcode = base_opcode_map(r); +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            let num = read_num(bytes_iter, 1, &mut instruction.length) as i8; +            instruction.opcode = base_opcode_map((modrm >> 3) & 7);              instruction.operands[1] = Operand::ImmediateI8(num);          },          OperandCode::ModRM_0x81_Ev_Ivs => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            let imm = read_imm_signed(bytes_iter, if opwidth == 8 { 4 } else { opwidth }, opwidth, length)?; -            instruction.opcode = base_opcode_map(r); +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            let imm = read_imm_signed(bytes_iter, if opwidth == 8 { 4 } else { opwidth }, opwidth, &mut instruction.length).unwrap(); +            instruction.opcode = base_opcode_map((modrm >> 3) & 7);              instruction.operands[1] = imm;          },          OperandCode::ModRM_0xc0_Eb_Ib => {              let opwidth = 1; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            let num = read_num(bytes_iter, 1, length) as i8; -            instruction.opcode = BITWISE_OPCODE_MAP[r as usize].clone(); +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            let num = read_num(bytes_iter, 1, &mut instruction.length) as i8; +            instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();              instruction.operands[1] = Operand::ImmediateI8(num);          },          OperandCode::ModRM_0xc1_Ev_Ib => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            let num = read_num(bytes_iter, 1, length) as i8; -            instruction.opcode = BITWISE_OPCODE_MAP[r as usize].clone(); +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            let num = read_num(bytes_iter, 1, &mut instruction.length) as i8; +            instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();              instruction.operands[1] = Operand::ImmediateI8(num);          },          OperandCode::ModRM_0xc6_Eb_Ib => {              let opwidth = 1; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            let num = read_num(bytes_iter, 1, length) as i8; -            if r != 0 { +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            let num = read_num(bytes_iter, 1, &mut instruction.length) as i8; +            if (modrm & 0b00111000) != 0 {                  instruction.opcode = Opcode::Invalid; -                return Err("Invalid modr/m for opcode 0xc6".to_owned()); +                return None; // Err("Invalid modr/m for opcode 0xc6".to_owned());              }              instruction.opcode = Opcode::MOV;              instruction.operands[1] = Operand::ImmediateI8(num);          },          OperandCode::ModRM_0xc7_Ev_Iv => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            if r != 0 { +            if (modrm & 0b00111000) != 0 {                  instruction.opcode = Opcode::Invalid; -                return Err("Invalid modr/m for opcode 0xc7".to_string()); +                return None; // Err("Invalid modr/m for opcode 0xc7".to_string());              } -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();              instruction.opcode = Opcode::MOV; -            instruction.operands[1] = read_imm_unsigned(bytes_iter, opwidth, length)?; +            instruction.operands[1] = read_imm_unsigned(bytes_iter, opwidth, &mut instruction.length).unwrap();          },          OperandCode::ModRM_0xd0_Eb_1 => {              let opwidth = 1; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            instruction.opcode = BITWISE_OPCODE_MAP[r as usize]; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();              instruction.operands[1] = Operand::ImmediateI8(1);          },          OperandCode::ModRM_0xd1_Ev_1 => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            instruction.opcode = BITWISE_OPCODE_MAP[r as usize]; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();              instruction.operands[1] = Operand::ImmediateI8(1);          },          OperandCode::ModRM_0xf6 => {              let opwidth = 1; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            match r { +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            match (modrm >> 3) & 7 {                  0 | 1 => {                      instruction.opcode = Opcode::TEST; -                    instruction.operands[1] = read_imm_signed(bytes_iter, 1, opwidth, length)?; +                    instruction.operands[1] = read_imm_signed(bytes_iter, 1, opwidth, &mut instruction.length).unwrap();                  },                  2 => {                      instruction.opcode = Opcode::NOT; @@ -1686,13 +2264,13 @@ fn read_operands<T: Iterator<Item=u8>>(          },          OperandCode::ModRM_0xf7 => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            match r { +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            match ((modrm >> 3) & 7) {                  0 | 1 => {                      instruction.opcode = Opcode::TEST;                      let numwidth = if opwidth == 8 { 4 } else { opwidth }; -                    instruction.operands[1] = read_imm_signed(bytes_iter, numwidth, opwidth, length)?; +                    instruction.operands[1] = read_imm_signed(bytes_iter, numwidth, opwidth, &mut instruction.length).unwrap();                  },                  2 => {                      instruction.opcode = Opcode::NOT; @@ -1719,9 +2297,9 @@ fn read_operands<T: Iterator<Item=u8>>(          },          OperandCode::ModRM_0xfe_Eb => {              let opwidth = 1; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();              instruction.opcode = [                  Opcode::INC,                  Opcode::DEC, @@ -1731,14 +2309,14 @@ fn read_operands<T: Iterator<Item=u8>>(                  Opcode::Invalid,                  Opcode::Invalid,                  Opcode::Invalid -            ][r as usize]; +            ][((modrm >> 3) & 7) as usize];              instruction.operands[1] = Operand::Nothing;          }          OperandCode::ModRM_0xff_Ev => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();              let opcode = [                  Opcode::INC,                  Opcode::DEC, @@ -1748,136 +2326,140 @@ fn read_operands<T: Iterator<Item=u8>>(                  Opcode::JMPF,                  Opcode::PUSH,                  Opcode::Invalid -            ][r as usize]; +            ][((modrm >> 3) & 7) as usize];              instruction.opcode = opcode;              instruction.operands[1] = Operand::Nothing;          }          OperandCode::Ev => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, _, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();              instruction.operands[1] = Operand::Nothing;          },          OperandCode::Eb_Gb => {              let opwidth = 1; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();              instruction.operands[1] = -                Operand::Register(RegSpec::gp_from_parts(r, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          },          OperandCode::Ev_Gv => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();              instruction.operands[1] = -                Operand::Register(RegSpec::gp_from_parts(r, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          },          OperandCode::Gb_Eb => {              let opwidth = 1; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 1).unwrap();              instruction.operands[0] = -                Operand::Register(RegSpec::gp_from_parts(r, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          },          OperandCode::Gv_Eb => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 1).unwrap();              instruction.operands[0] = -                Operand::Register(RegSpec::gp_from_parts(r, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          },          OperandCode::Gv_Ew => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[1], length)?; +            read_E(bytes_iter, instruction, modrm, 2, 1).unwrap();              instruction.operands[0] = -                Operand::Register(RegSpec::gp_from_parts(r, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          },          OperandCode::Ew_Sw => {              let opwidth = 2; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            if r > 5 { -                return Err("Invalid r".to_owned()); +            // check r +            if ((modrm >> 3) & 7) > 5 { +                return None; //Err("Invalid r".to_owned());              }              instruction.operands[1] = -                Operand::Register(RegSpec { bank: RegisterBank::S, num: r }); +                Operand::Register(RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }); +            let mod_bits = modrm >> 6;              if mod_bits == 0b11 {                  instruction.operands[0] = -                    Operand::Register(RegSpec { bank: RegisterBank::W, num: m }); +                    Operand::Register(RegSpec { bank: RegisterBank::W, num: modrm & 7});              } else { -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +                read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();              }          },          OperandCode::Sw_Ew => {              let opwidth = 2; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); -            if r > 5 { -                return Err("Invalid r".to_owned()); +            // check r +            if ((modrm >> 3) & 7) > 5 { +                return None; // Err("Invalid r".to_owned());              }              instruction.operands[0] = -                Operand::Register(RegSpec { bank: RegisterBank::S, num: r }); +                Operand::Register(RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }); +            let mod_bits = modrm >> 6;              if mod_bits == 0b11 {                  instruction.operands[1] = -                    Operand::Register(RegSpec { bank: RegisterBank::W, num: m }); +                    Operand::Register(RegSpec { bank: RegisterBank::W, num: modrm & 7});              } else { -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1], length)?; +                read_E(bytes_iter, instruction, modrm, opwidth, 1).unwrap();              }          },          // TODO: verify M          OperandCode::Gv_Ed => {              let opwidth = 4; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap();  //                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 1).unwrap();              instruction.operands[0] = -                Operand::Register(RegSpec::gp_from_parts(r, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          },          OperandCode::Gv_Ev | OperandCode::Gv_M => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap();  //                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 1).unwrap();              instruction.operands[0] = -                Operand::Register(RegSpec::gp_from_parts(r, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          },          OperandCode::E_G_xmm => {              let opwidth = 8; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap();  //                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); -            read_E_xmm(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +            read_E_xmm(bytes_iter, instruction, modrm, opwidth, 0).unwrap();              instruction.operands[1] = -                Operand::Register(RegSpec::from_parts(r, instruction.prefixes.rex().r(), RegisterBank::X)); +                Operand::Register(RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X));          },          OperandCode::G_E_xmm => {              let opwidth = 8; -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap();  //                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); -            read_E_xmm(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1], length)?; +            read_E_xmm(bytes_iter, instruction, modrm, opwidth, 1).unwrap();              instruction.operands[0] = -                Operand::Register(RegSpec::from_parts(r, instruction.prefixes.rex().r(), RegisterBank::X)); +                Operand::Register(RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X));          },          OperandCode::Zv_Ivq(opcode_byte) => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let reg_idx = opcode_byte & 0x7;              instruction.operands = [                  Operand::Register(RegSpec::gp_from_parts(reg_idx, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())), -                read_imm_ivq(bytes_iter, opwidth, length)? +                read_imm_ivq(bytes_iter, opwidth, &mut instruction.length).unwrap()              ];          },          OperandCode::AL_Ib => { @@ -1885,7 +2467,7 @@ fn read_operands<T: Iterator<Item=u8>>(              let numwidth = 1;              instruction.operands = [                  Operand::Register(RegSpec::al()), -                read_imm_signed(bytes_iter, numwidth, opwidth, length)? +                read_imm_signed(bytes_iter, numwidth, opwidth, &mut instruction.length).unwrap()              ];          }          OperandCode::AX_Ivd => { @@ -1893,49 +2475,49 @@ fn read_operands<T: Iterator<Item=u8>>(              let numwidth = if opwidth == 8 { 4 } else { opwidth };              instruction.operands = [                  Operand::Register(RegSpec::gp_from_parts(0, false, opwidth, false)), -                read_imm_signed(bytes_iter, numwidth, opwidth, length)? +                read_imm_signed(bytes_iter, numwidth, opwidth, &mut instruction.length).unwrap()              ];          }          OperandCode::Zb_Ib(opcode_byte) => {              let reg_idx = opcode_byte & 0x7;              instruction.operands = [                  Operand::Register(RegSpec::gp_from_parts(reg_idx, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())), -                read_imm_unsigned(bytes_iter, 1, length)? +                read_imm_unsigned(bytes_iter, 1, &mut instruction.length).unwrap()              ];          },          OperandCode::Iw => {              instruction.operands = [ -                read_imm_unsigned(bytes_iter, 2, length)?, +                read_imm_unsigned(bytes_iter, 2, &mut instruction.length).unwrap(),                  Operand::Nothing              ];          }          OperandCode::Jbs => {              // TODO: arch width (8 in 64, 4 in 32, 2 in 16)              instruction.operands = [ -                read_imm_signed(bytes_iter, 1, 8, length)?, +                read_imm_signed(bytes_iter, 1, 8, &mut instruction.length).unwrap(),                  Operand::Nothing              ];          },          OperandCode::Ibs => {              instruction.operands = [ -                read_imm_signed(bytes_iter, 1, 8, length)?, +                read_imm_signed(bytes_iter, 1, 8, &mut instruction.length).unwrap(),                  Operand::Nothing              ];          },          OperandCode::Ivs => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vd, &instruction.prefixes);              instruction.operands = [ -                read_imm_unsigned(bytes_iter, opwidth, length)?, +                read_imm_unsigned(bytes_iter, opwidth, &mut instruction.length).unwrap(),                  Operand::Nothing              ];          },          OperandCode::ModRM_0x83_Ev_Ibs => { -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap();              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; -            instruction.opcode = base_opcode_map(r); -            instruction.operands[1] = read_imm_signed(bytes_iter, 1, opwidth, length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            instruction.opcode = base_opcode_map((modrm >> 3) & 7); +            instruction.operands[1] = read_imm_signed(bytes_iter, 1, opwidth, &mut instruction.length).unwrap();          },          OperandCode::Zv(opcode_byte) => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); @@ -1946,56 +2528,60 @@ fn read_operands<T: Iterator<Item=u8>>(              ), Operand::Nothing];          },          OperandCode::Jvds => { -            let offset = read_num(bytes_iter, 4, length); +            let offset = read_num(bytes_iter, 4, &mut instruction.length);              instruction.operands = [Operand::ImmediateI32(offset as i32), Operand::Nothing];          }          OperandCode::ModRM_0x0f00 => { -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            let r = (modrm >> 3) & 7;              if r == 0 {                  instruction.opcode = Opcode::SLDT;                  instruction.operands[1] = Operand::Nothing; -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[0], length)?;              } else if r == 1 {                  instruction.opcode = Opcode::STR;                  instruction.operands[1] = Operand::Nothing; -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[0], length)?;              } else if r == 2 {                  instruction.opcode = Opcode::LLDT;                  instruction.operands[1] = Operand::Nothing; -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[0], length)?;              } else if r == 3 {                  instruction.opcode = Opcode::LTR;                  instruction.operands[1] = Operand::Nothing; -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[0], length)?;              } else if r == 4 {                  instruction.opcode = Opcode::VERR;                  instruction.operands[1] = Operand::Nothing; -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[0], length)?;              } else if r == 5 {                  instruction.opcode = Opcode::VERW;                  instruction.operands[1] = Operand::Nothing; -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[0], length)?;              } else if r == 6 {                  instruction.opcode = Opcode::JMPE;                  instruction.operands = [Operand::Nothing, Operand::Nothing]; +                return Some(());              } else if r == 7 { -                return Err("Invalid modr/m bits".to_owned()); +                instruction.opcode = Opcode::Invalid; +                instruction.operands = [Operand::Nothing, Operand::Nothing]; +                return Some(());              } else {                  unreachable!("r <= 8");              } +            read_E(bytes_iter, instruction, modrm, 2, 0).unwrap();          }          OperandCode::ModRM_0x0f01 => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            let r = (modrm >> 3) & 7;              if r == 0 { +                let mod_bits = modrm >> 6; +                let m = modrm & 7;                  if mod_bits == 0b11 {                      panic!("Unsupported instruction: 0x0f01 with modrm: 11 000 ___");                  } else {                      instruction.opcode = Opcode::SGDT;                      instruction.operands[1] = Operand::Nothing; -                    read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +                    read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();                  }              } else if r == 1 { +                let mod_bits = modrm >> 6; +                let m = modrm & 7;                  if mod_bits == 0b11 {                      // TOOD: MONITOR                      instruction.opcode = Opcode::NOP; @@ -2003,9 +2589,11 @@ fn read_operands<T: Iterator<Item=u8>>(                  } else {                      instruction.opcode = Opcode::SIDT;                      instruction.operands[1] = Operand::Nothing; -                    read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +                    read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();                  }              } else if r == 2 { +                let mod_bits = modrm >> 6; +                let m = modrm & 7;                  if mod_bits == 0b11 {                      // TOOD: XGETBV                      instruction.opcode = Opcode::NOP; @@ -2013,9 +2601,11 @@ fn read_operands<T: Iterator<Item=u8>>(                  } else {                      instruction.opcode = Opcode::LGDT;                      instruction.operands[1] = Operand::Nothing; -                    read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +                    read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();                  }              } else if r == 3 { +                let mod_bits = modrm >> 6; +                let m = modrm & 7;                  if mod_bits == 0b11 {                      // TOOD: VMRUN                      instruction.opcode = Opcode::NOP; @@ -2023,21 +2613,23 @@ fn read_operands<T: Iterator<Item=u8>>(                  } else {                      instruction.opcode = Opcode::LIDT;                      instruction.operands[1] = Operand::Nothing; -                    read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +                    read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();                  }              } else if r == 4 {                  // TODO: this permits storing only to word-size registers -                // spec suggets this might do something different for f.ex rdi? +                // spec suggets this might do something different for f.ex rdi.unwrap()                  instruction.opcode = Opcode::SMSW;                  instruction.operands[1] = Operand::Nothing; -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[0], length)?; +                read_E(bytes_iter, instruction, modrm, 2, 0).unwrap();              } else if r == 5 {                  panic!("Unsupported instruction: 0x0f01 with modrm: __ 101 ___");              } else if r == 6 {                  instruction.opcode = Opcode::LMSW;                  instruction.operands[1] = Operand::Nothing; -                read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[0], length)?; +                read_E(bytes_iter, instruction, modrm, 2, 0).unwrap();              } else if r == 7 { +                let mod_bits = modrm >> 6; +                let m = modrm & 7;                  if mod_bits == 0b11 {                      if m == 1 {                          instruction.opcode = Opcode::SWAPGS; @@ -2047,63 +2639,60 @@ fn read_operands<T: Iterator<Item=u8>>(                          instruction.operands = [Operand::Nothing, Operand::Nothing];                      } else {                      //    panic!("Unsupported instruction: 0x0f01 with modrm: 11 110 r >= 2"); -                        return Err("unsupported 0x0f01 variant".to_string()) +                        return None; // Err("unsupported 0x0f01 variant".to_string())                      }                  } else {                      instruction.opcode = Opcode::INVLPG;                      instruction.operands[1] = Operand::Nothing; -                    read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +                    read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap();                  }              } else {                  unreachable!("r <= 8");              }          }          OperandCode::ModRM_0x0fae => { -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            let r = (modrm >> 3) & 7; +            let mod_bits = modrm >> 6;              match r {                  0 => {                      if mod_bits == 0b11 { -                        return Err("Invalid mod bits".to_owned()) +                        return None; // Err("Invalid mod bits".to_owned())                      } else {                          instruction.opcode = Opcode::FXSAVE;                          instruction.operands[1] = Operand::Nothing; -                        read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 8, &mut instruction.operands[0], length)?;                      }                  }                  1 => {                      if mod_bits == 0b11 { -                        return Err("Invalid mod bits".to_owned()); +                        return None; // Err("Invalid mod bits".to_owned());                      } else {                          instruction.opcode = Opcode::FXRSTOR;                          instruction.operands[1] = Operand::Nothing; -                        read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 8, &mut instruction.operands[0], length)?;                      }                  }                  2 => {                      if mod_bits == 0b11 { -                        return Err("Invalid mod bits".to_owned()); +                        return None; // Err("Invalid mod bits".to_owned());                      } else {                          instruction.opcode = Opcode::LDMXCSR;                          instruction.operands[1] = Operand::Nothing; -                        read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 8, &mut instruction.operands[0], length)?;                      }                  }                  3 => {                      if mod_bits == 0b11 { -                        return Err("Invalid mod bits".to_owned()); +                        return None; //Err("Invalid mod bits".to_owned());                      } else {                          instruction.opcode = Opcode::STMXCSR;                          instruction.operands[1] = Operand::Nothing; -                        read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 8, &mut instruction.operands[0], length)?;                      }                  }                  4 => {                      if mod_bits == 0b11 { -                        return Err("Invalid mod bits".to_owned()); +                        return None; //Err("Invalid mod bits".to_owned());                      } else {                          instruction.opcode = Opcode::XSAVE;                          instruction.operands[1] = Operand::Nothing; -                        read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 8, &mut instruction.operands[0], length)?;                      }                  }                  5 => { @@ -2113,41 +2702,42 @@ fn read_operands<T: Iterator<Item=u8>>(                      } else {                          instruction.opcode = Opcode::XSTOR;                          instruction.operands[1] = Operand::Nothing; -                        read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 8, &mut instruction.operands[0], length)?;                      }                  }                  6 => {                      if mod_bits == 0b11 {                          instruction.opcode = Opcode::MFENCE;                          instruction.operands = [Operand::Nothing, Operand::Nothing]; +                        return Some(());                      } else { -                        // TODO: radare reports this, but i'm not sure? +                        // TODO: radare reports this, but i'm not sure.unwrap()                          instruction.opcode = Opcode::XSAVEOPT;                          instruction.operands[1] = Operand::Nothing; -                        read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 8, &mut instruction.operands[0], length)?;                      }                  }                  7 => {                      if mod_bits == 0b11 {                          instruction.opcode = Opcode::SFENCE;                          instruction.operands = [Operand::Nothing, Operand::Nothing]; +                        return Some(());                      } else { -                        // TODO: radare reports this, but i'm not sure? +                        // TODO: radare reports this, but i'm not sure.unwrap()                          instruction.opcode = Opcode::CLFLUSH;                          instruction.operands[1] = Operand::Nothing; -                        read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 8, &mut instruction.operands[0], length)?;                      }                  }                  _ => { unreachable!("r < 6"); }              } +            read_E(bytes_iter, instruction, modrm, 8, 0).unwrap();          }          OperandCode::ModRM_0x0fba => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); -            let (mod_bits, r, m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            let r = (modrm >> 3) & 7;              match r {                  0 | 1 | 2 | 3 => {                      instruction.opcode = Opcode::Invalid; -                    return Err("invalid instruction".to_string()); +                    return None; //Err("invalid instruction".to_string());                  },                  4 => {                      instruction.opcode = Opcode::BT; @@ -2166,13 +2756,15 @@ fn read_operands<T: Iterator<Item=u8>>(                  }              } -            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; +            read_E(bytes_iter, instruction, modrm, opwidth, 0).unwrap(); -            instruction.operands[1] = read_imm_signed(bytes_iter, 1, 1, length)?; +            instruction.operands[1] = read_imm_signed(bytes_iter, 1, 1, &mut instruction.length).unwrap();          }          OperandCode::Rq_Cq_0 => { -            let (_, mut r, mut m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            let mut m = modrm & 7; +            let mut r = (modrm >> 3) & 7;              if instruction.prefixes.rex().r() {                  r += 0b1000;              } @@ -2185,7 +2777,9 @@ fn read_operands<T: Iterator<Item=u8>>(              ];          }          OperandCode::Rq_Dq_0 => { -            let (_, mut r, mut m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            let mut m = modrm & 7; +            let mut r = (modrm >> 3) & 7;              if instruction.prefixes.rex().r() {                  r += 0b1000;              } @@ -2198,7 +2792,9 @@ fn read_operands<T: Iterator<Item=u8>>(              ];          }          OperandCode::Cq_Rq_0 => { -            let (_, mut r, mut m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            let mut m = modrm & 7; +            let mut r = (modrm >> 3) & 7;              if instruction.prefixes.rex().r() {                  r += 0b1000;              } @@ -2211,7 +2807,9 @@ fn read_operands<T: Iterator<Item=u8>>(              ];          }          OperandCode::Dq_Rq_0 => { -            let (_, mut r, mut m) = read_modrm(bytes_iter, length)?; +            let modrm = read_modrm(bytes_iter, &mut instruction.length).unwrap(); +            let mut m = modrm & 7; +            let mut r = (modrm >> 3) & 7;              if instruction.prefixes.rex().r() {                  r += 0b1000;              } @@ -2239,33 +2837,24 @@ fn read_operands<T: Iterator<Item=u8>>(              instruction.operands = [Operand::Nothing, Operand::Nothing];              instruction.opcode = Opcode::Invalid;          //    use std::hint::unreachable_unchecked; -            return Err(format!("unsupported operand code: {:?}", operand_code)); +            return None; // Err(format!("unsupported operand code: {:.unwrap()}", operand_code));          //    unsafe { unreachable_unchecked(); }          }      }; -    Ok(()) -} -#[inline] -fn width_to_gp_reg_bank(width: u8, rex: bool) -> RegisterBank { -    use std::hint::unreachable_unchecked; -    match width { -        1 => return if rex { RegisterBank::rB } else { RegisterBank::B }, -        2 => return RegisterBank::W, -        4 => return RegisterBank::D, -        8 => return RegisterBank::Q, -        _ => unsafe { unreachable_unchecked(); } -    } +    Some(())  }  pub fn decode_one<'b, T: IntoIterator<Item=u8>>(bytes: T, instr: &'b mut Instruction) -> Option<()> {      let mut bytes_iter = bytes.into_iter(); -    let mut len: u8 = 0; -    match read_opcode(&mut bytes_iter, instr, &mut len) { -        Ok(operand_code) => { -            match read_operands(&mut bytes_iter, instr, operand_code, &mut len) { +    instr.length = 0; +    read_instr(&mut bytes_iter, instr) +} +/* +    match read_opcode(&mut bytes_iter, instr) { +        Some(operand_code) => { +            match read_operands(&mut bytes_iter, instr, operand_code) {                  Ok(()) => { -                    instr.length = len;                      Some(())                  },                  Err(_reason) => { @@ -2276,7 +2865,8 @@ pub fn decode_one<'b, T: IntoIterator<Item=u8>>(bytes: T, instr: &'b mut Instruc                  }              }          } -        Err(_reason) => { +//        Err(_reason) => { +        None => {  //            panic!("Decode error on opcode: {:?}", reason);          //    println!("Invalid instruction: {}", reason);  //                return Instruction::invalid() @@ -2284,6 +2874,7 @@ pub fn decode_one<'b, T: IntoIterator<Item=u8>>(bytes: T, instr: &'b mut Instruc          }      }  } +*/  #[inline]  fn read_num<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8) -> u64 { @@ -2392,12 +2983,12 @@ fn imm_width_from_prefixes_64(interpretation: SizeCode, prefixes: &Prefixes) ->  }  #[inline] -fn read_modrm<T: Iterator<Item=u8>>(bytes_iter: &mut T, length: &mut u8) -> Result<(u8, u8, u8), String> { +fn read_modrm<T: Iterator<Item=u8>>(bytes_iter: &mut T, length: &mut u8) -> Result<u8, String> {      let modrm = match bytes_iter.next() {          Some(b) => b,          // TODO: ...          None => return Err("Out of bytes".to_string()),      };      *length += 1; -    Ok(octets_of(modrm)) +    Ok(modrm)  } | 
