aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2019-07-21 01:10:51 -0700
committeriximeow <me@iximeow.net>2020-01-12 16:10:13 -0800
commita6e827989857bd1b130cbff41ec373871b523b12 (patch)
tree5019cc802dc53d916ba1625af984adbebeabda53
parentde6f39460833ddc097e089313629a69c5d6d8b7e (diff)
table-driven decodes
-rw-r--r--src/lib.rs2037
1 files changed, 1314 insertions, 723 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 015b45f..1bf98f7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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)
}