diff options
Diffstat (limited to 'src/lib.rs')
-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) } |