aboutsummaryrefslogtreecommitdiff
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
parent4bb189250b99494b292fb24717ee90f3178cbde9 (diff)
vex
-rw-r--r--src/display.rs562
-rw-r--r--src/lib.rs499
-rw-r--r--src/vex.rs1906
-rw-r--r--test/test.rs128
4 files changed, 3049 insertions, 46 deletions
diff --git a/src/display.rs b/src/display.rs
index 156998a..8bd2689 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -82,6 +82,9 @@ impl fmt::Display for RegSpec {
RegisterBank::S => {
["cs", "ds", "es", "fs", "gs", "ss"][self.num as usize]
}
+ RegisterBank::K => {
+ ["k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"][self.num as usize]
+ }
};
write!(f, "{}", name)
}
@@ -229,6 +232,7 @@ impl fmt::Display for Opcode {
&Opcode::BTC => write!(f, "{}", "btc"),
&Opcode::BSF => write!(f, "{}", "bsf"),
&Opcode::BSR => write!(f, "{}", "bsr"),
+ &Opcode::TZCNT => write!(f, "{}", "tzcnt"),
&Opcode::MOVSS => write!(f, "{}", "movss"),
&Opcode::SQRTSS => write!(f, "{}", "sqrtss"),
&Opcode::ADDSS => write!(f, "{}", "addss"),
@@ -535,6 +539,284 @@ impl fmt::Display for Opcode {
&Opcode::CBD => write!(f, "{}", "cbd"),
&Opcode::CDQ => write!(f, "{}", "cdq"),
&Opcode::CQO => write!(f, "{}", "cqo"),
+ &Opcode::ANDN => write!(f, "{}", "andn"),
+ &Opcode::BEXTR => write!(f, "{}", "bextr"),
+ &Opcode::BLSI => write!(f, "{}", "blsi"),
+ &Opcode::BLSMSK => write!(f, "{}", "blsmsk"),
+ &Opcode::BLSR => write!(f, "{}", "blsr"),
+ &Opcode::VMOVUPS => write!(f, "{}", "vmovups"),
+ &Opcode::VADDPD => write!(f, "{}", "vaddpd"),
+ &Opcode::VADDPS => write!(f, "{}", "vaddps"),
+ &Opcode::VADDSUBPD => write!(f, "{}", "vaddsubpd"),
+ &Opcode::VAESDEC => write!(f, "{}", "vaesdec"),
+ &Opcode::VAESDECLAST => write!(f, "{}", "vaesdeclast"),
+ &Opcode::VAESENC => write!(f, "{}", "vaesenc"),
+ &Opcode::VAESENCLAST => write!(f, "{}", "vaesenclast"),
+ &Opcode::VAESIMC => write!(f, "{}", "vaesimc"),
+ &Opcode::VAESKEYGENASSIST => write!(f, "{}", "vaeskeygenassist"),
+ &Opcode::VBLENDPD => write!(f, "{}", "vblendpd"),
+ &Opcode::VBLENDPS => write!(f, "{}", "vblendps"),
+ &Opcode::VBLENDVPD => write!(f, "{}", "vblendvpd"),
+ &Opcode::VBLENDVPS => write!(f, "{}", "vblendvps"),
+ &Opcode::VBROADCASTF128 => write!(f, "{}", "vbroadcastf128"),
+ &Opcode::VBROADCASTI128 => write!(f, "{}", "vbroadcasti128"),
+ &Opcode::VBROADCASTSD => write!(f, "{}", "vbroadcastsd"),
+ &Opcode::VBROADCASTSS => write!(f, "{}", "vbroadcastss"),
+ &Opcode::VCMPPD => write!(f, "{}", "vcmppd"),
+ &Opcode::VCMPPS => write!(f, "{}", "vcmpps"),
+ &Opcode::VCVTDQ2PD => write!(f, "{}", "vcvtdq2pd"),
+ &Opcode::VCVTDQ2PS => write!(f, "{}", "vcvtdq2ps"),
+ &Opcode::VCVTPD2PS => write!(f, "{}", "vcvtpd2ps"),
+ &Opcode::VCVTPH2PS => write!(f, "{}", "vcvtph2ps"),
+ &Opcode::VCVTPS2DQ => write!(f, "{}", "vcvtps2dq"),
+ &Opcode::VCVTPS2PD => write!(f, "{}", "vcvtps2pd"),
+ &Opcode::VCVTPS2PH => write!(f, "{}", "vcvtps2ph"),
+ &Opcode::VCVTTPD2DQ => write!(f, "{}", "vcvttpd2dq"),
+ &Opcode::VCVTTPS2DQ => write!(f, "{}", "vcvttps2dq"),
+ &Opcode::VDIVPD => write!(f, "{}", "vdivpd"),
+ &Opcode::VDIVPS => write!(f, "{}", "vdivps"),
+ &Opcode::VDPPD => write!(f, "{}", "vdppd"),
+ &Opcode::VDPPS => write!(f, "{}", "vdpps"),
+ &Opcode::VEXTRACTF128 => write!(f, "{}", "vextractf128"),
+ &Opcode::VEXTRACTI128 => write!(f, "{}", "vextracti128"),
+ &Opcode::VEXTRACTPS => write!(f, "{}", "vextractps"),
+ &Opcode::VFMADD132PD => write!(f, "{}", "vfmadd132pd"),
+ &Opcode::VFMADD132PS => write!(f, "{}", "vfmadd132ps"),
+ &Opcode::VFMADD213PD => write!(f, "{}", "vfmadd213pd"),
+ &Opcode::VFMADD213PS => write!(f, "{}", "vfmadd213ps"),
+ &Opcode::VFMADD231PD => write!(f, "{}", "vfmadd231pd"),
+ &Opcode::VFMADD231PS => write!(f, "{}", "vfmadd231ps"),
+ &Opcode::VFMADDSUB132PD => write!(f, "{}", "vfmaddsub132pd"),
+ &Opcode::VFMADDSUB132PS => write!(f, "{}", "vfmaddsub132ps"),
+ &Opcode::VFMADDSUB213PD => write!(f, "{}", "vfmaddsub213pd"),
+ &Opcode::VFMADDSUB213PS => write!(f, "{}", "vfmaddsub213ps"),
+ &Opcode::VFMADDSUB231PD => write!(f, "{}", "vfmaddsub231pd"),
+ &Opcode::VFMADDSUB231PS => write!(f, "{}", "vfmaddsub231ps"),
+ &Opcode::VFMSUB132PD => write!(f, "{}", "vfmsub132pd"),
+ &Opcode::VFMSUB132PS => write!(f, "{}", "vfmsub132ps"),
+ &Opcode::VFMSUB213PD => write!(f, "{}", "vfmsub213pd"),
+ &Opcode::VFMSUB213PS => write!(f, "{}", "vfmsub213ps"),
+ &Opcode::VFMSUB231PD => write!(f, "{}", "vfmsub231pd"),
+ &Opcode::VFMSUB231PS => write!(f, "{}", "vfmsub231ps"),
+ &Opcode::VFMSUBADD132PD => write!(f, "{}", "vfmsubadd132pd"),
+ &Opcode::VFMSUBADD132PS => write!(f, "{}", "vfmsubadd132ps"),
+ &Opcode::VFMSUBADD213PD => write!(f, "{}", "vfmsubadd213pd"),
+ &Opcode::VFMSUBADD213PS => write!(f, "{}", "vfmsubadd213ps"),
+ &Opcode::VFMSUBADD231PD => write!(f, "{}", "vfmsubadd231pd"),
+ &Opcode::VFMSUBADD231PS => write!(f, "{}", "vfmsubadd231ps"),
+ &Opcode::VFNMADD132PD => write!(f, "{}", "vfnmadd132pd"),
+ &Opcode::VFNMADD132PS => write!(f, "{}", "vfnmadd132ps"),
+ &Opcode::VFNMADD213PD => write!(f, "{}", "vfnmadd213pd"),
+ &Opcode::VFNMADD213PS => write!(f, "{}", "vfnmadd213ps"),
+ &Opcode::VFNMADD231PD => write!(f, "{}", "vfnmadd231pd"),
+ &Opcode::VFNMADD231PS => write!(f, "{}", "vfnmadd231ps"),
+ &Opcode::VFNMSUB132PD => write!(f, "{}", "vfnmsub132pd"),
+ &Opcode::VFNMSUB132PS => write!(f, "{}", "vfnmsub132ps"),
+ &Opcode::VFNMSUB213PD => write!(f, "{}", "vfnmsub213pd"),
+ &Opcode::VFNMSUB213PS => write!(f, "{}", "vfnmsub213ps"),
+ &Opcode::VFNMSUB231PD => write!(f, "{}", "vfnmsub231pd"),
+ &Opcode::VFNMSUB231PS => write!(f, "{}", "vfnmsub231ps"),
+ &Opcode::VGATHERDPD => write!(f, "{}", "vgatherdpd"),
+ &Opcode::VGATHERDPS => write!(f, "{}", "vgatherdps"),
+ &Opcode::VGATHERQPD => write!(f, "{}", "vgatherqpd"),
+ &Opcode::VGATHERQPS => write!(f, "{}", "vgatherqps"),
+ &Opcode::VHADDPD => write!(f, "{}", "vhaddpd"),
+ &Opcode::VHSUBPD => write!(f, "{}", "vhsubpd"),
+ &Opcode::VINSERTF128 => write!(f, "{}", "vinsertf128"),
+ &Opcode::VINSERTI128 => write!(f, "{}", "vinserti128"),
+ &Opcode::VINSERTPS => write!(f, "{}", "vinsertps"),
+ &Opcode::VMASKMOVDQU => write!(f, "{}", "vmaskmovdqu"),
+ &Opcode::VMASKMOVPD => write!(f, "{}", "vmaskmovpd"),
+ &Opcode::VMASKMOVPS => write!(f, "{}", "vmaskmovps"),
+ &Opcode::VMAXPD => write!(f, "{}", "vmaxpd"),
+ &Opcode::VMAXPS => write!(f, "{}", "vmaxps"),
+ &Opcode::VMINPD => write!(f, "{}", "vminpd"),
+ &Opcode::VMINPS => write!(f, "{}", "vminps"),
+ &Opcode::VMOVAPD => write!(f, "{}", "vmovapd"),
+ &Opcode::VMOVAPS => write!(f, "{}", "vmovaps"),
+ &Opcode::VMOVD => write!(f, "{}", "vmovd"),
+ &Opcode::VMOVDQA => write!(f, "{}", "vmovdqa"),
+ &Opcode::VMOVDQU => write!(f, "{}", "vmovdqu"),
+ &Opcode::VMOVHLPS => write!(f, "{}", "vmovhlps"),
+ &Opcode::VMOVHPD => write!(f, "{}", "vmovhpd"),
+ &Opcode::VMOVHPS => write!(f, "{}", "vmovhps"),
+ &Opcode::VMOVLHPS => write!(f, "{}", "vmovlhps"),
+ &Opcode::VMOVLPD => write!(f, "{}", "vmovlpd"),
+ &Opcode::VMOVLPS => write!(f, "{}", "vmovlps"),
+ &Opcode::VMOVMSKPD => write!(f, "{}", "vmovmskpd"),
+ &Opcode::VMOVMSKPS => write!(f, "{}", "vmovmskps"),
+ &Opcode::VMOVNTDQ => write!(f, "{}", "vmovntdq"),
+ &Opcode::VMOVNTDQA => write!(f, "{}", "vmovntdqa"),
+ &Opcode::VMOVNTPD => write!(f, "{}", "vmovntpd"),
+ &Opcode::VMOVNTPS => write!(f, "{}", "vmovntps"),
+ &Opcode::VMOVQ => write!(f, "{}", "vmovq"),
+ &Opcode::VMOVSHDUP => write!(f, "{}", "vmovshdup"),
+ &Opcode::VMOVSLDUP => write!(f, "{}", "vmovsldup"),
+ &Opcode::VMOVUPD => write!(f, "{}", "vmovupd"),
+ &Opcode::VMOVUPS => write!(f, "{}", "vmovups"),
+ &Opcode::VMPSADBW => write!(f, "{}", "vmpsadbw"),
+ &Opcode::VMULPD => write!(f, "{}", "vmulpd"),
+ &Opcode::VMULPS => write!(f, "{}", "vmulps"),
+ &Opcode::VPABSB => write!(f, "{}", "vpabsb"),
+ &Opcode::VPABSD => write!(f, "{}", "vpabsd"),
+ &Opcode::VPABSW => write!(f, "{}", "vpabsw"),
+ &Opcode::VPACKSSDW => write!(f, "{}", "vpackssdw"),
+ &Opcode::VPACKSSWB => write!(f, "{}", "vpacksswb"),
+ &Opcode::VPACKUSWB => write!(f, "{}", "vpackuswb"),
+ &Opcode::VPADDB => write!(f, "{}", "vpaddb"),
+ &Opcode::VPADDD => write!(f, "{}", "vpaddd"),
+ &Opcode::VPADDQ => write!(f, "{}", "vpaddq"),
+ &Opcode::VPADDSB => write!(f, "{}", "vpaddsb"),
+ &Opcode::VPADDSW => write!(f, "{}", "vpaddsw"),
+ &Opcode::VPADDUSB => write!(f, "{}", "vpaddusb"),
+ &Opcode::VPADDUSW => write!(f, "{}", "vpaddusw"),
+ &Opcode::VPADDW => write!(f, "{}", "vpaddw"),
+ &Opcode::VPALIGNR => write!(f, "{}", "vpalignr"),
+ &Opcode::VPAND => write!(f, "{}", "vpand"),
+ &Opcode::VPANDN => write!(f, "{}", "vpandn"),
+ &Opcode::VPAVGB => write!(f, "{}", "vpavgb"),
+ &Opcode::VPAVGW => write!(f, "{}", "vpavgw"),
+ &Opcode::VPBLENDD => write!(f, "{}", "vpblendd"),
+ &Opcode::VPBLENDVB => write!(f, "{}", "vpblendvb"),
+ &Opcode::VPBLENDW => write!(f, "{}", "vpblendw"),
+ &Opcode::VPBROADCASTB => write!(f, "{}", "vpbroadcastb"),
+ &Opcode::VPBROADCASTD => write!(f, "{}", "vpbroadcastd"),
+ &Opcode::VPBROADCASTQ => write!(f, "{}", "vpbroadcastq"),
+ &Opcode::VPBROADCASTW => write!(f, "{}", "vpbroadcastw"),
+ &Opcode::VPCLMULQDQ => write!(f, "{}", "vpclmulqdq"),
+ &Opcode::VPCMPEQB => write!(f, "{}", "vpcmpeqb"),
+ &Opcode::VPCMPEQD => write!(f, "{}", "vpcmpeqd"),
+ &Opcode::VPCMPEQQ => write!(f, "{}", "vpcmpeqq"),
+ &Opcode::VPCMPEQW => write!(f, "{}", "vpcmpeqw"),
+ &Opcode::VPCMPGTB => write!(f, "{}", "vpcmpgtb"),
+ &Opcode::VPCMPGTD => write!(f, "{}", "vpcmpgtd"),
+ &Opcode::VPCMPGTQ => write!(f, "{}", "vpcmpgtq"),
+ &Opcode::VPCMPGTW => write!(f, "{}", "vpcmpgtw"),
+ &Opcode::VPCMPISTRI => write!(f, "{}", "vpcmpistri"),
+ &Opcode::VPCMPISTRM => write!(f, "{}", "vpcmpistrm"),
+ &Opcode::VPERM2F128 => write!(f, "{}", "vperm2f128"),
+ &Opcode::VPERM2I128 => write!(f, "{}", "vperm2i128"),
+ &Opcode::VPERMD => write!(f, "{}", "vpermd"),
+ &Opcode::VPERMILPD => write!(f, "{}", "vpermilpd"),
+ &Opcode::VPERMILPS => write!(f, "{}", "vpermilps"),
+ &Opcode::VPERMPD => write!(f, "{}", "vpermpd"),
+ &Opcode::VPERMPS => write!(f, "{}", "vpermps"),
+ &Opcode::VPERMQ => write!(f, "{}", "vpermq"),
+ &Opcode::VPEXTRB => write!(f, "{}", "vpextrb"),
+ &Opcode::VPEXTRD => write!(f, "{}", "vpextrd"),
+ &Opcode::VPEXTRQ => write!(f, "{}", "vpextrq"),
+ &Opcode::VPEXTRW => write!(f, "{}", "vpextrw"),
+ &Opcode::VPGATHERDD => write!(f, "{}", "vpgatherdd"),
+ &Opcode::VPGATHERDQ => write!(f, "{}", "vpgatherdq"),
+ &Opcode::VPGATHERQD => write!(f, "{}", "vpgatherqd"),
+ &Opcode::VPGATHERQQ => write!(f, "{}", "vpgatherqq"),
+ &Opcode::VPHADDD => write!(f, "{}", "vphaddd"),
+ &Opcode::VPHADDSW => write!(f, "{}", "vphaddsw"),
+ &Opcode::VPHADDW => write!(f, "{}", "vphaddw"),
+ &Opcode::VPHMINPOSUW => write!(f, "{}", "vphminposuw"),
+ &Opcode::VPHSUBD => write!(f, "{}", "vphsubd"),
+ &Opcode::VPHSUBSW => write!(f, "{}", "vphsubsw"),
+ &Opcode::VPHSUBW => write!(f, "{}", "vphsubw"),
+ &Opcode::VPINSRB => write!(f, "{}", "vpinsrb"),
+ &Opcode::VPINSRD => write!(f, "{}", "vpinsrd"),
+ &Opcode::VPINSRQ => write!(f, "{}", "vpinsrq"),
+ &Opcode::VPINSRW => write!(f, "{}", "vpinsrw"),
+ &Opcode::VPMADDUBSW => write!(f, "{}", "vpmaddubsw"),
+ &Opcode::VPMADDWD => write!(f, "{}", "vpmaddwd"),
+ &Opcode::VPMASKMOVD => write!(f, "{}", "vpmaskmovd"),
+ &Opcode::VPMASKMOVQ => write!(f, "{}", "vpmaskmovq"),
+ &Opcode::VPMAXSB => write!(f, "{}", "vpmaxsb"),
+ &Opcode::VPMAXSD => write!(f, "{}", "vpmaxsd"),
+ &Opcode::VPMAXSW => write!(f, "{}", "vpmaxsw"),
+ &Opcode::VPMAXUD => write!(f, "{}", "vpmaxud"),
+ &Opcode::VPMINSD => write!(f, "{}", "vpminsd"),
+ &Opcode::VPMINUD => write!(f, "{}", "vpminud"),
+ &Opcode::VPMOVMSKB => write!(f, "{}", "vpmovmskb"),
+ &Opcode::VPMOVSXBD => write!(f, "{}", "vpmovsxbd"),
+ &Opcode::VPMOVSXBQ => write!(f, "{}", "vpmovsxbq"),
+ &Opcode::VPMOVSXBW => write!(f, "{}", "vpmovsxbw"),
+ &Opcode::VPMOVSXDQ => write!(f, "{}", "vpmovsxdq"),
+ &Opcode::VPMOVSXWD => write!(f, "{}", "vpmovsxwd"),
+ &Opcode::VPMOVSXWQ => write!(f, "{}", "vpmovsxwq"),
+ &Opcode::VPMOVZXBD => write!(f, "{}", "vpmovzxbd"),
+ &Opcode::VPMOVZXBQ => write!(f, "{}", "vpmovzxbq"),
+ &Opcode::VPMOVZXBW => write!(f, "{}", "vpmovzxbw"),
+ &Opcode::VPMOVZXDQ => write!(f, "{}", "vpmovzxdq"),
+ &Opcode::VPMOVZXWD => write!(f, "{}", "vpmovzxwd"),
+ &Opcode::VPMOVZXWQ => write!(f, "{}", "vpmovzxwq"),
+ &Opcode::VPMULDQ => write!(f, "{}", "vpmuldq"),
+ &Opcode::VPMULHRSW => write!(f, "{}", "vpmulhrsw"),
+ &Opcode::VPMULHUW => write!(f, "{}", "vpmulhuw"),
+ &Opcode::VPMULHW => write!(f, "{}", "vpmulhw"),
+ &Opcode::VPMULLD => write!(f, "{}", "vpmulld"),
+ &Opcode::VPMULLW => write!(f, "{}", "vpmullw"),
+ &Opcode::VPMULUDQ => write!(f, "{}", "vpmuludq"),
+ &Opcode::VPOR => write!(f, "{}", "vpor"),
+ &Opcode::VPSADBW => write!(f, "{}", "vpsadbw"),
+ &Opcode::VPSHUFB => write!(f, "{}", "vpshufb"),
+ &Opcode::VPSHUFD => write!(f, "{}", "vpshufd"),
+ &Opcode::VPSIGNB => write!(f, "{}", "vpsignb"),
+ &Opcode::VPSIGND => write!(f, "{}", "vpsignd"),
+ &Opcode::VPSIGNW => write!(f, "{}", "vpsignw"),
+ &Opcode::VPSLLD => write!(f, "{}", "vpslld"),
+ &Opcode::VPSLLDQ => write!(f, "{}", "vpslldq"),
+ &Opcode::VPSLLQ => write!(f, "{}", "vpsllq"),
+ &Opcode::VPSLLVD => write!(f, "{}", "vpsllvd"),
+ &Opcode::VPSLLVQ => write!(f, "{}", "vpsllvq"),
+ &Opcode::VPSLLW => write!(f, "{}", "vpsllw"),
+ &Opcode::VPSRAD => write!(f, "{}", "vpsrad"),
+ &Opcode::VPSRAVD => write!(f, "{}", "vpsravd"),
+ &Opcode::VPSRAW => write!(f, "{}", "vpsraw"),
+ &Opcode::VPSRLD => write!(f, "{}", "vpsrld"),
+ &Opcode::VPSRLDQ => write!(f, "{}", "vpsrldq"),
+ &Opcode::VPSRLQ => write!(f, "{}", "vpsrlq"),
+ &Opcode::VPSRLVD => write!(f, "{}", "vpsrlvd"),
+ &Opcode::VPSRLVQ => write!(f, "{}", "vpsrlvq"),
+ &Opcode::VPSRLW => write!(f, "{}", "vpsrlw"),
+ &Opcode::VPSUBB => write!(f, "{}", "vpsubb"),
+ &Opcode::VPSUBD => write!(f, "{}", "vpsubd"),
+ &Opcode::VPSUBQ => write!(f, "{}", "vpsubq"),
+ &Opcode::VPSUBSB => write!(f, "{}", "vpsubsb"),
+ &Opcode::VPSUBSW => write!(f, "{}", "vpsubsw"),
+ &Opcode::VPSUBUSB => write!(f, "{}", "vpsubusb"),
+ &Opcode::VPSUBUSW => write!(f, "{}", "vpsubusw"),
+ &Opcode::VPSUBW => write!(f, "{}", "vpsubw"),
+ &Opcode::VPTEST => write!(f, "{}", "vptest"),
+ &Opcode::VPUNPCKHBW => write!(f, "{}", "vpunpckhbw"),
+ &Opcode::VPUNPCKHDQ => write!(f, "{}", "vpunpckhdq"),
+ &Opcode::VPUNPCKHQDQ => write!(f, "{}", "vpunpckhqdq"),
+ &Opcode::VPUNPCKHWD => write!(f, "{}", "vpunpckhwd"),
+ &Opcode::VPUNPCKLBW => write!(f, "{}", "vpunpcklbw"),
+ &Opcode::VPUNPCKLDQ => write!(f, "{}", "vpunpckldq"),
+ &Opcode::VPUNPCKLQDQ => write!(f, "{}", "vpunpcklqdq"),
+ &Opcode::VPUNPCKLWD => write!(f, "{}", "vpunpcklwd"),
+ &Opcode::VPXOR => write!(f, "{}", "vpxor"),
+ &Opcode::VRCPPS => write!(f, "{}", "vrcpps"),
+ &Opcode::VROUNDPD => write!(f, "{}", "vroundpd"),
+ &Opcode::VROUNDPS => write!(f, "{}", "vroundps"),
+ &Opcode::VRSQRTPS => write!(f, "{}", "vrsqrtps"),
+ &Opcode::VSHUFPD => write!(f, "{}", "vshufpd"),
+ &Opcode::VSHUFPS => write!(f, "{}", "vshufps"),
+ &Opcode::VSQRTPD => write!(f, "{}", "vsqrtpd"),
+ &Opcode::VSQRTPS => write!(f, "{}", "vsqrtps"),
+ &Opcode::VSUBPD => write!(f, "{}", "vsubpd"),
+ &Opcode::VSUBPS => write!(f, "{}", "vsubps"),
+ &Opcode::VTESTPD => write!(f, "{}", "vtestpd"),
+ &Opcode::VTESTPS => write!(f, "{}", "vtestps"),
+ &Opcode::VUNPCKHPD => write!(f, "{}", "vunpckhpd"),
+ &Opcode::VUNPCKHPS => write!(f, "{}", "vunpckhps"),
+ &Opcode::VUNPCKLPD => write!(f, "{}", "vunpcklpd"),
+ &Opcode::VUNPCKLPS => write!(f, "{}", "vunpcklps"),
+ &Opcode::VXORPD => write!(f, "{}", "vxorpd"),
+ &Opcode::VXORPS => write!(f, "{}", "vxorps"),
+ &Opcode::VZEROUPPER => write!(f, "{}", "vzeroupper"),
+ &Opcode::VMOVDDUP => write!(f, "{}", "vmovddup"),
+ &Opcode::VPSHUFLW => write!(f, "{}", "vpshuflw"),
+ &Opcode::VHADDPS => write!(f, "{}", "vhaddps"),
+ &Opcode::VHSUBPS => write!(f, "{}", "vhsubps"),
+ &Opcode::VADDSUBPS => write!(f, "{}", "vaddsubps"),
+ &Opcode::VCVTPD2DQ => write!(f, "{}", "vcvtpd2dq"),
+ &Opcode::VLDDQU => write!(f, "{}", "vlddqu"),
&Opcode::Invalid => write!(f, "{}", "invalid"),
}
}
@@ -543,6 +825,126 @@ impl fmt::Display for Opcode {
impl <T: std::fmt::Write> Colorize<T> for Opcode {
fn colorize(&self, colors: Option<&ColorSettings>, out: &mut T) -> std::fmt::Result {
match self {
+ Opcode::VHADDPS |
+ Opcode::VHSUBPS |
+ Opcode::VADDSUBPS |
+ Opcode::VADDPD |
+ Opcode::VADDPS |
+ Opcode::VADDSUBPD |
+ Opcode::VFMADD132PD |
+ Opcode::VFMADD132PS |
+ Opcode::VFMADD213PD |
+ Opcode::VFMADD213PS |
+ Opcode::VFMADD231PD |
+ Opcode::VFMADD231PS |
+ Opcode::VFMADDSUB132PD |
+ Opcode::VFMADDSUB132PS |
+ Opcode::VFMADDSUB213PD |
+ Opcode::VFMADDSUB213PS |
+ Opcode::VFMADDSUB231PD |
+ Opcode::VFMADDSUB231PS |
+ Opcode::VFMSUB132PD |
+ Opcode::VFMSUB132PS |
+ Opcode::VFMSUB213PD |
+ Opcode::VFMSUB213PS |
+ Opcode::VFMSUB231PD |
+ Opcode::VFMSUB231PS |
+ Opcode::VFMSUBADD132PD |
+ Opcode::VFMSUBADD132PS |
+ Opcode::VFMSUBADD213PD |
+ Opcode::VFMSUBADD213PS |
+ Opcode::VFMSUBADD231PD |
+ Opcode::VFMSUBADD231PS |
+ Opcode::VFNMADD132PD |
+ Opcode::VFNMADD132PS |
+ Opcode::VFNMADD213PD |
+ Opcode::VFNMADD213PS |
+ Opcode::VFNMADD231PD |
+ Opcode::VFNMADD231PS |
+ Opcode::VFNMSUB132PD |
+ Opcode::VFNMSUB132PS |
+ Opcode::VFNMSUB213PD |
+ Opcode::VFNMSUB213PS |
+ Opcode::VFNMSUB231PD |
+ Opcode::VFNMSUB231PS |
+ Opcode::VDIVPD |
+ Opcode::VDIVPS |
+ Opcode::VHADDPD |
+ Opcode::VHSUBPD |
+ Opcode::VMULPD |
+ Opcode::VMULPS |
+ Opcode::VPABSB |
+ Opcode::VPABSD |
+ Opcode::VPABSW |
+ Opcode::VPSIGNB |
+ Opcode::VPSIGND |
+ Opcode::VPSIGNW |
+ Opcode::VPADDB |
+ Opcode::VPADDD |
+ Opcode::VPADDQ |
+ Opcode::VPADDSB |
+ Opcode::VPADDSW |
+ Opcode::VPADDUSB |
+ Opcode::VPADDUSW |
+ Opcode::VPADDW |
+ Opcode::VPAVGB |
+ Opcode::VPAVGW |
+ Opcode::VPMULDQ |
+ Opcode::VPMULHRSW |
+ Opcode::VPMULHUW |
+ Opcode::VPMULHW |
+ Opcode::VPMULLD |
+ Opcode::VPMULLW |
+ Opcode::VPMULUDQ |
+ Opcode::VPSUBB |
+ Opcode::VPSUBD |
+ Opcode::VPSUBQ |
+ Opcode::VPSUBSB |
+ Opcode::VPSUBSW |
+ Opcode::VPSUBUSB |
+ Opcode::VPSUBUSW |
+ Opcode::VPSUBW |
+ Opcode::VROUNDPD |
+ Opcode::VROUNDPS |
+ Opcode::VRSQRTPS |
+ Opcode::VSQRTPD |
+ Opcode::VSQRTPS |
+ Opcode::VSUBPD |
+ Opcode::VSUBPS |
+ Opcode::VPSADBW |
+ Opcode::VMPSADBW |
+ Opcode::VPHADDD |
+ Opcode::VPHADDSW |
+ Opcode::VPHADDW |
+ Opcode::VPHSUBD |
+ Opcode::VPHSUBSW |
+ Opcode::VPHSUBW |
+ Opcode::VPMADDUBSW |
+ Opcode::VPMADDWD |
+ Opcode::VDPPD |
+ Opcode::VDPPS |
+ Opcode::VRCPPS |
+ Opcode::VPAND |
+ Opcode::VPANDN |
+ Opcode::VPOR |
+ Opcode::VPXOR |
+ Opcode::VXORPD |
+ Opcode::VXORPS |
+ Opcode::VPSLLD |
+ Opcode::VPSLLDQ |
+ Opcode::VPSLLQ |
+ Opcode::VPSLLVD |
+ Opcode::VPSLLVQ |
+ Opcode::VPSLLW |
+ Opcode::VPSRAD |
+ Opcode::VPSRAVD |
+ Opcode::VPSRAW |
+ Opcode::VPSRLD |
+ Opcode::VPSRLDQ |
+ Opcode::VPSRLQ |
+ Opcode::VPSRLVD |
+ Opcode::VPSRLVQ |
+ Opcode::VPSRLW |
Opcode::RCPSS |
Opcode::RSQRTSS |
Opcode::SQRTSD |
@@ -590,6 +992,12 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {
Opcode::BTC |
Opcode::BSF |
Opcode::BSR |
+ Opcode::TZCNT |
+ Opcode::ANDN |
+ Opcode::BEXTR |
+ Opcode::BLSI |
+ Opcode::BLSMSK |
+ Opcode::BLSR |
Opcode::ADDPS |
Opcode::ANDNPS |
Opcode::ANDPS |
@@ -685,6 +1093,127 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {
Opcode::JG => { write!(out, "{}", colors.control_flow_op(self)) }
/* Data transfer */
+ Opcode::VCVTDQ2PD |
+ Opcode::VCVTDQ2PS |
+ Opcode::VCVTPD2DQ |
+ Opcode::VCVTPD2PS |
+ Opcode::VCVTPH2PS |
+ Opcode::VCVTPS2DQ |
+ Opcode::VCVTPS2PD |
+ Opcode::VCVTPS2PH |
+ Opcode::VCVTTPD2DQ |
+ Opcode::VCVTTPS2DQ |
+ Opcode::VMOVDDUP |
+ Opcode::VPSHUFLW |
+ Opcode::VBLENDPD |
+ Opcode::VBLENDPS |
+ Opcode::VBLENDVPD |
+ Opcode::VBLENDVPS |
+ Opcode::VBROADCASTF128 |
+ Opcode::VBROADCASTI128 |
+ Opcode::VBROADCASTSD |
+ Opcode::VBROADCASTSS |
+ Opcode::VEXTRACTF128 |
+ Opcode::VEXTRACTI128 |
+ Opcode::VEXTRACTPS |
+ Opcode::VGATHERDPD |
+ Opcode::VGATHERDPS |
+ Opcode::VGATHERQPD |
+ Opcode::VGATHERQPS |
+ Opcode::VINSERTF128 |
+ Opcode::VINSERTI128 |
+ Opcode::VINSERTPS |
+ Opcode::VMASKMOVDQU |
+ Opcode::VMASKMOVPD |
+ Opcode::VMASKMOVPS |
+ Opcode::VMOVAPD |
+ Opcode::VMOVAPS |
+ Opcode::VMOVD |
+ Opcode::VMOVDQA |
+ Opcode::VMOVDQU |
+ Opcode::VMOVHLPS |
+ Opcode::VMOVHPD |
+ Opcode::VMOVHPS |
+ Opcode::VMOVLHPS |
+ Opcode::VMOVLPD |
+ Opcode::VMOVLPS |
+ Opcode::VMOVMSKPD |
+ Opcode::VMOVMSKPS |
+ Opcode::VMOVNTDQ |
+ Opcode::VMOVNTDQA |
+ Opcode::VMOVNTPD |
+ Opcode::VMOVNTPS |
+ Opcode::VMOVQ |
+ Opcode::VMOVSHDUP |
+ Opcode::VMOVSLDUP |
+ Opcode::VMOVUPD |
+ Opcode::VMOVUPS |
+ Opcode::VPBLENDD |
+ Opcode::VPBLENDVB |
+ Opcode::VPBLENDW |
+ Opcode::VPBROADCASTB |
+ Opcode::VPBROADCASTD |
+ Opcode::VPBROADCASTQ |
+ Opcode::VPBROADCASTW |
+ Opcode::VPGATHERDD |
+ Opcode::VPGATHERDQ |
+ Opcode::VPGATHERQD |
+ Opcode::VPGATHERQQ |
+ Opcode::VPCLMULQDQ |
+ Opcode::VPMOVMSKB |
+ Opcode::VPMOVSXBD |
+ Opcode::VPMOVSXBQ |
+ Opcode::VPMOVSXBW |
+ Opcode::VPMOVSXDQ |
+ Opcode::VPMOVSXWD |
+ Opcode::VPMOVSXWQ |
+ Opcode::VPMOVZXBD |
+ Opcode::VPMOVZXBQ |
+ Opcode::VPMOVZXBW |
+ Opcode::VPMOVZXDQ |
+ Opcode::VPMOVZXWD |
+ Opcode::VPMOVZXWQ |
+ Opcode::VUNPCKHPD |
+ Opcode::VUNPCKHPS |
+ Opcode::VUNPCKLPD |
+ Opcode::VUNPCKLPS |
+ Opcode::VPUNPCKHBW |
+ Opcode::VPUNPCKHDQ |
+ Opcode::VPUNPCKHQDQ |
+ Opcode::VPUNPCKHWD |
+ Opcode::VPUNPCKLBW |
+ Opcode::VPUNPCKLDQ |
+ Opcode::VPUNPCKLQDQ |
+ Opcode::VPUNPCKLWD |
+ Opcode::VSHUFPD |
+ Opcode::VSHUFPS |
+ Opcode::VPACKSSDW |
+ Opcode::VPACKSSWB |
+ Opcode::VPACKUSWB |
+ Opcode::VPALIGNR |
+ Opcode::VPERM2F128 |
+ Opcode::VPERM2I128 |
+ Opcode::VPERMD |
+ Opcode::VPERMILPD |
+ Opcode::VPERMILPS |
+ Opcode::VPERMPD |
+ Opcode::VPERMPS |
+ Opcode::VPERMQ |
+ Opcode::VPEXTRB |
+ Opcode::VPEXTRD |
+ Opcode::VPEXTRQ |
+ Opcode::VPEXTRW |
+ Opcode::VPINSRB |
+ Opcode::VPINSRD |
+ Opcode::VPINSRQ |
+ Opcode::VPINSRW |
+ Opcode::VPMASKMOVD |
+ Opcode::VPMASKMOVQ |
+ Opcode::VPSHUFB |
+ Opcode::VPSHUFD |
+ Opcode::VPHMINPOSUW |
+ Opcode::VZEROUPPER |
+ Opcode::VLDDQU |
Opcode::BSWAP |
Opcode::CVTDQ2PD |
Opcode::CVTDQ2PS |
@@ -754,6 +1283,7 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {
Opcode::MOVQ2DQ |
Opcode::MOVSHDUP |
Opcode::MOVUPS |
+ Opcode::VMOVUPS |
Opcode::PEXTRW |
Opcode::PINSRW |
Opcode::MOV |
@@ -804,6 +1334,31 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {
Opcode::SETLE |
Opcode::SETG => { write!(out, "{}", colors.data_op(self)) }
+ Opcode::VCMPPD |
+ Opcode::VCMPPS |
+ Opcode::VMAXPD |
+ Opcode::VMAXPS |
+ Opcode::VMINPD |
+ Opcode::VMINPS |
+ Opcode::VPCMPEQB |
+ Opcode::VPCMPEQD |
+ Opcode::VPCMPEQQ |
+ Opcode::VPCMPEQW |
+ Opcode::VPCMPGTB |
+ Opcode::VPCMPGTD |
+ Opcode::VPCMPGTQ |
+ Opcode::VPCMPGTW |
+ Opcode::VPCMPISTRI |
+ Opcode::VPCMPISTRM |
+ Opcode::VPMAXSB |
+ Opcode::VPMAXSD |
+ Opcode::VPMAXSW |
+ Opcode::VPMAXUD |
+ Opcode::VPMINSD |
+ Opcode::VPMINUD |
+ Opcode::VPTEST |
+ Opcode::VTESTPD |
+ Opcode::VTESTPS |
Opcode::PCMPEQB |
Opcode::PCMPEQD |
Opcode::PCMPEQW |
@@ -880,6 +1435,13 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {
Opcode::VMWRITE |
Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) }
+ Opcode::VAESDEC |
+ Opcode::VAESDECLAST |
+ Opcode::VAESENC |
+ Opcode::VAESENCLAST |
+ Opcode::VAESIMC |
+ Opcode::VAESKEYGENASSIST => { write!(out, "{}", colors.misc_op(self)) }
+
Opcode::UD2 |
Opcode::Invalid => { write!(out, "{}", colors.invalid_op(self)) }
}
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) {
diff --git a/src/vex.rs b/src/vex.rs
new file mode 100644
index 0000000..98ff452
--- /dev/null
+++ b/src/vex.rs
@@ -0,0 +1,1906 @@
+use OperandSpec;
+use RegSpec;
+use RegisterBank;
+use Instruction;
+use Opcode;
+use read_modrm;
+use read_E;
+use read_E_xmm;
+use read_E_ymm;
+
+#[derive(Debug)]
+enum VEXOpcodeMap {
+ Map0F,
+ Map0F38,
+ Map0F3A,
+}
+
+#[derive(Debug)]
+enum VEXOpcodePrefix {
+ None,
+ Prefix66,
+ PrefixF3,
+ PrefixF2,
+}
+
+enum VEXOperandCode {
+ Nothing,
+ E_G_xmm,
+ U_G_xmm,
+ M_G_xmm,
+ G_M_xmm,
+ G_U_xmm,
+ E_G_xmm_imm8,
+ U_G_xmm_imm8,
+ E_G_ymm,
+ U_G_ymm,
+ M_G_ymm,
+ G_M_ymm,
+ G_U_ymm,
+ E_V_G_ymm,
+ E_xmm_G_ymm_imm8,
+ Ev_G_xmm_imm8,
+ G_E_xmm,
+ G_E_xmm_imm8,
+ G_E_ymm,
+ G_E_ymm_imm8,
+ G_xmm_E_xmm,
+ G_xmm_E_ymm,
+ G_ymm_E_xmm,
+ G_ymm_E_ymm,
+ V_G_ymm_E_xmm,
+ M_V_G_xmm,
+ M_V_G_ymm,
+ V15_G_E_xmm,
+ V15_G_E_ymm,
+ V15_G_M_xmm,
+ V15_G_M_ymm,
+ V_G_E_xmm,
+ V_G_E_xmm_imm8,
+ V_G_E_xmm_xmm4,
+ V_G_E_ymm,
+ V_G_E_ymm_imm8,
+ V_G_E_ymm_ymm4,
+ V_G_M_xmm,
+ V_G_M_ymm,
+ V_xmm_G_ymm_E_ymm_imm8,
+ V_ymm_G_ymm_E_xmm_imm8,
+ V_G_xmm_Ew_imm8,
+ Eq_G_xmm,
+ Ed_G_xmm,
+ G_xmm_Ed,
+ G_xmm_Eq,
+}
+
+#[inline(never)]
+pub(crate) fn three_byte_vex<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Instruction, mut length: u8) -> Result<(), ()> {
+ let vex_byte_one = bytes.next().ok_or(())?;
+ let vex_byte_two = bytes.next().ok_or(())?;
+ let p = vex_byte_two & 0x03;
+ let p = match p {
+ 0x00 => VEXOpcodePrefix::None,
+ 0x01 => VEXOpcodePrefix::Prefix66,
+ 0x02 => VEXOpcodePrefix::PrefixF3,
+ 0x03 => VEXOpcodePrefix::PrefixF2,
+ _ => { unreachable!("p is two bits"); }
+ };
+ instruction.prefixes.vex_from_c4(vex_byte_one, vex_byte_two);
+
+ read_vex_instruction(VEXOpcodeMap::Map0F, bytes, instruction, &mut length, p);
+ instruction.length = length;
+ Ok(())
+}
+
+pub(crate) fn two_byte_vex<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Instruction, mut length: u8) -> Result<(), ()> {
+ let vex_byte = bytes.next().ok_or(())?;
+ let p = vex_byte & 0x03;
+ let p = match p {
+ 0x00 => VEXOpcodePrefix::None,
+ 0x01 => VEXOpcodePrefix::Prefix66,
+ 0x02 => VEXOpcodePrefix::PrefixF3,
+ 0x03 => VEXOpcodePrefix::PrefixF2,
+ _ => { unreachable!("p is two bits"); }
+ };
+ instruction.prefixes.vex_from_c5(vex_byte);
+
+ read_vex_instruction(VEXOpcodeMap::Map0F, bytes, instruction, &mut length, p);
+ instruction.length = length;
+ Ok(())
+}
+
+fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Instruction, length: &mut u8, operand_code: VEXOperandCode) -> Result<(), ()> {
+ match operand_code {
+ VEXOperandCode::Nothing => {
+ Ok(())
+ },
+ op @ VEXOperandCode::V15_G_E_xmm |
+ op @ VEXOperandCode::V15_G_M_xmm |
+ op @ VEXOperandCode::E_G_xmm |
+ op @ VEXOperandCode::U_G_xmm |
+ op @ VEXOperandCode::M_G_xmm |
+ op @ VEXOperandCode::E_G_xmm_imm8 |
+ op @ VEXOperandCode::U_G_xmm_imm8 => {
+ let modrm = read_modrm(bytes, instruction, length)?;
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);
+ let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?;
+ instruction.operands[0] = mem_oper;
+ instruction.operands[1] = OperandSpec::RegRRR;
+ Ok(())
+ }
+
+ op @ VEXOperandCode::G_M_xmm |
+ op @ VEXOperandCode::G_U_xmm |
+ op @ VEXOperandCode::G_E_xmm |
+ op @ VEXOperandCode::G_E_xmm_imm8 => {
+ let modrm = read_modrm(bytes, instruction, length)?;
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);
+ let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = mem_oper;
+ Ok(())
+ }
+
+ op @ VEXOperandCode::E_G_ymm |
+ op @ VEXOperandCode::U_G_ymm |
+ op @ VEXOperandCode::M_G_ymm |
+ op @ VEXOperandCode::V15_G_E_ymm |
+ op @ VEXOperandCode::V15_G_M_ymm => {
+ let modrm = read_modrm(bytes, instruction, length)?;
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);
+ let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?;
+ instruction.operands[0] = mem_oper;
+ instruction.operands[1] = OperandSpec::RegRRR;
+ Ok(())
+ }
+
+ op @ VEXOperandCode::G_M_ymm |
+ op @ VEXOperandCode::G_U_ymm |
+ op @ VEXOperandCode::G_E_ymm => {
+ let modrm = read_modrm(bytes, instruction, length)?;
+ instruction.modrm_rrr =
+ RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);
+ let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?;
+ instruction.operands[0] = OperandSpec::RegRRR;
+ instruction.operands[1] = mem_oper;
+ Ok(())
+ }
+
+ VEXOperandCode::E_V_G_ymm |
+ VEXOperandCode::E_xmm_G_ymm_imm8 |
+ VEXOperandCode::Ev_G_xmm_imm8 |
+ VEXOperandCode::G_E_ymm_imm8 |
+ VEXOperandCode::G_xmm_E_xmm |
+ VEXOperandCode::G_xmm_E_ymm |
+ VEXOperandCode::G_ymm_E_xmm |
+ VEXOperandCode::G_ymm_E_ymm |
+ VEXOperandCode::M_V_G_xmm |
+ VEXOperandCode::M_V_G_ymm |
+ VEXOperandCode::V_G_E_xmm |
+ VEXOperandCode::V_G_E_xmm_imm8 |
+ VEXOperandCode::V_G_E_xmm_xmm4 |
+ VEXOperandCode::V_G_E_ymm |
+ VEXOperandCode::V_G_E_ymm_imm8 |
+ VEXOperandCode::V_G_E_ymm_ymm4 |
+ VEXOperandCode::V_G_M_xmm |
+ VEXOperandCode::V_G_M_ymm |
+ VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 |
+ VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 |
+ VEXOperandCode::Eq_G_xmm |
+ VEXOperandCode::Ed_G_xmm |
+ VEXOperandCode::G_xmm_Ed |
+ VEXOperandCode::G_xmm_Eq |
+ VEXOperandCode::V_G_ymm_E_xmm |
+ VEXOperandCode::V_G_xmm_Ew_imm8 => {
+ Ok(()) // :)
+ }
+
+ }
+}
+
+fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &mut T, instruction: &mut Instruction, length: &mut u8, p: VEXOpcodePrefix) -> Result<(), ()> {
+ let opc = bytes.next().ok_or(())?;
+ let L = instruction.prefixes.vex().l();
+
+ println!("reading vex instruction from opcode prefix {:?}, L: {}, opc: {:#x}", p, L, opc);
+
+ // several combinations simply have no instructions. check for those first.
+ let (opcode, operand_code) = match opcode_map {
+ VEXOpcodeMap::Map0F => {
+ match p {
+ VEXOpcodePrefix::None => {
+ match opc {
+ 0x10 => (Opcode::VMOVUPS, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }),
+ 0x11 => (Opcode::VMOVUPS, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }),
+ // ugh
+// 0x12 => (Opcode::VMOVHLPS, ..),
+// 0x12 => (Opcode::VMOVLPS, ..),
+ 0x13 => (Opcode::VMOVLPS, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::M_G_xmm
+ }),
+ 0x14 => (Opcode::VUNPCKLPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x15 => (Opcode::VUNPCKHPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ // ugh
+// 0x16 => (Opcode::VMOVHPS, ..),
+// 0x16 => (Opcode::VMOVLHPS, ..),
+ 0x17 => (Opcode::VMOVHPS, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::M_G_xmm
+ }),
+ 0x28 => (Opcode::VMOVAPS, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x29 => (Opcode::VMOVAPS, if L {
+ VEXOperandCode::E_G_ymm
+ } else {
+ VEXOperandCode::E_G_xmm
+ }),
+ 0x2B => (Opcode::VMOVNTPS, if L {
+ VEXOperandCode::M_G_ymm
+ } else {
+ VEXOperandCode::M_G_xmm
+ }),
+ 0x50 => (Opcode::VMOVMSKPS, if L {
+ VEXOperandCode::U_G_ymm
+ } else {
+ VEXOperandCode::U_G_xmm
+ }),
+ 0x51 => (Opcode::VSQRTPS, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x52 => (Opcode::VRSQRTPS, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x53 => (Opcode::VRCPPS, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x57 => (Opcode::VXORPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x58 => (Opcode::VADDPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x59 => (Opcode::VMULPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x5A => (Opcode::VCVTPS2PD, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x5B => (Opcode::VCVTDQ2PS, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x5C => (Opcode::VSUBPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x5D => (Opcode::VMINPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x5E => (Opcode::VDIVPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x5F => (Opcode::VMAXPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x77 => (Opcode::VZEROUPPER, VEXOperandCode::Nothing),
+ 0xC2 => (Opcode::VCMPPS, if L {
+ VEXOperandCode::V_G_E_ymm_imm8
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0xC6 => (Opcode::VSHUFPS, if L {
+ VEXOperandCode::V_G_E_ymm_imm8
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }
+ }
+ },
+ VEXOpcodePrefix::Prefix66 => {
+ match opc {
+ 0x10 => (Opcode::VMOVUPD, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x11 => (Opcode::VMOVUPD, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x12 => (Opcode::VMOVLPD, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_M_xmm
+ }),
+ 0x13 => (Opcode::VMOVLPD, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::M_G_xmm
+ }),
+ 0x14 => (Opcode::VUNPCKLPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x15 => (Opcode::VUNPCKHPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x16 => (Opcode::VMOVHPD, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_M_xmm
+ }),
+ 0x17 => (Opcode::VMOVHPD, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::M_G_xmm
+ }),
+ 0x28 => (Opcode::VMOVAPD, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x29 => (Opcode::VMOVAPD, if L {
+ VEXOperandCode::E_G_ymm
+ } else {
+ VEXOperandCode::E_G_xmm
+ }),
+ 0x2B => (Opcode::VMOVNTPD, if L {
+ VEXOperandCode::M_G_ymm
+ } else {
+ VEXOperandCode::M_G_xmm
+ }),
+ 0x50 => (Opcode::VMOVMSKPD, if L {
+ VEXOperandCode::G_U_ymm
+ } else {
+ VEXOperandCode::G_U_xmm
+ }),
+ 0x51 => (Opcode::VSQRTPD, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x57 => (Opcode::VXORPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x58 => (Opcode::VADDPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x59 => (Opcode::VMULPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x5A => (Opcode::VCVTPD2PS, if L {
+ VEXOperandCode::G_xmm_E_ymm
+ } else {
+ VEXOperandCode::G_xmm_E_xmm
+ }),
+ 0x5B => (Opcode::VCVTPS2DQ, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x5C => (Opcode::VSUBPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x5D => (Opcode::VMINPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x5E => (Opcode::VDIVPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x5F => (Opcode::VMAXPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x60 => (Opcode::VPUNPCKLBW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x61 => (Opcode::VPUNPCKLWD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x62 => (Opcode::VPUNPCKLDQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x63 => (Opcode::VPACKSSWB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x64 => (Opcode::VPCMPGTB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x65 => (Opcode::VPCMPGTW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x66 => (Opcode::VPCMPGTD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x67 => (Opcode::VPACKUSWB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x68 => (Opcode::VPUNPCKHBW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x69 => (Opcode::VPUNPCKHWD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x6A => (Opcode::VPUNPCKHDQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x6B => (Opcode::VPACKSSDW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x6C => (Opcode::VPUNPCKLQDQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x6D => (Opcode::VPUNPCKHQDQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x6E => if instruction.prefixes.vex().w() {
+ (Opcode::VMOVQ, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::G_xmm_Eq
+ })
+ } else {
+ (Opcode::VMOVD, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::G_xmm_Ed
+ })
+ },
+ 0x6F => (Opcode::VMOVDQA, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x70 => (Opcode::VPSHUFD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ }),
+ 0x71 => (Opcode::VPSLLW, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x71 => (Opcode::VPSRAW, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x71 => (Opcode::VPSRLW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ }),
+ 0x72 => (Opcode::VPSLLD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x72 => (Opcode::VPSRAD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x72 => (Opcode::VPSRLD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x73 => (Opcode::VPSLLDQ, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x73 => (Opcode::VPSLLQ, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x73 => (Opcode::VPSRLDQ, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x73 => (Opcode::VPSRLQ, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x74 => (Opcode::VPCMPEQB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x75 => (Opcode::VPCMPEQW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x76 => (Opcode::VPCMPEQD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x7C => (Opcode::VHADDPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x7D => (Opcode::VHSUBPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x7E => (Opcode::VMOVD, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::Ed_G_xmm
+ }),
+ 0x7E => (Opcode::VMOVQ, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::Eq_G_xmm
+ }),
+ 0x7F => (Opcode::VMOVDQA, if L {
+ VEXOperandCode::E_G_ymm
+ } else {
+ VEXOperandCode::E_G_xmm
+ }),
+ 0xC2 => (Opcode::VCMPPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xC4 => (Opcode::VPINSRW, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_xmm_Ew_imm8
+ }),
+ 0xC5 => (Opcode::VPEXTRW, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::U_G_xmm_imm8
+ }),
+ 0xC6 => (Opcode::VSHUFPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xD0 => (Opcode::VADDSUBPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xD1 => (Opcode::VPSRLW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xD2 => (Opcode::VPSRLD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xD3 => (Opcode::VPSRLQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xD4 => (Opcode::VPADDQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xD5 => (Opcode::VPMULLW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xD6 => (Opcode::VMOVQ, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0xD7 => (Opcode::VPMOVMSKB, if L {
+ VEXOperandCode::U_G_ymm
+ } else {
+ VEXOperandCode::U_G_xmm
+ }),
+ 0xD8 => (Opcode::VPSUBUSB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xD9 => (Opcode::VPSUBUSW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xDB => (Opcode::VPAND, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xDC => (Opcode::VPADDUSB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0xDD => (Opcode::VPADDUSW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xDF => (Opcode::VPANDN, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xE0 => (Opcode::VPAVGB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xE1 => (Opcode::VPSRAW, if L {
+ VEXOperandCode::V_G_ymm_E_xmm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xE2 => (Opcode::VPSRAD, if L {
+ VEXOperandCode::V_G_ymm_E_xmm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xE3 => (Opcode::VPAVGW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xE4 => (Opcode::VPMULHUW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xE5 => (Opcode::VPMULHW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xE6 => (Opcode::VCVTTPD2DQ, if L {
+ VEXOperandCode::G_xmm_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0xE7 => (Opcode::VMOVNTDQ, if L {
+ VEXOperandCode::M_G_ymm
+ } else {
+ VEXOperandCode::M_G_xmm
+ }),
+ 0xE8 => (Opcode::VPSUBSB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xE9 => (Opcode::VPSUBSW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xEB => (Opcode::VPOR, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xEC => (Opcode::VPADDSB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xED => (Opcode::VPADDSW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xEE => (Opcode::VPMAXSW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xEF => (Opcode::VPXOR, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xF1 => (Opcode::VPSLLW, if L {
+ VEXOperandCode::V_G_ymm_E_xmm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xF2 => (Opcode::VPSLLD, if L {
+ VEXOperandCode::V_G_ymm_E_xmm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xF3 => (Opcode::VPSLLQ, if L {
+ VEXOperandCode::V_G_ymm_E_xmm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xF4 => (Opcode::VPMULUDQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xF5 => (Opcode::VPMADDWD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xF6 => (Opcode::VPSADBW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xF7 => (Opcode::VMASKMOVDQU, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0xF8 => (Opcode::VPSUBB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xF9 => (Opcode::VPSUBW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xFA => (Opcode::VPSUBD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xFB => (Opcode::VPSUBQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xFC => (Opcode::VPADDB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xFD => (Opcode::VPADDW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xFE => (Opcode::VPADDD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }
+ }
+ }
+ VEXOpcodePrefix::PrefixF2 => {
+ match opc {
+ 0x12 => (Opcode::VMOVDDUP, if L {
+ VEXOperandCode::G_E_ymm
+ } else {
+ VEXOperandCode::G_E_xmm
+ }),
+ 0x70 => (Opcode::VPSHUFLW, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ }),
+ 0x7c => (Opcode::VHADDPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x7d => (Opcode::VHSUBPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xd0 => (Opcode::VADDSUBPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xe6 => (Opcode::VCVTPD2DQ, if L {
+ VEXOperandCode::G_xmm_E_ymm
+ } else {
+ VEXOperandCode::G_xmm_E_xmm
+ }),
+ 0xf0 => (Opcode::VLDDQU, if L {
+ VEXOperandCode::G_M_ymm
+ } else {
+ VEXOperandCode::G_M_ymm
+ }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }
+ }
+ }
+ VEXOpcodePrefix::PrefixF3 => {
+ match opc {
+ 0x12 => (Opcode::VMOVSLDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }),
+ 0x16 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }),
+ 0x5b => (Opcode::VCVTTPS2DQ, if L { VEXOperandCode::G_ymm_E_ymm } else { VEXOperandCode::G_xmm_E_xmm }),
+ 0x6f => (Opcode::VMOVDQU, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }),
+ 0x70 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm_imm8 } else { VEXOperandCode::G_E_xmm_imm8 }),
+ 0x7e => (Opcode::VMOVQ, if L { instruction.opcode = Opcode::Invalid; return Err(()); } else { VEXOperandCode::G_E_xmm }),
+ 0x7f => (Opcode::VMOVDQU, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }),
+ 0xe6 => (Opcode::VCVTDQ2PD, if L { VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_xmm_E_xmm }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }
+ }
+ }
+ }
+ }
+ VEXOpcodeMap::Map0F38 => {
+ // TODO: verify rejecting invalid W bit
+ if let VEXOpcodePrefix::Prefix66 = p {
+ // possibly valid!
+ match opc {
+ 0x00 => (Opcode::VPSHUFB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x01 => (Opcode::VPHADDW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x02 => (Opcode::VPHADDD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x03 => (Opcode::VPHADDSW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x04 => (Opcode::VPMADDUBSW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x05 => (Opcode::VPHSUBW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x06 => (Opcode::VPHSUBD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x07 => (Opcode::VPHSUBSW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x08 => (Opcode::VPSIGNB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x09 => (Opcode::VPSIGNW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x0A => (Opcode::VPSIGND, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x0B => (Opcode::VPMULHRSW, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x0C => (Opcode::VPERMILPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x0D => (Opcode::VPERMILPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x0E => (Opcode::VTESTPS, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x0F => (Opcode::VTESTPD, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x13 => (Opcode::VCVTPH2PS, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x16 => (Opcode::VPERMPS, if L {
+ VEXOperandCode::V_G_E_xmm
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x17 => (Opcode::VPTEST, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x18 => (Opcode::VBROADCASTSS, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x19 => (Opcode::VBROADCASTSD, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x1A => (Opcode::VBROADCASTF128, if L {
+ VEXOperandCode::V15_G_M_ymm
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x1C => (Opcode::VPABSB, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x1D => (Opcode::VPABSW, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x1E => (Opcode::VPABSD, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x20 => (Opcode::VPMOVSXBW, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x21 => (Opcode::VPMOVSXBD, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x22 => (Opcode::VPMOVSXBQ, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x23 => (Opcode::VPMOVSXWD, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x24 => (Opcode::VPMOVSXWQ, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x25 => (Opcode::VPMOVSXDQ, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x28 => (Opcode::VPMULDQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x29 => (Opcode::VPCMPEQQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x2A => (Opcode::VMOVNTDQA, if L {
+ VEXOperandCode::V15_G_M_ymm
+ } else {
+ VEXOperandCode::V15_G_M_xmm
+ }),
+ 0x2C => (Opcode::VMASKMOVPS, if L {
+ VEXOperandCode::V_G_M_ymm
+ } else {
+ VEXOperandCode::V_G_M_xmm
+ }),
+ 0x2D => (Opcode::VMASKMOVPD, if L {
+ VEXOperandCode::V_G_M_ymm
+ } else {
+ VEXOperandCode::V_G_M_xmm
+ }),
+ 0x2E => (Opcode::VMASKMOVPS, if L {
+ VEXOperandCode::M_V_G_ymm
+ } else {
+ VEXOperandCode::M_V_G_xmm
+ }),
+ 0x2F => (Opcode::VMASKMOVPD, if L {
+ VEXOperandCode::M_V_G_ymm
+ } else {
+ VEXOperandCode::M_V_G_xmm
+ }),
+ 0x30 => (Opcode::VPMOVZXBW, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x31 => (Opcode::VPMOVZXBD, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x32 => (Opcode::VPMOVZXBQ, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x33 => (Opcode::VPMOVZXWD, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x34 => (Opcode::VPMOVZXWQ, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x35 => (Opcode::VPMOVZXDQ, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x36 => (Opcode::VPERMD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x37 => (Opcode::VPCMPGTQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x39 => (Opcode::VPMINSD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x3B => (Opcode::VPMINUD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x3C => (Opcode::VPMAXSB, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x3D => (Opcode::VPMAXSD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x3F => (Opcode::VPMAXUD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x40 => (Opcode::VPMULLD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x41 => (Opcode::VPHMINPOSUW, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x45 => (Opcode::VPSRLVD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x45 => (Opcode::VPSRLVQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x46 => (Opcode::VPSRAVD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x47 => (Opcode::VPSLLVD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x47 => (Opcode::VPSLLVQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x58 => (Opcode::VPBROADCASTD, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x59 => (Opcode::VPBROADCASTQ, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0x5A => (Opcode::VBROADCASTI128, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x78 => (Opcode::VPBROADCASTB, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_ymm
+ }),
+ 0x79 => (Opcode::VPBROADCASTW, if L {
+ VEXOperandCode::V15_G_E_ymm
+ } else {
+ VEXOperandCode::V15_G_E_ymm
+ }),
+ 0x8C => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VPMASKMOVD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VPMASKMOVQ, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0x8E => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VPMASKMOVD, if L {
+ VEXOperandCode::E_V_G_ymm
+ } else {
+ VEXOperandCode::E_V_G_ymm
+ })
+ } else {
+ (Opcode::VPMASKMOVQ, if L {
+ VEXOperandCode::E_V_G_ymm
+ } else {
+ VEXOperandCode::E_V_G_ymm
+ })
+ }
+ },
+ // TODO
+ 0x90 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VPGATHERDD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ })
+ } else {
+ (Opcode::VPGATHERDQ, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ })
+ }
+ },
+ 0x91 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VPGATHERQD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ })
+ } else {
+ (Opcode::VPGATHERQQ, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ })
+ }
+ },
+ 0x92 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VGATHERDPD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ })
+ } else {
+ (Opcode::VGATHERDPS, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ })
+ }
+ },
+ 0x93 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VGATHERQPD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ })
+ } else {
+ (Opcode::VGATHERQPS, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ })
+ }
+ },
+ 0x96 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMADDSUB132PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMADDSUB132PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0x97 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMSUBADD132PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMSUBADD132PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0x98 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMADD132PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMADD132PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0x9A => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMSUB132PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMSUB132PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0x9C => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFNMADD132PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFNMADD132PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0x9E => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFNMSUB132PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFNMSUB132PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xA6 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMADDSUB213PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMADDSUB213PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xA7 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMSUBADD213PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMSUBADD213PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xA8 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMADD213PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMADD213PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xAA => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMSUB213PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMSUB213PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xAC => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFNMADD213PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFNMADD213PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xAE => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFNMSUB213PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFNMSUB213PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xB6 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMADDSUB231PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMADDSUB231PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xB7 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMSUBADD231PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMSUBADD231PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xB8 => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMADD231PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMADD231PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xBA => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFMSUB231PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFMSUB231PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xBC => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFNMADD231PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFNMADD231PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xBE => {
+ if instruction.prefixes.vex().w() {
+ (Opcode::VFNMSUB231PD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ } else {
+ (Opcode::VFNMSUB231PS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_ymm
+ })
+ }
+ },
+ 0xDB => (Opcode::VAESIMC, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V15_G_E_xmm
+ }),
+ 0xDC => (Opcode::VAESENC, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xDD => (Opcode::VAESENCLAST, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xDE => (Opcode::VAESDEC, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0xDF => (Opcode::VAESDECLAST, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }
+ }
+ } else {
+ // the only VEX* 0f38 instructions have an implied 66 prefix.
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }
+ }
+ VEXOpcodeMap::Map0F3A => {
+ if let VEXOpcodePrefix::Prefix66 = p {
+ // possibly valid!
+ match opc {
+ 0x00 => (Opcode::VPERMQ, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x01 => (Opcode::VPERMPD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x02 => (Opcode::VPBLENDD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x04 => (Opcode::VPERMILPS, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x05 => (Opcode::VPERMILPD, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ VEXOperandCode::V_G_E_xmm
+ }),
+ 0x06 => (Opcode::VPERM2F128, if L {
+ VEXOperandCode::V_G_E_ymm
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x08 => (Opcode::VROUNDPS, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ }),
+ 0x09 => (Opcode::VROUNDPD, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ }),
+ 0x0C => (Opcode::VBLENDPS, if L {
+ VEXOperandCode::V_G_E_ymm_imm8
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x0D => (Opcode::VBLENDPD, if L {
+ VEXOperandCode::V_G_E_ymm_imm8
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x0E => (Opcode::VPBLENDW, if L {
+ VEXOperandCode::V_G_E_ymm_imm8
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x0F => (Opcode::VPALIGNR, if L {
+ VEXOperandCode::V_G_E_ymm_imm8
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x14 => (Opcode::VPEXTRB, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::Ev_G_xmm_imm8
+ }),
+ 0x15 => (Opcode::VPEXTRW, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::Ev_G_xmm_imm8
+ }),
+ 0x16 => (Opcode::VPEXTRD, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ // varies on W
+ VEXOperandCode::Ev_G_xmm_imm8
+ }),
+ 0x16 => (Opcode::VPEXTRQ, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x17 => (Opcode::VEXTRACTPS, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::G_E_ymm_imm8
+ }),
+ 0x18 => (Opcode::VINSERTF128, if L {
+ VEXOperandCode::V_G_E_ymm_imm8
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x19 => (Opcode::VEXTRACTF128, if L {
+ VEXOperandCode::E_xmm_G_ymm_imm8
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x1D => (Opcode::VCVTPS2PH, if L {
+ VEXOperandCode::E_xmm_G_ymm_imm8
+ } else {
+ VEXOperandCode::E_G_xmm_imm8
+ }),
+ 0x20 => (Opcode::VPINSRB, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x21 => (Opcode::VINSERTPS, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x22 => (Opcode::VPINSRD, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x22 => (Opcode::VPINSRQ, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x38 => (Opcode::VINSERTI128, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8
+ }),
+ 0x39 => (Opcode::VEXTRACTI128, if L {
+ VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x40 => (Opcode::VDPPS, if L {
+ VEXOperandCode::V_G_E_ymm_imm8
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x41 => (Opcode::VDPPD, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x42 => (Opcode::VMPSADBW, if L {
+ VEXOperandCode::G_E_ymm_imm8
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ }),
+ 0x44 => (Opcode::VPCLMULQDQ, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::V_G_E_xmm_imm8
+ }),
+ 0x46 => (Opcode::VPERM2I128, if L {
+ VEXOperandCode::V_G_E_ymm_imm8
+ } else {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }),
+ 0x4A => (Opcode::VBLENDVPS, if L {
+ VEXOperandCode::V_G_E_ymm_ymm4
+ } else {
+ VEXOperandCode::V_G_E_xmm_xmm4
+ }),
+ 0x4B => (Opcode::VBLENDVPD, if L {
+ VEXOperandCode::V_G_E_ymm_ymm4
+ } else {
+ VEXOperandCode::V_G_E_xmm_xmm4
+ }),
+ 0x4C => (Opcode::VPBLENDVB, if L {
+ VEXOperandCode::V_G_E_ymm_ymm4
+ } else {
+ VEXOperandCode::V_G_E_xmm_xmm4
+ }),
+ 0x62 => (Opcode::VPCMPISTRM, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ }),
+ 0x63 => (Opcode::VPCMPISTRI, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ }),
+ 0xDF => (Opcode::VAESKEYGENASSIST, if L {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ } else {
+ VEXOperandCode::G_E_xmm_imm8
+ }),
+ _ => {
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }
+ }
+ } else {
+ // the only VEX* 0f3a instructions have an implied 66 prefix.
+ instruction.opcode = Opcode::Invalid;
+ return Err(());
+ }
+ }
+ };
+ instruction.opcode = opcode;
+ read_vex_operands(bytes, instruction, length, operand_code)
+}
diff --git a/test/test.rs b/test/test.rs
index cc865d9..8452e89 100644
--- a/test/test.rs
+++ b/test/test.rs
@@ -8,14 +8,26 @@ use yaxpeax_x86::{Instruction, InstDecoder, decode_one};
fn decode(bytes: &[u8]) -> Option<Instruction> {
let mut instr = Instruction::invalid();
- match decode_one(bytes.iter().map(|x| *x).take(16).collect::<Vec<u8>>(), &mut instr) {
+ match decode_one(&InstDecoder::default(), bytes.iter().map(|x| *x).take(16).collect::<Vec<u8>>(), &mut instr) {
+ Some(()) => Some(instr),
+ None => None
+ }
+}
+
+fn decode_as(decoder: &InstDecoder, bytes: &[u8]) -> Option<Instruction> {
+ let mut instr = Instruction::invalid();
+ match decode_one(decoder, bytes.iter().map(|x| *x).take(16).collect::<Vec<u8>>(), &mut instr) {
Some(()) => Some(instr),
None => None
}
}
fn test_invalid(data: &[u8]) {
- if let Some(inst) = InstDecoder::default().decode(data.into_iter().cloned()) {
+ test_invalid_under(&InstDecoder::default(), data);
+}
+
+fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) {
+ if let Some(inst) = decoder.decode(data.into_iter().cloned()) {
assert_eq!(inst.opcode, yaxpeax_x86::Opcode::Invalid);
} else {
// this is fine
@@ -23,11 +35,15 @@ fn test_invalid(data: &[u8]) {
}
fn test_display(data: &[u8], expected: &'static str) {
+ test_display_under(&InstDecoder::default(), data, expected);
+}
+
+fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str) {
let mut hex = String::new();
for b in data {
write!(hex, "{:02x}", b).unwrap();
}
- match InstDecoder::default().decode(data.into_iter().map(|x| *x)) {
+ match decoder.decode(data.into_iter().map(|x| *x)) {
Some(instr) => {
let text = format!("{}", instr);
assert!(
@@ -231,8 +247,16 @@ fn test_push_pop() {
}
#[test]
+fn test_bmi1() {
+ let bmi1 = InstDecoder::default();
+ let no_bmi1 = InstDecoder::default().without_bmi1();
+ test_display_under(&bmi1, &[0x41, 0x0f, 0xbc, 0xd3], "tzcnt edx, r11d");
+ test_display_under(&no_bmi1, &[0x41, 0x0f, 0xbc, 0xd3], "bsf edx, r11d");
+}
+
+#[test]
fn test_bitwise() {
- test_display(&[0x41, 0x0f, 0xbc, 0xd3], "bsf edx, r11d");
+ test_display_under(&InstDecoder::minimal(), &[0x41, 0x0f, 0xbc, 0xd3], "bsf edx, r11d");
test_display(&[0x48, 0x0f, 0xa3, 0xd0], "bt rax, rdx");
test_display(&[0x48, 0x0f, 0xab, 0xd0], "bts rax, rdx");
}
@@ -265,8 +289,96 @@ fn evex() {
}
#[test]
-#[ignore]
-fn vex() {
+fn test_vex() {
+ test_display(&[0xc5, 0xf8, 0x10, 0x00], "vmovups xmm0, [rax]");
+ test_display(&[0xc5, 0x78, 0x10, 0x0f], "vmovups xmm9, [rdi]");
+ test_display(&[0xc5, 0xf8, 0x10, 0xcf], "vmovups xmm1, xmm7");
+ test_display(&[0xc5, 0xf9, 0x10, 0x0f], "vmovupd xmm1, [rdi]");
+ test_display(&[0xc5, 0xfa, 0x7e, 0x10], "vmovq xmm2, [rax]");
+ test_display(&[0xc5, 0xfc, 0x10, 0x0f], "vmovups ymm1, [rdi]");
+ test_display(&[0xc5, 0xfd, 0x10, 0x0f], "vmovupd ymm1, [rdi]");
+ test_display(&[0xc5, 0xfe, 0x10, 0x0f], "vmovss ymm1, [rdi]");
+ test_display(&[0xc5, 0xff, 0x10, 0xcf], "vmovsd xmm1, xmm0, xmm7");
+ test_display(&[0xc5, 0xff, 0x10, 0x00], "vmovsd xmm0, [rax]");
+ test_invalid(&[0x4f, 0xc5, 0xf8, 0x10, 0x00]);
+ test_invalid(&[0xf0, 0xc5, 0xf8, 0x10, 0x00]);
+ test_display(&[0xc4, 0x02, 0x71, 0x00, 0x00], "vpshufb xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x00, 0x00], "vpshufb ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x00, 0xcd], "vpshufb xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x00, 0xcd], "vpshufb ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x01, 0x00], "vphaddw xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x01, 0x00], "vphaddw ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x01, 0xcd], "vphaddw xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x01, 0xcd], "vphaddw ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x02, 0x00], "vphaddd xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x02, 0x00], "vphaddd ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x02, 0xcd], "vphaddd xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x02, 0xcd], "vphaddd ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x03, 0x00], "vphaddsw xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x03, 0x00], "vphaddsw ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x03, 0xcd], "vphaddsw xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x03, 0xcd], "vphaddsw ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x04, 0x00], "vphaddubsw xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x04, 0x00], "vphaddubsw ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x04, 0xcd], "vphaddubsw xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x04, 0xcd], "vphaddubsw ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x05, 0x00], "vphsubw xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x05, 0x00], "vphsubw ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x05, 0xcd], "vphsubw xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x05, 0xcd], "vphsubw ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x06, 0x00], "vphsubd xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x06, 0x00], "vphsubd ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x06, 0xcd], "vphsubd xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x06, 0xcd], "vphsubd ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x07, 0x00], "vphsubsw xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x07, 0x00], "vphsubsw ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x07, 0xcd], "vphsubsw xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x07, 0xcd], "vphsubsw ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x08, 0x00], "vpsignb xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x08, 0x00], "vpsignb ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x08, 0xcd], "vpsignb xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x08, 0xcd], "vpsignb ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x09, 0x00], "vpsignw xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x09, 0x00], "vpsignw ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x09, 0xcd], "vpsignw xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x09, 0xcd], "vpsignw ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x0a, 0x00], "vpsignd xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x0a, 0x00], "vpsignd ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x0a, 0xcd], "vpsignd xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x0a, 0xcd], "vpsignd ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x0b, 0x00], "vpmulhrsw xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x0b, 0x00], "vpmulhrsw ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x0b, 0xcd], "vpmulhrsw xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x0b, 0xcd], "vpmulhrsw ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x0c, 0x00], "vpermilps xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x0c, 0x00], "vpermilps ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x0c, 0xcd], "vpermilps xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x0c, 0xcd], "vpermilps ymm9, ymm1, ymm13");
+ test_display(&[0xc4, 0x02, 0x71, 0x0d, 0x00], "vpermilpd xmm9, xmm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x75, 0x0d, 0x00], "vpermilpd ymm9, ymm1, [r8]");
+ test_display(&[0xc4, 0x02, 0x71, 0x0d, 0xcd], "vpermilpd xmm9, xmm1, xmm13");
+ test_display(&[0xc4, 0x02, 0x75, 0x0d, 0xcd], "vpermilpd ymm9, ymm1, ymm13");
+ test_invalid(&[0xc4, 0x02, 0x71, 0x0e, 0x00]);
+ test_display(&[0xc4, 0x02, 0x79, 0x0e, 0x00], "vtestps xmm8, [r8]");
+ test_display(&[0xc4, 0x02, 0x7d, 0x0e, 0x00], "vtestps ymm8, [r8]");
+ test_display(&[0xc4, 0x02, 0x79, 0x0e, 0xcd], "vtestps xmm9, xmm13");
+ test_display(&[0xc4, 0x02, 0x7d, 0x0e, 0xcd], "vtestps ymm9, ymm13");
+ test_invalid(&[0xc4, 0x02, 0x71, 0x0f, 0x00]);
+ test_display(&[0xc4, 0x02, 0x79, 0x0f, 0x00], "vtestpd xmm8, [r8]");
+ test_display(&[0xc4, 0x02, 0x7d, 0x0f, 0x00], "vtestpd ymm8, [r8]");
+ test_display(&[0xc4, 0x02, 0x79, 0x0f, 0xcd], "vtestpd xmm9, xmm13");
+ test_display(&[0xc4, 0x02, 0x7d, 0x0f, 0xcd], "vtestpd ymm9, ymm13");
+ test_display(&[0xc4, 0xe2, 0x65, 0x90, 0x04, 0x51], "vpgatherdd ymm0, [rcx + ymm2 * 2], ymm3");
+ test_display(&[0xc4, 0xe2, 0xe5, 0x90, 0x04, 0x51], "vpgatherdq ymm0, [rcx + ymm2 * 2], ymm3");
+ test_display(&[0xc4, 0xe2, 0x65, 0x91, 0x04, 0x51], "vpgatherqd ymm0, [rcx + ymm2 * 2], ymm3");
+ test_display(&[0xc4, 0xe2, 0xe5, 0x91, 0x04, 0x51], "vpgatherqq ymm0, [rcx + ymm2 * 2], ymm3");
+ test_display(&[0xc4, 0x02, 0x09, 0x9d, 0xcd], "vfnmadd132ss xmm9, xmm14, xmm11");
+ test_display(&[0xc4, 0x02, 0x89, 0x9d, 0xcd], "vfnmadd132ss xmm9, xmm14, xmm11");
+// ...
+ test_display(&[0xc4, 0xe3, 0x79, 0x14, 0x00, 0xd0], "vpextrb rax, xmm2, 0x0a");
+ test_display(&[0xc4, 0xe3, 0x79, 0x14, 0x00, 0x0a], "vpextrb [rax], xmm2, 0x0a");
+ test_invalid(&[0xc4, 0xe3, 0xf9, 0x14, 0x00, 0xd0]);
+ test_invalid(&[0xc4, 0xe3, 0xf9, 0x14, 0x00, 0x0a]);
}
#[test]
@@ -293,13 +405,13 @@ fn prefixed_0f() {
test_display(&[0x0f, 0x12, 0xcf], "movhlps xmm1, xmm7");
test_display(&[0x0f, 0x16, 0x0f], "movhps xmm1, [rdi]");
test_display(&[0x0f, 0x16, 0xcf], "movlhps xmm1, xmm7");
-// test_display(&[0x0f, 0x12, 0xc0], "movhlps xmm0, xmm0");
+ test_display(&[0x0f, 0x12, 0xc0], "movhlps xmm0, xmm0");
test_invalid(&[0x0f, 0x13, 0xc0]);
test_display(&[0x0f, 0x13, 0x00], "movlps [rax], xmm0");
test_display(&[0x0f, 0x14, 0x08], "unpcklps xmm1, [rax]");
test_display(&[0x0f, 0x15, 0x08], "unpckhps xmm1, [rax]");
test_display(&[0x0f, 0x16, 0x0f], "movhps xmm1, [rdi]");
-// test_display(&[0x0f, 0x16, 0xc0], "movlhps xmm0, xmm0");
+ test_display(&[0x0f, 0x16, 0xc0], "movlhps xmm0, xmm0");
test_invalid(&[0x0f, 0x17, 0xc0]);
test_display(&[0x0f, 0x17, 0x00], "movhps [rax], xmm0");
test_invalid(&[0x0f, 0x18, 0xc0]);