aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2019-12-13 14:39:47 -0800
committeriximeow <me@iximeow.net>2020-01-12 16:10:13 -0800
commit436c65e51f7e14201f902c57fb6a069860126477 (patch)
treeceed36b6a4414dc98b042975be2e27472c60a6d6 /src/lib.rs
parent4bb189250b99494b292fb24717ee90f3178cbde9 (diff)
vex
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs499
1 files changed, 461 insertions, 38 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 24f11f8..bfb01de 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,6 +6,7 @@ extern crate serde;
extern crate yaxpeax_arch;
extern crate termion;
+mod vex;
mod display;
use std::hint::unreachable_unchecked;
@@ -362,8 +363,8 @@ impl Operand {
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>(), 40);
+ // assert_eq!(std::mem::size_of::<Prefixes>(), 4);
+ // assert_eq!(std::mem::size_of::<Instruction>(), 40);
}
#[allow(non_camel_case_types)]
@@ -374,6 +375,7 @@ pub enum RegisterBank {
CR, DR, S, EIP, RIP, EFlags, RFlags, // Control reg, Debug reg, Selector, ...
X, Y, Z, // XMM, YMM, ZMM
ST, MM, // ST, MM regs (x87, mmx)
+ K, // AVX512 mask registers
}
#[allow(non_camel_case_types)]
#[cfg(not(feature="use-serde"))]
@@ -383,6 +385,7 @@ pub enum RegisterBank {
CR, DR, S, EIP, RIP, EFlags, RFlags, // Control reg, Debug reg, Selector, ...
X, Y, Z, // XMM, YMM, ZMM
ST, MM, // ST, MM regs (x87, mmx)
+ K, // AVX512 mask registers
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
@@ -390,6 +393,15 @@ pub enum Segment {
DS = 0, CS, ES, FS, GS, SS
}
+const BMI1: [Opcode; 6] = [
+ Opcode::ANDN,
+ Opcode::BEXTR,
+ Opcode::BLSI,
+ Opcode::BLSMSK,
+ Opcode::BLSR,
+ Opcode::TZCNT,
+];
+
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Opcode {
@@ -409,6 +421,7 @@ pub enum Opcode {
BTR,
BSF,
BSR,
+ TZCNT,
MOVSS,
ADDSS,
SUBSS,
@@ -617,6 +630,12 @@ pub enum Opcode {
RSQRTSS,
RCPSS,
+ ANDN,
+ BEXTR,
+ BLSI,
+ BLSMSK,
+ BLSR,
+
ADDPS,
ANDNPS,
ANDPS,
@@ -726,6 +745,280 @@ pub enum Opcode {
VMREAD,
VMWRITE,
XORPS,
+
+ VMOVDDUP,
+ VPSHUFLW,
+ VHADDPS,
+ VHSUBPS,
+ VADDSUBPS,
+ VCVTPD2DQ,
+ VLDDQU,
+
+ VADDPD,
+ VADDPS,
+ VADDSUBPD,
+ VAESDEC,
+ VAESDECLAST,
+ VAESENC,
+ VAESENCLAST,
+ VAESIMC,
+ VAESKEYGENASSIST,
+ VBLENDPD,
+ VBLENDPS,
+ VBLENDVPD,
+ VBLENDVPS,
+ VBROADCASTF128,
+ VBROADCASTI128,
+ VBROADCASTSD,
+ VBROADCASTSS,
+ VCMPPD,
+ VCMPPS,
+ VCVTDQ2PD,
+ VCVTDQ2PS,
+ VCVTPD2PS,
+ VCVTPH2PS,
+ VCVTPS2DQ,
+ VCVTPS2PD,
+ VCVTPS2PH,
+ VCVTTPD2DQ,
+ VCVTTPS2DQ,
+ VDIVPD,
+ VDIVPS,
+ VDPPD,
+ VDPPS,
+ VEXTRACTF128,
+ VEXTRACTI128,
+ VEXTRACTPS,
+ VFMADD132PD,
+ VFMADD132PS,
+ VFMADD213PD,
+ VFMADD213PS,
+ VFMADD231PD,
+ VFMADD231PS,
+ VFMADDSUB132PD,
+ VFMADDSUB132PS,
+ VFMADDSUB213PD,
+ VFMADDSUB213PS,
+ VFMADDSUB231PD,
+ VFMADDSUB231PS,
+ VFMSUB132PD,
+ VFMSUB132PS,
+ VFMSUB213PD,
+ VFMSUB213PS,
+ VFMSUB231PD,
+ VFMSUB231PS,
+ VFMSUBADD132PD,
+ VFMSUBADD132PS,
+ VFMSUBADD213PD,
+ VFMSUBADD213PS,
+ VFMSUBADD231PD,
+ VFMSUBADD231PS,
+ VFNMADD132PD,
+ VFNMADD132PS,
+ VFNMADD213PD,
+ VFNMADD213PS,
+ VFNMADD231PD,
+ VFNMADD231PS,
+ VFNMSUB132PD,
+ VFNMSUB132PS,
+ VFNMSUB213PD,
+ VFNMSUB213PS,
+ VFNMSUB231PD,
+ VFNMSUB231PS,
+ VGATHERDPD,
+ VGATHERDPS,
+ VGATHERQPD,
+ VGATHERQPS,
+ VHADDPD,
+ VHSUBPD,
+ VINSERTF128,
+ VINSERTI128,
+ VINSERTPS,
+ VMASKMOVDQU,
+ VMASKMOVPD,
+ VMASKMOVPS,
+ VMAXPD,
+ VMAXPS,
+ VMINPD,
+ VMINPS,
+ VMOVAPD,
+ VMOVAPS,
+ VMOVD,
+ VMOVDQA,
+ VMOVDQU,
+ VMOVHLPS,
+ VMOVHPD,
+ VMOVHPS,
+ VMOVLHPS,
+ VMOVLPD,
+ VMOVLPS,
+ VMOVMSKPD,
+ VMOVMSKPS,
+ VMOVNTDQ,
+ VMOVNTDQA,
+ VMOVNTPD,
+ VMOVNTPS,
+ VMOVQ,
+ VMOVSHDUP,
+ VMOVSLDUP,
+ VMOVUPD,
+ VMOVUPS,
+ VMPSADBW,
+ VMULPD,
+ VMULPS,
+ VPABSB,
+ VPABSD,
+ VPABSW,
+ VPACKSSDW,
+ VPACKSSWB,
+ VPACKUSWB,
+ VPADDB,
+ VPADDD,
+ VPADDQ,
+ VPADDSB,
+ VPADDSW,
+ VPADDUSB,
+ VPADDUSW,
+ VPADDW,
+ VPALIGNR,
+ VPAND,
+ VPANDN,
+ VPAVGB,
+ VPAVGW,
+ VPBLENDD,
+ VPBLENDVB,
+ VPBLENDW,
+ VPBROADCASTB,
+ VPBROADCASTD,
+ VPBROADCASTQ,
+ VPBROADCASTW,
+ VPCLMULQDQ,
+ VPCMPEQB,
+ VPCMPEQD,
+ VPCMPEQQ,
+ VPCMPEQW,
+ VPCMPGTB,
+ VPCMPGTD,
+ VPCMPGTQ,
+ VPCMPGTW,
+ VPCMPISTRI,
+ VPCMPISTRM,
+ VPERM2F128,
+ VPERM2I128,
+ VPERMD,
+ VPERMILPD,
+ VPERMILPS,
+ VPERMPD,
+ VPERMPS,
+ VPERMQ,
+ VPEXTRB,
+ VPEXTRD,
+ VPEXTRQ,
+ VPEXTRW,
+ VPGATHERDD,
+ VPGATHERDQ,
+ VPGATHERQD,
+ VPGATHERQQ,
+ VPHADDD,
+ VPHADDSW,
+ VPHADDW,
+ VPHMINPOSUW,
+ VPHSUBD,
+ VPHSUBSW,
+ VPHSUBW,
+ VPINSRB,
+ VPINSRD,
+ VPINSRQ,
+ VPINSRW,
+ VPMADDUBSW,
+ VPMADDWD,
+ VPMASKMOVD,
+ VPMASKMOVQ,
+ VPMAXSB,
+ VPMAXSD,
+ VPMAXSW,
+ VPMAXUD,
+ VPMINSD,
+ VPMINUD,
+ VPMOVMSKB,
+ VPMOVSXBD,
+ VPMOVSXBQ,
+ VPMOVSXBW,
+ VPMOVSXDQ,
+ VPMOVSXWD,
+ VPMOVSXWQ,
+ VPMOVZXBD,
+ VPMOVZXBQ,
+ VPMOVZXBW,
+ VPMOVZXDQ,
+ VPMOVZXWD,
+ VPMOVZXWQ,
+ VPMULDQ,
+ VPMULHRSW,
+ VPMULHUW,
+ VPMULHW,
+ VPMULLD,
+ VPMULLW,
+ VPMULUDQ,
+ VPOR,
+ VPSADBW,
+ VPSHUFB,
+ VPSHUFD,
+ VPSIGNB,
+ VPSIGND,
+ VPSIGNW,
+ VPSLLD,
+ VPSLLDQ,
+ VPSLLQ,
+ VPSLLVD,
+ VPSLLVQ,
+ VPSLLW,
+ VPSRAD,
+ VPSRAVD,
+ VPSRAW,
+ VPSRLD,
+ VPSRLDQ,
+ VPSRLQ,
+ VPSRLVD,
+ VPSRLVQ,
+ VPSRLW,
+ VPSUBB,
+ VPSUBD,
+ VPSUBQ,
+ VPSUBSB,
+ VPSUBSW,
+ VPSUBUSB,
+ VPSUBUSW,
+ VPSUBW,
+ VPTEST,
+ VPUNPCKHBW,
+ VPUNPCKHDQ,
+ VPUNPCKHQDQ,
+ VPUNPCKHWD,
+ VPUNPCKLBW,
+ VPUNPCKLDQ,
+ VPUNPCKLQDQ,
+ VPUNPCKLWD,
+ VPXOR,
+ VRCPPS,
+ VROUNDPD,
+ VROUNDPS,
+ VRSQRTPS,
+ VSHUFPD,
+ VSHUFPS,
+ VSQRTPD,
+ VSQRTPS,
+ VSUBPD,
+ VSUBPS,
+ VTESTPD,
+ VTESTPS,
+ VUNPCKHPD,
+ VUNPCKHPS,
+ VUNPCKLPD,
+ VUNPCKLPS,
+ VXORPD,
+ VXORPS,
+ VZEROUPPER,
}
#[derive(Debug)]
pub struct Instruction {
@@ -733,6 +1026,7 @@ pub struct Instruction {
modrm_rrr: RegSpec,
modrm_mmm: RegSpec, // doubles as sib_base
sib_index: RegSpec,
+ vex_reg: RegSpec,
scale: u8,
length: u8,
operand_count: u8,
@@ -807,7 +1101,63 @@ impl LengthedInstruction for Instruction {
}
}
+#[derive(PartialEq)]
pub struct InstDecoder {
+ // extensions tracked here:
+ // 0. SSE3
+ // 1. SSSE3
+ // 2. monitor (intel-only?)
+ // 3. vmx (some atom chips still lack it)
+ // 4. fma3 (intel haswell/broadwell+, amd piledriver+)
+ // 5. cmpxchg16b (some amd are missingt this one)
+ // 6. sse4.1
+ // 7. sse4.2
+ // 8. movbe
+ // 9. popcnt (independent of BMI)
+ // 10. aesni
+ // 11. xsave (xsave, xrestor, xsetbv, xgetbv)
+ // 12. rdrand (intel ivybridge+, amd ..??)
+ // 13. sgx (eadd, eblock, ecreate, edbgrd, edbgwr, einit, eldb, eldu, epa, eremove, etrace,
+ // ewb, eenter, eexit, egetkey, ereport, eresume)
+ // 14. bmi1 (intel haswell+, amd jaguar+)
+ // 15. avx2 (intel haswell+, amd excavator+)
+ // 16. bmi2 (intel ?, amd ?)
+ // 17. invpcid
+ // 18. mpx
+ // 19. avx512_f
+ // 20. avx512_dq
+ // 21. rdseed
+ // 22. adx
+ // 23. avx512_fma
+ // 24. pcommit
+ // 25. clflushopt
+ // 26. clwb
+ // 27. avx512_pf
+ // 28. avx512_er
+ // 29. avx512_cd
+ // 30. sha
+ // 31. avx512_bw
+ // 32. avx512_vl
+ // 33. prefetchwt1
+ // 34. avx512_vbmi
+ // 35. avx512_vbmi2
+ // 36. gfni (galois field instructions)
+ // 37. vaes
+ // 38. vpclmulqdq
+ // 39. avx_vnni
+ // 40. avx512_bitalg
+ // 41. avx512_vpopcntdq
+ // 42. avx512_4vnniw
+ // 43. avx512_4fmaps
+ // 44. cx8 // cmpxchg8 - is this actually optional in x86_64?
+ // 45. syscall // syscall/sysret - actually optional in x86_64?
+ // 46. rdtscp // actually optional in x86_64?
+ // 47. abm (lzcnt, popcnt)
+ // 48. sse4a
+ // 49. 3dnowprefetch // actually optional?
+ // 50. xop
+ // 51. skinit
+ // 52. tbm
flags: u64,
}
@@ -816,11 +1166,34 @@ impl InstDecoder {
///
/// Pedantic and only decodes what the spec says is well-defined, rejecting undefined sequences
/// and any instructions defined by extensions.
- fn minimal() -> Self {
+ pub fn minimal() -> Self {
InstDecoder {
flags: 0,
}
}
+
+ fn bmi1(&self) -> bool {
+ self.flags & (1 << 13) != 0
+ }
+
+ pub fn without_bmi1(mut self) -> Self {
+ self.flags &= (!(1 << 13));
+ self
+ }
+
+ fn revise_instruction(&self, inst: &mut Instruction) -> Result<(), ()> {
+ match inst.opcode {
+ Opcode::TZCNT => {
+ if !self.bmi1() {
+ // tzcnt is only supported if bmi1 is enabled. without bmi1, this decodes as
+ // bsf.
+ inst.opcode = Opcode::BSF;
+ }
+ }
+ _ => {}
+ }
+ Ok(())
+ }
}
impl Default for InstDecoder {
@@ -838,13 +1211,13 @@ impl Default for InstDecoder {
impl Decoder<Instruction> for InstDecoder {
fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Option<Instruction> {
let mut instr = Instruction::invalid();
- match decode_one(bytes, &mut instr) {
+ match decode_one(self, bytes, &mut instr) {
Some(_) => Some(instr),
None => None
}
}
fn decode_into<T: IntoIterator<Item=u8>>(&self, instr: &mut Instruction, bytes: T) -> Option<()> {
- decode_one(bytes, instr)
+ decode_one(self, bytes, instr)
}
}
@@ -938,6 +1311,7 @@ impl Instruction {
modrm_rrr: RegSpec::rax(),
modrm_mmm: RegSpec::rax(), // doubles as sib_base
sib_index: RegSpec::rax(),
+ vex_reg: RegSpec::rax(),
scale: 0,
length: 0,
disp: 0,
@@ -1002,16 +1376,26 @@ impl Instruction {
#[derive(Debug, Copy, Clone)]
pub struct Prefixes {
bits: u8,
- rep_prefix: RepPrefix,
rex: PrefixRex,
segment: Segment,
}
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum RepPrefix {
- None = 0,
- E = 1,
- NE = 2,
+#[derive(Debug, Copy, Clone)]
+pub struct PrefixVex {
+ bits: u8,
+}
+
+impl PrefixVex {
+ #[inline]
+ fn b(&self) -> bool { (self.bits & 0x01) == 0x01 }
+ #[inline]
+ fn x(&self) -> bool { (self.bits & 0x02) == 0x02 }
+ #[inline]
+ fn r(&self) -> bool { (self.bits & 0x04) == 0x04 }
+ #[inline]
+ fn w(&self) -> bool { (self.bits & 0x08) == 0x08 }
+ #[inline]
+ fn l(&self) -> bool { (self.bits & 0x10) == 0x10 }
}
#[derive(Debug, Copy, Clone)]
@@ -1024,7 +1408,6 @@ impl Prefixes {
fn new(bits: u8) -> Prefixes {
Prefixes {
bits: bits,
- rep_prefix: RepPrefix::None,
rex: PrefixRex { bits: 0 },
segment: Segment::DS,
}
@@ -1034,11 +1417,11 @@ impl Prefixes {
#[inline]
fn set_rep(&mut self) { self.bits = (self.bits & 0xcf) | 0x10 }
#[inline]
- fn repz(&self) -> bool { self.bits & 0x30 == 0x20 }
+ pub fn repz(&self) -> bool { self.bits & 0x30 == 0x20 }
#[inline]
fn set_repz(&mut self) { self.bits = (self.bits & 0xcf) | 0x20 }
#[inline]
- fn repnz(&self) -> bool { self.bits & 0x30 == 0x30 }
+ pub fn repnz(&self) -> bool { self.bits & 0x30 == 0x30 }
#[inline]
fn set_repnz(&mut self) { self.bits = (self.bits & 0xcf) | 0x30 }
#[inline]
@@ -1050,14 +1433,6 @@ impl Prefixes {
#[inline]
fn set_address_size(&mut self) { self.bits = self.bits | 0x2 }
#[inline]
- pub fn repne(&self) -> bool { self.rep_prefix == RepPrefix::NE }
- #[inline]
- fn set_repne(&mut self) { self.rep_prefix = RepPrefix::NE; }
- #[inline]
- pub fn repe(&self) -> bool { self.rep_prefix == RepPrefix::E }
- #[inline]
- fn set_repe(&mut self) { self.rep_prefix = RepPrefix::E; }
- #[inline]
pub fn set_lock(&mut self) { self.bits |= 0x4 }
#[inline]
pub fn lock(&self) -> bool { self.bits & 0x4 == 4 }
@@ -1088,14 +1463,37 @@ impl Prefixes {
#[inline]
fn rex(&self) -> &PrefixRex { &self.rex }
#[inline]
- fn rex_mut(&mut self) -> &mut PrefixRex { &mut self.rex }
+ fn vex(&self) -> PrefixVex { PrefixVex { bits: self.rex.bits } }
+
+ #[inline]
+ fn rex_from(&mut self, bits: u8) {
+ self.rex.bits = bits;
+ }
+
+ #[inline]
+ fn vex_from_c5(&mut self, bits: u8) {
+ // collect rex bits
+ let r = bits & 0x80;
+ let wrxb = (r >> 5) ^ 0x04;
+ let l = (bits & 0x04) << 2;
+ let synthetic_rex = wrxb | l | 0x80;
+ self.rex.from(synthetic_rex);
+ }
+
+ #[inline]
+ fn vex_from_c4(&mut self, high: u8, low: u8) {
+ let w = low & 0x80;
+ let rxb = (high >> 5) ^ 0x07;
+ let wrxb = rxb | w >> 4;
+ let l = (low & 0x04) << 2;
+ let synthetic_rex = wrxb | l | 0x80;
+ self.rex.from(synthetic_rex);
+ }
}
impl PrefixRex {
#[inline]
- fn present(&self) -> bool { (self.bits & 0x10) == 0x10 }
- #[inline]
- fn set_present(&mut self) { self.bits |= 0x10; }
+ fn present(&self) -> bool { (self.bits & 0xc0) == 0x40 }
#[inline]
fn b(&self) -> bool { (self.bits & 0x01) == 0x01 }
#[inline]
@@ -1106,8 +1504,7 @@ impl PrefixRex {
fn w(&self) -> bool { (self.bits & 0x08) == 0x08 }
#[inline]
fn from(&mut self, prefix: u8) {
- self.bits = prefix & 0x0f;
- self.set_present();
+ self.bits = prefix;
}
}
@@ -1138,6 +1535,10 @@ pub enum OperandCode {
AX_Xv,
DX_AX,
E_G_xmm,
+ E_G_ymm,
+ E_G_zmm,
+ G_E_ymm,
+ G_E_zmm,
Ev_Ivs,
Ew_Sw,
Fw,
@@ -2371,7 +2772,7 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [
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),
+ OpcodeRecord(Interpretation::Instruction(Opcode::TZCNT), OperandCode::Gv_Ev),
OpcodeRecord(Interpretation::Instruction(Opcode::BSR), OperandCode::Gv_Ev),
OpcodeRecord(Interpretation::Instruction(Opcode::MOVSX_b), OperandCode::Gv_Eb),
OpcodeRecord(Interpretation::Instruction(Opcode::MOVSX_w), OperandCode::Gv_Ew),
@@ -2675,8 +3076,8 @@ const OPCODES: [OpcodeRecord; 256] = [
OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc1_Ev_Ib),
OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Iw),
OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Nothing),
- OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
- OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),
+ OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing),
+ OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing),
OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc6_Eb_Ib),
OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc7_Ev_Iv),
OpcodeRecord(Interpretation::Instruction(Opcode::ENTER), OperandCode::Iw_Ib),
@@ -2767,7 +3168,7 @@ 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, length: &mut u8) -> Result<OperandSpec, ()> {
+pub(crate) 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(instr, modrm, bank)
@@ -2776,13 +3177,21 @@ fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, mod
}
}
#[allow(non_snake_case)]
-fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, ()> {
+pub(crate) 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(instr, modrm, RegisterBank::X)
} else {
read_M(bytes_iter, instr, modrm, length)
}
}
+#[allow(non_snake_case)]
+pub(crate) fn read_E_ymm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, ()> {
+ if modrm >= 0b11000000 {
+ read_modrm_reg(instr, modrm, RegisterBank::Y)
+ } else {
+ read_M(bytes_iter, instr, modrm, length)
+ }
+}
#[allow(non_snake_case)]
fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result<OperandSpec, ()> {
@@ -2942,7 +3351,7 @@ fn width_to_gp_reg_bank(width: u8, rex: bool) -> RegisterBank {
}
}
-pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction) -> Result<(), ()> {
+pub fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction) -> Result<(), ()> {
let mut length = 0u8;
let mut alternate_opcode_map: Option<OpcodeMap> = None;
// use std::intrinsics::unlikely;
@@ -2971,7 +3380,7 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins
length += 1;
let record = OPCODES[b as usize];
if (b & 0xf0) == 0x40 {
- prefixes.rex_mut().from(b);
+ prefixes.rex_from(b);
} else if b == 0x0f {
let record = match alternate_opcode_map {
Some(opcode_map) => {
@@ -3010,7 +3419,7 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins
// prefix, but since 660f21 is not valid, the opcode is interpreted
// as 0f21, where 66 is a prefix, which makes 41 not the last
// prefix before the opcode, and it's discarded.
- prefixes.rex_mut().from(0);
+ prefixes.rex_from(0);
escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map);
match b {
0x26 => {
@@ -3037,6 +3446,14 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins
0x67 => {
prefixes.set_address_size();
},
+ 0xc4 => {
+ instruction.prefixes = prefixes;
+ return vex::three_byte_vex(&mut bytes_iter, instruction, length);
+ }
+ 0xc5 => {
+ instruction.prefixes = prefixes;
+ return vex::two_byte_vex(&mut bytes_iter, instruction, length);
+ }
0xf0 => {
prefixes.set_lock();
},
@@ -3064,6 +3481,12 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins
instruction.prefixes = prefixes;
read_operands(bytes_iter, instruction, record.1, &mut length)?;
instruction.length = length;
+
+ if decoder != &InstDecoder::default() {
+ // we might have to fix up or reject this instruction under whatever cpu features we need to
+ // pretend to have.
+ decoder.revise_instruction(instruction)?;
+ }
Ok(())
}
pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, length: &mut u8) -> Result<(), ()> {
@@ -4223,7 +4646,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut
Ok(())
}
-pub fn decode_one<'b, T: IntoIterator<Item=u8>>(bytes: T, instr: &'b mut Instruction) -> Option<()> {
+pub fn decode_one<'b, T: IntoIterator<Item=u8>>(decoder: &InstDecoder, bytes: T, instr: &'b mut Instruction) -> Option<()> {
instr.operands = [
OperandSpec::Nothing,
OperandSpec::Nothing,
@@ -4231,7 +4654,7 @@ pub fn decode_one<'b, T: IntoIterator<Item=u8>>(bytes: T, instr: &'b mut Instruc
OperandSpec::Nothing,
];
let mut bytes_iter = bytes.into_iter();
- read_instr(bytes_iter, instr).ok()
+ read_instr(decoder, bytes_iter, instr).ok()
}
/*
match read_opcode(&mut bytes_iter, instr) {