diff options
| author | iximeow <me@iximeow.net> | 2019-12-13 14:39:47 -0800 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-12 16:10:13 -0800 | 
| commit | 436c65e51f7e14201f902c57fb6a069860126477 (patch) | |
| tree | ceed36b6a4414dc98b042975be2e27472c60a6d6 /src | |
| parent | 4bb189250b99494b292fb24717ee90f3178cbde9 (diff) | |
vex
Diffstat (limited to 'src')
| -rw-r--r-- | src/display.rs | 562 | ||||
| -rw-r--r-- | src/lib.rs | 499 | ||||
| -rw-r--r-- | src/vex.rs | 1906 | 
3 files changed, 2929 insertions, 38 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)) }          } @@ -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) +} | 
