diff options
-rw-r--r-- | src/display.rs | 4 | ||||
-rw-r--r-- | src/lib.rs | 634 | ||||
-rw-r--r-- | test/test.rs | 57 |
3 files changed, 488 insertions, 207 deletions
diff --git a/src/display.rs b/src/display.rs index e70734d..0694265 100644 --- a/src/display.rs +++ b/src/display.rs @@ -418,7 +418,8 @@ impl fmt::Display for Opcode { &Opcode::SETGE => write!(f, "{}", "setge"), &Opcode::SETLE => write!(f, "{}", "setle"), &Opcode::SETG => write!(f, "{}", "setg"), - &Opcode::Invalid => write!(f, "{}", "invalid") + &Opcode::Invalid => write!(f, "{}", "invalid"), + _ => { unimplemented!("some other instruction"); }, } } } @@ -648,6 +649,7 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode { Opcode::UD2 | Opcode::Invalid => { write!(out, "{}", colors.invalid_op(self)) } + _ => { unimplemented!("some other instruction"); }, } } } @@ -35,6 +35,26 @@ enum OpcodeMap { MapF3, } +#[derive(Debug)] +pub enum ConditionCode { + O, + NO, + B, + AE, + Z, + NZ, + A, + BE, + S, + NS, + P, + NP, + L, + GE, + G, + LE, +} + #[allow(non_snake_case)] impl RegSpec { #[inline] @@ -327,7 +347,7 @@ fn operand_size() { assert_eq!(std::mem::size_of::<OperandSpec>(), 1); assert_eq!(std::mem::size_of::<RegSpec>(), 2); assert_eq!(std::mem::size_of::<Prefixes>(), 4); - assert_eq!(std::mem::size_of::<Instruction>(), 3); + assert_eq!(std::mem::size_of::<Instruction>(), 40); } #[allow(non_camel_case_types)] @@ -572,6 +592,110 @@ pub enum Opcode { MOVDQ2Q, RSQRTSS, RCPSS, + + ADDPS, + ANDNPS, + ANDPS, + BSWAP, + CMPPS, + COMISS, + CVTDQ2PS, + CVTPI2PS, + CVTPS2PD, + CVTPS2PI, + CVTTPS2PI, + DIVPS, + EMMS, + GETSEC, + LFS, + LGS, + LSS, + MASKMOVQ, + MAXPS, + MINPS, + MOVAPS, + MOVD, + MOVHPS, + MOVMSKPS, + MOVNTI, + MOVNTPS, + MOVNTQ, + MULPS, + ORPS, + PACKSSDW, + PACKSSWB, + PACKUSWB, + PADDB, + PADDD, + PADDQ, + PADDSB, + PADDSW, + PADDUSB, + PADDUSW, + PADDW, + PAND, + PANDN, + PAVGB, + PAVGW, + PCMPEQB, + PCMPEQD, + PCMPEQW, + PCMPGTB, + PCMPGTD, + PCMPGTW, + PEXTRW, + PINSRW, + PMADDWD, + PMAXSW, + PMAXUB, + PMINSW, + PMINUB, + PMOVMSKB, + PMULHUW, + PMULHW, + PMULLW, + PMULUDQ, + POR, + PSADBW, + PSHUFW, + PSLLD, + PSLLQ, + PSLLW, + PSRAD, + PSRAW, + PSRLD, + PSRLQ, + PSRLW, + PSUBB, + PSUBD, + PSUBQ, + PSUBSB, + PSUBSW, + PSUBUSB, + PSUBUSW, + PSUBW, + PUNPCKHBW, + PUNPCKHDQ, + PUNPCKHWD, + PUNPCKLBW, + PUNPCKLDQ, + PUNPCKLWD, + PXOR, + RCPPS, + RSM, + RSQRTPS, + SHLD, + SHUFPS, + SLHD, + SQRTPS, + SUBPS, + SYSENTER, + SYSEXIT, + UCOMISS, + UD2E, + VMREAD, + VMWRITE, + XORPS, } #[derive(Debug)] pub struct Instruction { @@ -580,6 +704,7 @@ pub struct Instruction { modrm_mmm: RegSpec, // doubles as sib_base sib_index: RegSpec, scale: u8, + length: u8, operand_count: u8, operands: [OperandSpec; 4], imm: u64, @@ -638,7 +763,7 @@ impl Arch for x86_64 { impl LengthedInstruction for Instruction { type Unit = u64; fn len(&self) -> u64 { - 1 //self.length.into() + self.length.into() } fn min_size() -> u64 { 1 @@ -658,7 +783,89 @@ impl Decodable for Instruction { } } +impl Opcode { + pub fn condition(&self) -> Option<ConditionCode> { + match self { + Opcode::JO | + Opcode::CMOVO | + Opcode::SETO => { Some(ConditionCode::O) }, + Opcode::JNO | + Opcode::CMOVNO | + Opcode::SETNO => { Some(ConditionCode::NO) }, + Opcode::JB | + Opcode::CMOVB | + Opcode::SETB => { Some(ConditionCode::B) }, + Opcode::JNB | + Opcode::CMOVNB | + Opcode::SETAE => { Some(ConditionCode::AE) }, + Opcode::JZ | + Opcode::CMOVZ | + Opcode::SETZ => { Some(ConditionCode::Z) }, + Opcode::JNZ | + Opcode::CMOVNZ | + Opcode::SETNZ => { Some(ConditionCode::NZ) }, + Opcode::JA | + Opcode::CMOVA | + Opcode::SETA => { Some(ConditionCode::A) }, + Opcode::JNA | + Opcode::CMOVNA | + Opcode::SETBE => { Some(ConditionCode::BE) }, + Opcode::JS | + Opcode::CMOVS | + Opcode::SETS => { Some(ConditionCode::S) }, + Opcode::JNS | + Opcode::CMOVNS | + Opcode::SETNS => { Some(ConditionCode::NS) }, + Opcode::JP | + Opcode::CMOVP | + Opcode::SETP => { Some(ConditionCode::P) }, + Opcode::JNP | + Opcode::CMOVNP | + Opcode::SETNP => { Some(ConditionCode::NP) }, + Opcode::JL | + Opcode::CMOVL | + Opcode::SETL => { Some(ConditionCode::L) }, + Opcode::JGE | + Opcode::CMOVGE | + Opcode::SETGE => { Some(ConditionCode::GE) }, + Opcode::JG | + Opcode::CMOVG | + Opcode::SETG => { Some(ConditionCode::G) }, + Opcode::JLE | + Opcode::CMOVLE | + Opcode::SETLE => { Some(ConditionCode::LE) }, + _ => None, + } + } +} + impl Instruction { + pub fn operand(&self, i: u8) -> Operand { + assert!(i < 4); + Operand::from_spec(self, self.operands[i as usize]) + } + + pub fn operand_count(&self) -> u8 { + let mut i = 0; + for op in self.operands.iter() { + if let OperandSpec::Nothing = op { + return i; + } else { + i += 1; + } + } + return i; + } + + pub fn operand_present(&self, i: u8) -> bool { + assert!(i < 4); + if let OperandSpec::Nothing = self.operands[i as usize] { + false + } else { + true + } + } + pub fn invalid() -> Instruction { Instruction { prefixes: Prefixes::new(0), @@ -667,6 +874,7 @@ impl Instruction { modrm_mmm: RegSpec::rax(), // doubles as sib_base sib_index: RegSpec::rax(), scale: 0, + length: 0, disp: 0, imm: 0, operand_count: 0, @@ -881,6 +1089,23 @@ pub enum OperandCode { Yb_Xb, Yv_AX, Yv_Xv, + G_E_q, + G_E_mm, + G_U_mm, + G_U_xmm, + G_M_q, + E_G_q, + Rv_Gmm_Ib, + G_mm_Ew_Ib, + Mq_Dq, + eAX, + ModRM_0x0f18, + ModRM_0x0f38, + ModRM_0x0f3a, + ModRM_0x0f71, + ModRM_0x0f72, + ModRM_0x0f73, + ModRM_0x0fc7, Nothing, Implied, Unsupported, @@ -1563,7 +1788,7 @@ fn read_opcode_f30f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, length: &mut u /* match bytes_iter.next() { Some(b) => { - instruction.length += 1; + *length += 1; match b { 0x10 => { instruction.opcode = Opcode::MOVSS; Some(OperandCode::G_E_xmm) }, 0x11 => { instruction.opcode = Opcode::MOVSS; Some(OperandCode::E_G_xmm) }, @@ -1615,15 +1840,15 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [ OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f13), OpcodeRecord(Interpretation::Instruction(Opcode::UNPCKLPS), OperandCode::G_E_xmm), OpcodeRecord(Interpretation::Instruction(Opcode::UNPCKHPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVHPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVHPS), OperandCode::E_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f18), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), // 0x20 OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Cq_0), @@ -1634,27 +1859,27 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [ OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPS), OperandCode::E_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTPI2PS), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTPS), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTTPS2PI), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTPS2PI), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::UCOMISS), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::COMISS), OperandCode::Nothing), // 0x30 OpcodeRecord(Interpretation::Instruction(Opcode::WRMSR), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::RDTSC), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::RDMSR), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::RDPMC), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SYSENTER), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SYSEXIT), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::GETSEC), OperandCode::eAX), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f38), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f3a), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), @@ -1680,58 +1905,58 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [ OpcodeRecord(Interpretation::Instruction(Opcode::CMOVG), OperandCode::Gv_Ev), // 0x50 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVMSKPS), OperandCode::G_U_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::SQRTPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::RSQRTPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::RCPPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::ANDPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::ANDNPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::ORPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::XORPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::ADDPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MULPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTPS2PD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTDQ2PS), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::SUBPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MINPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::DIVPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MAXPS), OperandCode::G_E_xmm), // 0x60 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLBW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLWD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLDQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSWB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PACKUSWB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHBW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHWD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHDQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSDW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::Unsupported), // 0x70 + OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f71), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f72), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f73), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::EMMS), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::VMREAD), OperandCode::E_G_q), + OpcodeRecord(Interpretation::Instruction(Opcode::VMWRITE), OperandCode::G_E_q), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::Unsupported), // 0x80 OpcodeRecord(Interpretation::Instruction(Opcode::JO), OperandCode::Jvds), @@ -1774,13 +1999,13 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [ OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::GS), OpcodeRecord(Interpretation::Instruction(Opcode::CPUID), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::BT), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Unsupported), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::GS), OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::GS), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::RSM), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::BTS), OperandCode::Ev_Gv), OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Unsupported), OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Unsupported), @@ -1790,14 +2015,14 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [ // 0xb0 OpcodeRecord(Interpretation::Instruction(Opcode::CMPXCHG), OperandCode::Eb_Gb), OpcodeRecord(Interpretation::Instruction(Opcode::CMPXCHG), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::LSS), OperandCode::G_M_q), + OpcodeRecord(Interpretation::Instruction(Opcode::BTR), OperandCode::E_G_q), + OpcodeRecord(Interpretation::Instruction(Opcode::LFS), OperandCode::G_M_q), + OpcodeRecord(Interpretation::Instruction(Opcode::LGS), OperandCode::G_M_q), OpcodeRecord(Interpretation::Instruction(Opcode::MOVZX_b), OperandCode::Gv_Eb), OpcodeRecord(Interpretation::Instruction(Opcode::MOVZX_w), OperandCode::Gv_Ew), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), // JMPE, ITANIUM + OpcodeRecord(Interpretation::Instruction(Opcode::UD2E), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fba), OpcodeRecord(Interpretation::Instruction(Opcode::BTC), OperandCode::Gv_Ev), OpcodeRecord(Interpretation::Instruction(Opcode::BSF), OperandCode::Gv_Ev), @@ -1808,72 +2033,73 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [ // 0xc0 OpcodeRecord(Interpretation::Instruction(Opcode::XADD), OperandCode::Eb_Gb), OpcodeRecord(Interpretation::Instruction(Opcode::XADD), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CMPPS), OperandCode::G_E_xmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTI), OperandCode::Mq_Dq), + OpcodeRecord(Interpretation::Instruction(Opcode::PINSRW), OperandCode::G_mm_Ew_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::Rv_Gmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::SHUFPS), OperandCode::G_E_xmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fc7), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R1), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R2), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R3), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R4), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R5), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R6), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R7), // 0xd0 OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRLW), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRLD), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRLQ), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDQ), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PMULLW), OperandCode::G_E_mm), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PMOVMSKB), OperandCode::G_U_mm), + + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBUSB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBUSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMINUB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PAND), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDUSB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDUSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMAXUB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PANDN), OperandCode::Unsupported), // 0xe0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PAVGB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRAW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRAD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PAVGW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMULHUW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMULHW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBSB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMINSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::POR), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDSB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMAXSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PXOR), OperandCode::Unsupported), // 0xf0 OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PSLLW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSLLD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSLLQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMULUDQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMADDWD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSADBW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::MASKMOVQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDD), OperandCode::Unsupported), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), ]; fn read_opcode_0f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, length: &mut u8) -> Option<OpcodeRecord> { @@ -1902,7 +2128,8 @@ struct OpcodeRecord(Interpretation, OperandCode); #[test] fn opcode_record_size() { - assert_eq!(std::mem::size_of::<OpcodeRecord>(), 2); + // there are more than 256 opcodes... + assert_eq!(std::mem::size_of::<OpcodeRecord>(), 4); } const OPCODES: [OpcodeRecord; 256] = [ @@ -2201,25 +2428,25 @@ const OPCODES: [OpcodeRecord; 256] = [ ]; #[allow(non_snake_case)] -fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8) -> Result<OperandSpec, ()> { +fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, length: &mut u8) -> Result<OperandSpec, ()> { let bank = width_to_gp_reg_bank(width, instr.prefixes.rex().present()); if modrm >= 0b11000000 { - read_modrm_reg(bytes_iter, instr, modrm, bank) + read_modrm_reg(instr, modrm, bank) } else { - read_M(bytes_iter, instr, modrm) + read_M(bytes_iter, instr, modrm, length) } } #[allow(non_snake_case)] -fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8) -> Result<OperandSpec, ()> { +fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, ()> { if modrm >= 0b11000000 { - read_modrm_reg(bytes_iter, instr, modrm, RegisterBank::X) + read_modrm_reg(instr, modrm, RegisterBank::X) } else { - read_M(bytes_iter, instr, modrm) + read_M(bytes_iter, instr, modrm, length) } } #[allow(non_snake_case)] -fn read_modrm_reg<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result<OperandSpec, ()> { +fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result<OperandSpec, ()> { instr.modrm_mmm = RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank); Ok(OperandSpec::RegMMM) } @@ -2315,7 +2542,7 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m } #[allow(non_snake_case)] -fn read_M<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8) -> Result<OperandSpec, ()> { +fn read_M<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, ()> { let modbits = (modrm >> 6); let addr_width = if instr.prefixes.address_size() { RegisterBank::D } else { RegisterBank::Q }; let mmm = modrm & 7; @@ -2461,10 +2688,11 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins unsafe { unreachable_unchecked(); } } instruction.prefixes = prefixes; - read_operands(bytes_iter, instruction, record.1)?; + read_operands(bytes_iter, instruction, record.1, &mut length)?; + instruction.length = length; Ok(()) } -pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode) -> Result<(), ()> { +pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, length: &mut u8) -> Result<(), ()> { let mut bytes_read = 0; if (operand_code as u8) & 0x40 == 0x40 { instruction.operands[0] = OperandSpec::RegRRR; @@ -2508,7 +2736,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.modrm_rrr = RegSpec::from_parts(reg, instruction.prefixes.rex().b(), bank); instruction.imm = - read_imm_ivq(&mut bytes_iter, opwidth)?; + read_imm_ivq(&mut bytes_iter, opwidth, length)?; bytes_read = opwidth; instruction.operands[1] = match opwidth { 1 => OperandSpec::ImmI8, @@ -2541,11 +2769,11 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut opwidth = 1; bank = RegisterBank::B; }; - modrm = read_modrm(&mut bytes_iter, instruction)?; + modrm = read_modrm(&mut bytes_iter, instruction, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), bank); - mem_oper = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + mem_oper = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; } let numeric_code = (operand_code as u8) & 0xbf; @@ -2560,7 +2788,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operand_count = 2; } else if operand_code == OperandCode::Ibs { instruction.imm = - read_imm_signed(&mut bytes_iter, 1)? as u64; + read_imm_signed(&mut bytes_iter, 1, length)? as u64; instruction.operands[0] = OperandSpec::ImmI8; instruction.operand_count = 1; } else { @@ -2635,6 +2863,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut // stupid RCT thing: let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 }; let imm = read_num(&mut bytes_iter, addr_width)?; + *length += addr_width; bytes_read = addr_width; instruction.modrm_rrr = RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present()); @@ -2661,6 +2890,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut // stupid RCT thing: let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 }; let imm = read_num(&mut bytes_iter, addr_width)?; + *length += addr_width; bytes_read = addr_width; instruction.disp = imm; instruction.operands[0] = if instruction.prefixes.address_size() { @@ -2677,7 +2907,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut op @ OperandCode::ModRM_0x81_Ev_Ivs => { instruction.operands[0] = mem_oper; let numwidth = if opwidth == 8 { 4 } else { opwidth }; - instruction.imm = read_imm_signed(&mut bytes_iter, numwidth)? as u64; + instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; bytes_read = numwidth; instruction.opcode = base_opcode_map((modrm >> 3) & 7); instruction.operands[1] = match opwidth { @@ -2699,7 +2929,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operands[0] = mem_oper; instruction.opcode = Opcode::MOV; let numwidth = if opwidth == 8 { 4 } else { opwidth }; - instruction.imm = read_imm_signed(&mut bytes_iter, numwidth)? as u64; + instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; bytes_read = numwidth; instruction.operands[1] = match opwidth { 1 => OperandSpec::ImmI8, @@ -2724,6 +2954,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut let num = match op { OperandCode::ModRM_0xc0_Eb_Ib | OperandCode::ModRM_0xc1_Ev_Ib => { + *length += 1; read_num(&mut bytes_iter, 1)? } _ => { @@ -2744,7 +2975,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut 0 | 1 => { instruction.opcode = Opcode::TEST; let numwidth = if opwidth == 8 { 4 } else { opwidth }; - instruction.imm = read_imm_signed(&mut bytes_iter, numwidth)? as u64; + instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; bytes_read = numwidth; instruction.operands[1] = match opwidth { 2 => OperandSpec::ImmI16, @@ -2808,31 +3039,31 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } OperandCode::Gv_Eb => { let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; bytes_read = 1; - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 1)?; + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 1, length)?; instruction.modrm_rrr = RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); instruction.operand_count = 2; }, OperandCode::Gv_Ew => { let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; bytes_read = 1; - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 2)?; + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; instruction.modrm_rrr = RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); instruction.operand_count = 2; }, OperandCode::Gdq_Ed => { let opwidth = 8; - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; bytes_read = 1; // println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4 /* opwidth */)?; + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4 /* opwidth */, length)?; instruction.modrm_rrr = RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); instruction.operand_count = 2; @@ -2848,22 +3079,22 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operand_count = 2; }, OperandCode::E_G_xmm => { - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; bytes_read = 1; // println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[0] = read_E_xmm(&mut bytes_iter, instruction, modrm)?; + instruction.operands[0] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; }, OperandCode::G_E_xmm => { - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; bytes_read = 1; // println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm)?; + instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); instruction.operands[0] = OperandSpec::RegRRR; @@ -2873,7 +3104,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.modrm_rrr = RegSpec::al(); instruction.imm = - read_imm_signed(&mut bytes_iter, 1)? as u64; + read_imm_signed(&mut bytes_iter, 1, length)? as u64; bytes_read = 1; instruction.operands[1] = OperandSpec::ImmI8; instruction.operand_count = 2; @@ -2884,7 +3115,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.modrm_rrr = RegSpec::gp_from_parts(0, false, opwidth, false); instruction.imm = - read_imm_signed(&mut bytes_iter, numwidth)? as u64; + read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; bytes_read = numwidth; instruction.operands[1] = match opwidth { 2 => OperandSpec::ImmI16, @@ -2910,13 +3141,14 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut OperandCode::ModRM_0x83_Ev_Ibs => { instruction.operands[0] = mem_oper; instruction.opcode = base_opcode_map((modrm >> 3) & 7); - instruction.imm = read_imm_signed(&mut bytes_iter, 1)? as u64; + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; bytes_read = 2; instruction.operands[1] = OperandSpec::ImmI8; instruction.operand_count = 2; }, OperandCode::Jvds => { let offset = read_num(&mut bytes_iter, 4)?; + *length += 4; instruction.imm = offset; instruction.operand_count = 1; instruction.operands[0] = OperandSpec::ImmI32; @@ -2925,14 +3157,14 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut instruction.operand_count = 0; } _ => { - unlikely_operands(bytes_iter, instruction, operand_code)?; + unlikely_operands(bytes_iter, instruction, operand_code, length)?; } }; } Ok(()) } -fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode) -> Result<(), ()> { +fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, length: &mut u8) -> Result<(), ()> { let mut bytes_read = 0; match operand_code { OperandCode::Gb_Eb_Ib => { @@ -2954,7 +3186,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } OperandCode::Ew_Sw => { let opwidth = 2; - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; bytes_read = 1; // check r @@ -2973,12 +3205,12 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut RegSpec { bank: RegisterBank::W, num: modrm & 7}; instruction.operands[0] = OperandSpec::RegMMM; } else { - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; } }, OperandCode::Sw_Ew => { let opwidth = 2; - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; // check r if ((modrm >> 3) & 7) > 5 { @@ -2996,7 +3228,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut RegSpec { bank: RegisterBank::W, num: modrm & 7}; instruction.operands[1] = OperandSpec::RegMMM; } else { - instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm)?; + instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm, length)?; } }, OperandCode::Gv_Ev_Iv => { @@ -3023,7 +3255,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } OperandCode::ModRM_0x0f00 => { instruction.operand_count = 1; - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; let r = (modrm >> 3) & 7; if r == 0 { instruction.opcode = Opcode::SLDT; @@ -3048,11 +3280,11 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } else { unreachable!("r <= 8"); } - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; } OperandCode::ModRM_0x0f01 => { let opwidth = imm_width_from_prefixes_64(SizeCode::vq, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; let r = (modrm >> 3) & 7; if r == 0 { let mod_bits = modrm >> 6; @@ -3062,7 +3294,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } else { instruction.opcode = Opcode::SGDT; instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; } } else if r == 1 { let mod_bits = modrm >> 6; @@ -3074,7 +3306,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } else { instruction.opcode = Opcode::SIDT; instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; } } else if r == 2 { let mod_bits = modrm >> 6; @@ -3086,7 +3318,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } else { instruction.opcode = Opcode::LGDT; instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; } } else if r == 3 { let mod_bits = modrm >> 6; @@ -3098,20 +3330,20 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } else { instruction.opcode = Opcode::LIDT; instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; } } else if r == 4 { // TODO: this permits storing only to word-size registers // spec suggets this might do something different for f.ex rdi? instruction.opcode = Opcode::SMSW; instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; } else if r == 5 { panic!("Unsupported instruction: 0x0f01 with modrm: __ 101 ___"); } else if r == 6 { instruction.opcode = Opcode::LMSW; instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; } else if r == 7 { let mod_bits = modrm >> 6; let m = modrm & 7; @@ -3129,14 +3361,14 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } else { instruction.opcode = Opcode::INVLPG; instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; } } else { unreachable!("r <= 8"); } } OperandCode::ModRM_0x0fae => { - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; let r = (modrm >> 3) & 7; let mod_bits = modrm >> 6; @@ -3174,12 +3406,12 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Opcode::CLFLUSH, Opcode::Invalid, ][r as usize]; - instruction.operands[0] = read_M(&mut bytes_iter, instruction, modrm)?; + instruction.operands[0] = read_M(&mut bytes_iter, instruction, modrm, length)?; } } OperandCode::ModRM_0x0fba => { let opwidth = imm_width_from_prefixes_64(SizeCode::vq, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; let r = (modrm >> 3) & 7; match r { 0 | 1 | 2 | 3 => { @@ -3203,9 +3435,9 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut } } - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth)?; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - instruction.imm = read_imm_signed(&mut bytes_iter, 1)? as u64; + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; bytes_read += 2; instruction.operands[1] = OperandSpec::ImmI8; instruction.operand_count = 2; @@ -3229,7 +3461,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut _ => unsafe { unreachable_unchecked() } }; - let modrm = read_modrm(&mut bytes_iter, instruction)?; + let modrm = read_modrm(&mut bytes_iter, instruction, length)?; let mut m = modrm & 7; let mut r = (modrm >> 3) & 7; if instruction.prefixes.rex().r() { @@ -3319,15 +3551,18 @@ fn read_num<T: Iterator<Item=u8>>(bytes: &mut T, width: u8) -> Result<u64, ()> { } #[inline] -fn read_imm_ivq<T: Iterator<Item=u8>>(bytes: &mut T, width: u8) -> Result<u64, ()> { +fn read_imm_ivq<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8) -> Result<u64, ()> { match width { 2 => { + *length += 2; Ok(read_num(bytes, 2)? as u16 as u64) }, 4 => { + *length += 4; Ok(read_num(bytes, 4)? as u32 as u64) }, 8 => { + *length += 8; Ok(read_num(bytes, 8)? as u64) }, _ => { @@ -3337,12 +3572,15 @@ fn read_imm_ivq<T: Iterator<Item=u8>>(bytes: &mut T, width: u8) -> Result<u64, ( } #[inline] -fn read_imm_signed<T: Iterator<Item=u8>>(bytes: &mut T, num_width: u8) -> Result<i64, ()> { +fn read_imm_signed<T: Iterator<Item=u8>>(bytes: &mut T, num_width: u8, length: &mut u8) -> Result<i64, ()> { if num_width == 1 { + *length += 1; Ok(read_num(bytes, 1)? as i8 as i64) } else if num_width == 2 { + *length += 2; Ok(read_num(bytes, 2)? as i16 as i64) } else { + *length += 4; // this is for 4 and 8, the only values for num_width may be 1, 2, 4, and 8. Ok(read_num(bytes, 4)? as i32 as i64) } @@ -3387,16 +3625,6 @@ fn imm_width_from_prefixes_64(interpretation: SizeCode, prefixes: Prefixes) -> u } #[inline] -fn read_modrm<T: Iterator<Item=u8>>(bytes_iter: &mut T, inst: &mut Instruction) -> Result<u8, ()> { - let modrm = match bytes_iter.next() { - Some(b) => b, - // TODO: ... - None => { unsafe { unreachable_unchecked(); } } - /* - None => { - return Err(()); - } - */ - }; - Ok(modrm) +fn read_modrm<T: Iterator<Item=u8>>(bytes_iter: &mut T, inst: &mut Instruction, length: &mut u8) -> Result<u8, ()> { + bytes_iter.next().map(|b| { *length += 1; b }).ok_or(()) } diff --git a/test/test.rs b/test/test.rs index f28f551..3182503 100644 --- a/test/test.rs +++ b/test/test.rs @@ -3,8 +3,8 @@ extern crate yaxpeax_x86; use std::fmt::Write; -use yaxpeax_arch::Decodable; -use yaxpeax_x86::{Instruction, decode_one}; +use yaxpeax_arch::Decoder; +use yaxpeax_x86::{Instruction, InstDecoder, decode_one}; fn decode(bytes: &[u8]) -> Option<Instruction> { let mut instr = Instruction::invalid(); @@ -19,7 +19,7 @@ fn test_display(data: &[u8], expected: &'static str) { for b in data { write!(hex, "{:02x}", b).unwrap(); } - match Instruction::decode(data.into_iter().map(|x| *x)) { + match InstDecoder::default().decode(data.into_iter().map(|x| *x)) { Some(instr) => { let text = format!("{}", instr); assert!( @@ -38,7 +38,37 @@ fn test_display(data: &[u8], expected: &'static str) { } #[test] +fn test_mmx() { + test_display(&[0x4f, 0x0f, 0x7e, 0xcf], "movd r15, mm1"); + test_display(&[0x4f, 0x0f, 0x7f, 0xcf], "movq mm7, mm1"); + test_display(&[0x0f, 0xc4, 0xc0, 0x14], "pinsrw mm0, eax, 0x14"); + test_display(&[0x4f, 0x0f, 0xc4, 0xc0, 0x14], "pinsrw mm0, r8d, 0x14"); + test_display(&[0x4f, 0x0f, 0xc4, 0x00, 0x14], "pinsrw mm0, word [r8], 0x14"); + test_display(&[0x4f, 0x0f, 0xd1, 0xcf], "psrlw mm1, mm7"); + test_display(&[0x4f, 0x0f, 0xd1, 0x00], "psrlw mm0, qword [r8]"); + test_display(&[0x4f, 0x0f, 0xd7, 0x00], "invalid"); + test_display(&[0x4f, 0x0f, 0xd7, 0xcf], "pmovmskb r9d, mm7"); +} + +#[test] +fn test_cvt() { + test_display(&[0x0f, 0x2c, 0xcf], "cvttps2pi mm1, xmm7"); + test_display(&[0x48, 0x0f, 0x2c, 0xcf], "cvttps2pi mm1, xmm7"); + test_display(&[0x4f, 0x0f, 0x2c, 0xcf], "cvttps2pi mm1, xmm15"); + test_display(&[0x4f, 0x0f, 0x2a, 0xcf], "cvtpi2ps xmm9, mm7"); + test_display(&[0x4f, 0x66, 0x0f, 0x2a, 0xcf], "cvtpi2pd xmm1, mm7"); + test_display(&[0x4f, 0xf3, 0x0f, 0x2a, 0xcf], "cvtsi2ss xmm1, edi"); + test_display(&[0x4f, 0xf2, 0x0f, 0x2a, 0xcf], "cvtsi2sd xmm1, edi"); + test_display(&[0x4f, 0xf2, 0x0f, 0x2a, 0x00], "cvtsi2sd xmm0, dword [rax]"); + test_display(&[0x4f, 0xf3, 0x0f, 0x2a, 0x00], "cvtsi2ss xmm0, dword [rax]"); + test_display(&[0x4f, 0x66, 0x0f, 0x2a, 0x00], "cvtpi2pd xmm0, qword [rax]"); +} + +#[test] fn test_system() { + test_display(&[0x66, 0x4f, 0x0f, 0xb2, 0x00], "lss r8, [r8]"); + test_display(&[0x67, 0x4f, 0x0f, 0xb2, 0x00], "lss r8, [r8d]"); + test_display(&[0x4f, 0x0f, 0xb2, 0x00], "lss r8, [r8]"); test_display(&[0x45, 0x0f, 0x22, 0xc8], "mov cr9, r8"); test_display(&[0x45, 0x0f, 0x20, 0xc8], "mov r8, cr9"); test_display(&[0x40, 0x0f, 0x22, 0xc8], "mov cr1, rax"); @@ -69,9 +99,30 @@ fn test_E_decode() { #[test] fn test_sse() { + test_display(&[0x4f, 0x0f, 0x28, 0x00], "movaps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x29, 0x00], "movaps xmmword [r8], xmm8"); + test_display(&[0x4f, 0x0f, 0x2b, 0x00], "movntps xmmword [r8], xmm8"); + test_display(&[0x4f, 0x0f, 0x2e, 0x00], "ucomiss xmm8, dword [r8]"); + test_display(&[0x4f, 0x0f, 0x2f, 0x00], "comiss xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x50, 0xc0], "movmskps r8d, xmm8"); test_display(&[0x0f, 0x28, 0xd0], "movaps xmm2, xmm0"); test_display(&[0x66, 0x0f, 0x28, 0xd0], "movapd xmm2, xmm0"); test_display(&[0x66, 0x0f, 0x28, 0x00], "movapd xmm0, [rax]"); + test_display(&[0x4f, 0x0f, 0x50, 0x00], "invalid"); + test_display(&[0x4f, 0x0f, 0x50, 0xc0], "movmskps r8d, xmm8"); + test_display(&[0x4f, 0x0f, 0x51, 0x00], "sqrtps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x52, 0x00], "rsqrtps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x53, 0x00], "rcpps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x54, 0x00], "andps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x55, 0x00], "andnps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x56, 0x00], "orps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x57, 0x00], "xorps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x58, 0x00], "addps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x59, 0x00], "mulps xmm8, xmmword [r8]"); + test_display(&[0x4f, 0x0f, 0x5a, 0x00], "cvtps2pd xmm8, qword [r8]"); + test_display(&[0x4f, 0x0f, 0x5b, 0x00], "cvtdq2ps xmm8, xmmword [r8]"); + test_display(&[0x66, 0x4f, 0x0f, 0x5b, 0x00], "cvtdq2ps xmm8, xmmword [r8]"); + test_display(&[0x67, 0x4f, 0x0f, 0x5b, 0x00], "cvtdq2ps xmm8, xmmword [r8d]"); test_display(&[0x4f, 0x66, 0x0f, 0x28, 0x00], "movapd xmm0, [rax]"); test_display(&[0x66, 0x4f, 0x0f, 0x28, 0x00], "movapd xmm8, [r8]"); test_display(&[0x66, 0x4f, 0x0f, 0x28, 0x00], "movapd xmm8, [r8]"); |