diff options
-rw-r--r-- | src/display.rs | 562 | ||||
-rw-r--r-- | src/lib.rs | 499 | ||||
-rw-r--r-- | src/vex.rs | 1906 | ||||
-rw-r--r-- | test/test.rs | 128 |
4 files changed, 3049 insertions, 46 deletions
diff --git a/src/display.rs b/src/display.rs index 156998a..8bd2689 100644 --- a/src/display.rs +++ b/src/display.rs @@ -82,6 +82,9 @@ impl fmt::Display for RegSpec { RegisterBank::S => { ["cs", "ds", "es", "fs", "gs", "ss"][self.num as usize] } + RegisterBank::K => { + ["k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"][self.num as usize] + } }; write!(f, "{}", name) } @@ -229,6 +232,7 @@ impl fmt::Display for Opcode { &Opcode::BTC => write!(f, "{}", "btc"), &Opcode::BSF => write!(f, "{}", "bsf"), &Opcode::BSR => write!(f, "{}", "bsr"), + &Opcode::TZCNT => write!(f, "{}", "tzcnt"), &Opcode::MOVSS => write!(f, "{}", "movss"), &Opcode::SQRTSS => write!(f, "{}", "sqrtss"), &Opcode::ADDSS => write!(f, "{}", "addss"), @@ -535,6 +539,284 @@ impl fmt::Display for Opcode { &Opcode::CBD => write!(f, "{}", "cbd"), &Opcode::CDQ => write!(f, "{}", "cdq"), &Opcode::CQO => write!(f, "{}", "cqo"), + &Opcode::ANDN => write!(f, "{}", "andn"), + &Opcode::BEXTR => write!(f, "{}", "bextr"), + &Opcode::BLSI => write!(f, "{}", "blsi"), + &Opcode::BLSMSK => write!(f, "{}", "blsmsk"), + &Opcode::BLSR => write!(f, "{}", "blsr"), + &Opcode::VMOVUPS => write!(f, "{}", "vmovups"), + &Opcode::VADDPD => write!(f, "{}", "vaddpd"), + &Opcode::VADDPS => write!(f, "{}", "vaddps"), + &Opcode::VADDSUBPD => write!(f, "{}", "vaddsubpd"), + &Opcode::VAESDEC => write!(f, "{}", "vaesdec"), + &Opcode::VAESDECLAST => write!(f, "{}", "vaesdeclast"), + &Opcode::VAESENC => write!(f, "{}", "vaesenc"), + &Opcode::VAESENCLAST => write!(f, "{}", "vaesenclast"), + &Opcode::VAESIMC => write!(f, "{}", "vaesimc"), + &Opcode::VAESKEYGENASSIST => write!(f, "{}", "vaeskeygenassist"), + &Opcode::VBLENDPD => write!(f, "{}", "vblendpd"), + &Opcode::VBLENDPS => write!(f, "{}", "vblendps"), + &Opcode::VBLENDVPD => write!(f, "{}", "vblendvpd"), + &Opcode::VBLENDVPS => write!(f, "{}", "vblendvps"), + &Opcode::VBROADCASTF128 => write!(f, "{}", "vbroadcastf128"), + &Opcode::VBROADCASTI128 => write!(f, "{}", "vbroadcasti128"), + &Opcode::VBROADCASTSD => write!(f, "{}", "vbroadcastsd"), + &Opcode::VBROADCASTSS => write!(f, "{}", "vbroadcastss"), + &Opcode::VCMPPD => write!(f, "{}", "vcmppd"), + &Opcode::VCMPPS => write!(f, "{}", "vcmpps"), + &Opcode::VCVTDQ2PD => write!(f, "{}", "vcvtdq2pd"), + &Opcode::VCVTDQ2PS => write!(f, "{}", "vcvtdq2ps"), + &Opcode::VCVTPD2PS => write!(f, "{}", "vcvtpd2ps"), + &Opcode::VCVTPH2PS => write!(f, "{}", "vcvtph2ps"), + &Opcode::VCVTPS2DQ => write!(f, "{}", "vcvtps2dq"), + &Opcode::VCVTPS2PD => write!(f, "{}", "vcvtps2pd"), + &Opcode::VCVTPS2PH => write!(f, "{}", "vcvtps2ph"), + &Opcode::VCVTTPD2DQ => write!(f, "{}", "vcvttpd2dq"), + &Opcode::VCVTTPS2DQ => write!(f, "{}", "vcvttps2dq"), + &Opcode::VDIVPD => write!(f, "{}", "vdivpd"), + &Opcode::VDIVPS => write!(f, "{}", "vdivps"), + &Opcode::VDPPD => write!(f, "{}", "vdppd"), + &Opcode::VDPPS => write!(f, "{}", "vdpps"), + &Opcode::VEXTRACTF128 => write!(f, "{}", "vextractf128"), + &Opcode::VEXTRACTI128 => write!(f, "{}", "vextracti128"), + &Opcode::VEXTRACTPS => write!(f, "{}", "vextractps"), + &Opcode::VFMADD132PD => write!(f, "{}", "vfmadd132pd"), + &Opcode::VFMADD132PS => write!(f, "{}", "vfmadd132ps"), + &Opcode::VFMADD213PD => write!(f, "{}", "vfmadd213pd"), + &Opcode::VFMADD213PS => write!(f, "{}", "vfmadd213ps"), + &Opcode::VFMADD231PD => write!(f, "{}", "vfmadd231pd"), + &Opcode::VFMADD231PS => write!(f, "{}", "vfmadd231ps"), + &Opcode::VFMADDSUB132PD => write!(f, "{}", "vfmaddsub132pd"), + &Opcode::VFMADDSUB132PS => write!(f, "{}", "vfmaddsub132ps"), + &Opcode::VFMADDSUB213PD => write!(f, "{}", "vfmaddsub213pd"), + &Opcode::VFMADDSUB213PS => write!(f, "{}", "vfmaddsub213ps"), + &Opcode::VFMADDSUB231PD => write!(f, "{}", "vfmaddsub231pd"), + &Opcode::VFMADDSUB231PS => write!(f, "{}", "vfmaddsub231ps"), + &Opcode::VFMSUB132PD => write!(f, "{}", "vfmsub132pd"), + &Opcode::VFMSUB132PS => write!(f, "{}", "vfmsub132ps"), + &Opcode::VFMSUB213PD => write!(f, "{}", "vfmsub213pd"), + &Opcode::VFMSUB213PS => write!(f, "{}", "vfmsub213ps"), + &Opcode::VFMSUB231PD => write!(f, "{}", "vfmsub231pd"), + &Opcode::VFMSUB231PS => write!(f, "{}", "vfmsub231ps"), + &Opcode::VFMSUBADD132PD => write!(f, "{}", "vfmsubadd132pd"), + &Opcode::VFMSUBADD132PS => write!(f, "{}", "vfmsubadd132ps"), + &Opcode::VFMSUBADD213PD => write!(f, "{}", "vfmsubadd213pd"), + &Opcode::VFMSUBADD213PS => write!(f, "{}", "vfmsubadd213ps"), + &Opcode::VFMSUBADD231PD => write!(f, "{}", "vfmsubadd231pd"), + &Opcode::VFMSUBADD231PS => write!(f, "{}", "vfmsubadd231ps"), + &Opcode::VFNMADD132PD => write!(f, "{}", "vfnmadd132pd"), + &Opcode::VFNMADD132PS => write!(f, "{}", "vfnmadd132ps"), + &Opcode::VFNMADD213PD => write!(f, "{}", "vfnmadd213pd"), + &Opcode::VFNMADD213PS => write!(f, "{}", "vfnmadd213ps"), + &Opcode::VFNMADD231PD => write!(f, "{}", "vfnmadd231pd"), + &Opcode::VFNMADD231PS => write!(f, "{}", "vfnmadd231ps"), + &Opcode::VFNMSUB132PD => write!(f, "{}", "vfnmsub132pd"), + &Opcode::VFNMSUB132PS => write!(f, "{}", "vfnmsub132ps"), + &Opcode::VFNMSUB213PD => write!(f, "{}", "vfnmsub213pd"), + &Opcode::VFNMSUB213PS => write!(f, "{}", "vfnmsub213ps"), + &Opcode::VFNMSUB231PD => write!(f, "{}", "vfnmsub231pd"), + &Opcode::VFNMSUB231PS => write!(f, "{}", "vfnmsub231ps"), + &Opcode::VGATHERDPD => write!(f, "{}", "vgatherdpd"), + &Opcode::VGATHERDPS => write!(f, "{}", "vgatherdps"), + &Opcode::VGATHERQPD => write!(f, "{}", "vgatherqpd"), + &Opcode::VGATHERQPS => write!(f, "{}", "vgatherqps"), + &Opcode::VHADDPD => write!(f, "{}", "vhaddpd"), + &Opcode::VHSUBPD => write!(f, "{}", "vhsubpd"), + &Opcode::VINSERTF128 => write!(f, "{}", "vinsertf128"), + &Opcode::VINSERTI128 => write!(f, "{}", "vinserti128"), + &Opcode::VINSERTPS => write!(f, "{}", "vinsertps"), + &Opcode::VMASKMOVDQU => write!(f, "{}", "vmaskmovdqu"), + &Opcode::VMASKMOVPD => write!(f, "{}", "vmaskmovpd"), + &Opcode::VMASKMOVPS => write!(f, "{}", "vmaskmovps"), + &Opcode::VMAXPD => write!(f, "{}", "vmaxpd"), + &Opcode::VMAXPS => write!(f, "{}", "vmaxps"), + &Opcode::VMINPD => write!(f, "{}", "vminpd"), + &Opcode::VMINPS => write!(f, "{}", "vminps"), + &Opcode::VMOVAPD => write!(f, "{}", "vmovapd"), + &Opcode::VMOVAPS => write!(f, "{}", "vmovaps"), + &Opcode::VMOVD => write!(f, "{}", "vmovd"), + &Opcode::VMOVDQA => write!(f, "{}", "vmovdqa"), + &Opcode::VMOVDQU => write!(f, "{}", "vmovdqu"), + &Opcode::VMOVHLPS => write!(f, "{}", "vmovhlps"), + &Opcode::VMOVHPD => write!(f, "{}", "vmovhpd"), + &Opcode::VMOVHPS => write!(f, "{}", "vmovhps"), + &Opcode::VMOVLHPS => write!(f, "{}", "vmovlhps"), + &Opcode::VMOVLPD => write!(f, "{}", "vmovlpd"), + &Opcode::VMOVLPS => write!(f, "{}", "vmovlps"), + &Opcode::VMOVMSKPD => write!(f, "{}", "vmovmskpd"), + &Opcode::VMOVMSKPS => write!(f, "{}", "vmovmskps"), + &Opcode::VMOVNTDQ => write!(f, "{}", "vmovntdq"), + &Opcode::VMOVNTDQA => write!(f, "{}", "vmovntdqa"), + &Opcode::VMOVNTPD => write!(f, "{}", "vmovntpd"), + &Opcode::VMOVNTPS => write!(f, "{}", "vmovntps"), + &Opcode::VMOVQ => write!(f, "{}", "vmovq"), + &Opcode::VMOVSHDUP => write!(f, "{}", "vmovshdup"), + &Opcode::VMOVSLDUP => write!(f, "{}", "vmovsldup"), + &Opcode::VMOVUPD => write!(f, "{}", "vmovupd"), + &Opcode::VMOVUPS => write!(f, "{}", "vmovups"), + &Opcode::VMPSADBW => write!(f, "{}", "vmpsadbw"), + &Opcode::VMULPD => write!(f, "{}", "vmulpd"), + &Opcode::VMULPS => write!(f, "{}", "vmulps"), + &Opcode::VPABSB => write!(f, "{}", "vpabsb"), + &Opcode::VPABSD => write!(f, "{}", "vpabsd"), + &Opcode::VPABSW => write!(f, "{}", "vpabsw"), + &Opcode::VPACKSSDW => write!(f, "{}", "vpackssdw"), + &Opcode::VPACKSSWB => write!(f, "{}", "vpacksswb"), + &Opcode::VPACKUSWB => write!(f, "{}", "vpackuswb"), + &Opcode::VPADDB => write!(f, "{}", "vpaddb"), + &Opcode::VPADDD => write!(f, "{}", "vpaddd"), + &Opcode::VPADDQ => write!(f, "{}", "vpaddq"), + &Opcode::VPADDSB => write!(f, "{}", "vpaddsb"), + &Opcode::VPADDSW => write!(f, "{}", "vpaddsw"), + &Opcode::VPADDUSB => write!(f, "{}", "vpaddusb"), + &Opcode::VPADDUSW => write!(f, "{}", "vpaddusw"), + &Opcode::VPADDW => write!(f, "{}", "vpaddw"), + &Opcode::VPALIGNR => write!(f, "{}", "vpalignr"), + &Opcode::VPAND => write!(f, "{}", "vpand"), + &Opcode::VPANDN => write!(f, "{}", "vpandn"), + &Opcode::VPAVGB => write!(f, "{}", "vpavgb"), + &Opcode::VPAVGW => write!(f, "{}", "vpavgw"), + &Opcode::VPBLENDD => write!(f, "{}", "vpblendd"), + &Opcode::VPBLENDVB => write!(f, "{}", "vpblendvb"), + &Opcode::VPBLENDW => write!(f, "{}", "vpblendw"), + &Opcode::VPBROADCASTB => write!(f, "{}", "vpbroadcastb"), + &Opcode::VPBROADCASTD => write!(f, "{}", "vpbroadcastd"), + &Opcode::VPBROADCASTQ => write!(f, "{}", "vpbroadcastq"), + &Opcode::VPBROADCASTW => write!(f, "{}", "vpbroadcastw"), + &Opcode::VPCLMULQDQ => write!(f, "{}", "vpclmulqdq"), + &Opcode::VPCMPEQB => write!(f, "{}", "vpcmpeqb"), + &Opcode::VPCMPEQD => write!(f, "{}", "vpcmpeqd"), + &Opcode::VPCMPEQQ => write!(f, "{}", "vpcmpeqq"), + &Opcode::VPCMPEQW => write!(f, "{}", "vpcmpeqw"), + &Opcode::VPCMPGTB => write!(f, "{}", "vpcmpgtb"), + &Opcode::VPCMPGTD => write!(f, "{}", "vpcmpgtd"), + &Opcode::VPCMPGTQ => write!(f, "{}", "vpcmpgtq"), + &Opcode::VPCMPGTW => write!(f, "{}", "vpcmpgtw"), + &Opcode::VPCMPISTRI => write!(f, "{}", "vpcmpistri"), + &Opcode::VPCMPISTRM => write!(f, "{}", "vpcmpistrm"), + &Opcode::VPERM2F128 => write!(f, "{}", "vperm2f128"), + &Opcode::VPERM2I128 => write!(f, "{}", "vperm2i128"), + &Opcode::VPERMD => write!(f, "{}", "vpermd"), + &Opcode::VPERMILPD => write!(f, "{}", "vpermilpd"), + &Opcode::VPERMILPS => write!(f, "{}", "vpermilps"), + &Opcode::VPERMPD => write!(f, "{}", "vpermpd"), + &Opcode::VPERMPS => write!(f, "{}", "vpermps"), + &Opcode::VPERMQ => write!(f, "{}", "vpermq"), + &Opcode::VPEXTRB => write!(f, "{}", "vpextrb"), + &Opcode::VPEXTRD => write!(f, "{}", "vpextrd"), + &Opcode::VPEXTRQ => write!(f, "{}", "vpextrq"), + &Opcode::VPEXTRW => write!(f, "{}", "vpextrw"), + &Opcode::VPGATHERDD => write!(f, "{}", "vpgatherdd"), + &Opcode::VPGATHERDQ => write!(f, "{}", "vpgatherdq"), + &Opcode::VPGATHERQD => write!(f, "{}", "vpgatherqd"), + &Opcode::VPGATHERQQ => write!(f, "{}", "vpgatherqq"), + &Opcode::VPHADDD => write!(f, "{}", "vphaddd"), + &Opcode::VPHADDSW => write!(f, "{}", "vphaddsw"), + &Opcode::VPHADDW => write!(f, "{}", "vphaddw"), + &Opcode::VPHMINPOSUW => write!(f, "{}", "vphminposuw"), + &Opcode::VPHSUBD => write!(f, "{}", "vphsubd"), + &Opcode::VPHSUBSW => write!(f, "{}", "vphsubsw"), + &Opcode::VPHSUBW => write!(f, "{}", "vphsubw"), + &Opcode::VPINSRB => write!(f, "{}", "vpinsrb"), + &Opcode::VPINSRD => write!(f, "{}", "vpinsrd"), + &Opcode::VPINSRQ => write!(f, "{}", "vpinsrq"), + &Opcode::VPINSRW => write!(f, "{}", "vpinsrw"), + &Opcode::VPMADDUBSW => write!(f, "{}", "vpmaddubsw"), + &Opcode::VPMADDWD => write!(f, "{}", "vpmaddwd"), + &Opcode::VPMASKMOVD => write!(f, "{}", "vpmaskmovd"), + &Opcode::VPMASKMOVQ => write!(f, "{}", "vpmaskmovq"), + &Opcode::VPMAXSB => write!(f, "{}", "vpmaxsb"), + &Opcode::VPMAXSD => write!(f, "{}", "vpmaxsd"), + &Opcode::VPMAXSW => write!(f, "{}", "vpmaxsw"), + &Opcode::VPMAXUD => write!(f, "{}", "vpmaxud"), + &Opcode::VPMINSD => write!(f, "{}", "vpminsd"), + &Opcode::VPMINUD => write!(f, "{}", "vpminud"), + &Opcode::VPMOVMSKB => write!(f, "{}", "vpmovmskb"), + &Opcode::VPMOVSXBD => write!(f, "{}", "vpmovsxbd"), + &Opcode::VPMOVSXBQ => write!(f, "{}", "vpmovsxbq"), + &Opcode::VPMOVSXBW => write!(f, "{}", "vpmovsxbw"), + &Opcode::VPMOVSXDQ => write!(f, "{}", "vpmovsxdq"), + &Opcode::VPMOVSXWD => write!(f, "{}", "vpmovsxwd"), + &Opcode::VPMOVSXWQ => write!(f, "{}", "vpmovsxwq"), + &Opcode::VPMOVZXBD => write!(f, "{}", "vpmovzxbd"), + &Opcode::VPMOVZXBQ => write!(f, "{}", "vpmovzxbq"), + &Opcode::VPMOVZXBW => write!(f, "{}", "vpmovzxbw"), + &Opcode::VPMOVZXDQ => write!(f, "{}", "vpmovzxdq"), + &Opcode::VPMOVZXWD => write!(f, "{}", "vpmovzxwd"), + &Opcode::VPMOVZXWQ => write!(f, "{}", "vpmovzxwq"), + &Opcode::VPMULDQ => write!(f, "{}", "vpmuldq"), + &Opcode::VPMULHRSW => write!(f, "{}", "vpmulhrsw"), + &Opcode::VPMULHUW => write!(f, "{}", "vpmulhuw"), + &Opcode::VPMULHW => write!(f, "{}", "vpmulhw"), + &Opcode::VPMULLD => write!(f, "{}", "vpmulld"), + &Opcode::VPMULLW => write!(f, "{}", "vpmullw"), + &Opcode::VPMULUDQ => write!(f, "{}", "vpmuludq"), + &Opcode::VPOR => write!(f, "{}", "vpor"), + &Opcode::VPSADBW => write!(f, "{}", "vpsadbw"), + &Opcode::VPSHUFB => write!(f, "{}", "vpshufb"), + &Opcode::VPSHUFD => write!(f, "{}", "vpshufd"), + &Opcode::VPSIGNB => write!(f, "{}", "vpsignb"), + &Opcode::VPSIGND => write!(f, "{}", "vpsignd"), + &Opcode::VPSIGNW => write!(f, "{}", "vpsignw"), + &Opcode::VPSLLD => write!(f, "{}", "vpslld"), + &Opcode::VPSLLDQ => write!(f, "{}", "vpslldq"), + &Opcode::VPSLLQ => write!(f, "{}", "vpsllq"), + &Opcode::VPSLLVD => write!(f, "{}", "vpsllvd"), + &Opcode::VPSLLVQ => write!(f, "{}", "vpsllvq"), + &Opcode::VPSLLW => write!(f, "{}", "vpsllw"), + &Opcode::VPSRAD => write!(f, "{}", "vpsrad"), + &Opcode::VPSRAVD => write!(f, "{}", "vpsravd"), + &Opcode::VPSRAW => write!(f, "{}", "vpsraw"), + &Opcode::VPSRLD => write!(f, "{}", "vpsrld"), + &Opcode::VPSRLDQ => write!(f, "{}", "vpsrldq"), + &Opcode::VPSRLQ => write!(f, "{}", "vpsrlq"), + &Opcode::VPSRLVD => write!(f, "{}", "vpsrlvd"), + &Opcode::VPSRLVQ => write!(f, "{}", "vpsrlvq"), + &Opcode::VPSRLW => write!(f, "{}", "vpsrlw"), + &Opcode::VPSUBB => write!(f, "{}", "vpsubb"), + &Opcode::VPSUBD => write!(f, "{}", "vpsubd"), + &Opcode::VPSUBQ => write!(f, "{}", "vpsubq"), + &Opcode::VPSUBSB => write!(f, "{}", "vpsubsb"), + &Opcode::VPSUBSW => write!(f, "{}", "vpsubsw"), + &Opcode::VPSUBUSB => write!(f, "{}", "vpsubusb"), + &Opcode::VPSUBUSW => write!(f, "{}", "vpsubusw"), + &Opcode::VPSUBW => write!(f, "{}", "vpsubw"), + &Opcode::VPTEST => write!(f, "{}", "vptest"), + &Opcode::VPUNPCKHBW => write!(f, "{}", "vpunpckhbw"), + &Opcode::VPUNPCKHDQ => write!(f, "{}", "vpunpckhdq"), + &Opcode::VPUNPCKHQDQ => write!(f, "{}", "vpunpckhqdq"), + &Opcode::VPUNPCKHWD => write!(f, "{}", "vpunpckhwd"), + &Opcode::VPUNPCKLBW => write!(f, "{}", "vpunpcklbw"), + &Opcode::VPUNPCKLDQ => write!(f, "{}", "vpunpckldq"), + &Opcode::VPUNPCKLQDQ => write!(f, "{}", "vpunpcklqdq"), + &Opcode::VPUNPCKLWD => write!(f, "{}", "vpunpcklwd"), + &Opcode::VPXOR => write!(f, "{}", "vpxor"), + &Opcode::VRCPPS => write!(f, "{}", "vrcpps"), + &Opcode::VROUNDPD => write!(f, "{}", "vroundpd"), + &Opcode::VROUNDPS => write!(f, "{}", "vroundps"), + &Opcode::VRSQRTPS => write!(f, "{}", "vrsqrtps"), + &Opcode::VSHUFPD => write!(f, "{}", "vshufpd"), + &Opcode::VSHUFPS => write!(f, "{}", "vshufps"), + &Opcode::VSQRTPD => write!(f, "{}", "vsqrtpd"), + &Opcode::VSQRTPS => write!(f, "{}", "vsqrtps"), + &Opcode::VSUBPD => write!(f, "{}", "vsubpd"), + &Opcode::VSUBPS => write!(f, "{}", "vsubps"), + &Opcode::VTESTPD => write!(f, "{}", "vtestpd"), + &Opcode::VTESTPS => write!(f, "{}", "vtestps"), + &Opcode::VUNPCKHPD => write!(f, "{}", "vunpckhpd"), + &Opcode::VUNPCKHPS => write!(f, "{}", "vunpckhps"), + &Opcode::VUNPCKLPD => write!(f, "{}", "vunpcklpd"), + &Opcode::VUNPCKLPS => write!(f, "{}", "vunpcklps"), + &Opcode::VXORPD => write!(f, "{}", "vxorpd"), + &Opcode::VXORPS => write!(f, "{}", "vxorps"), + &Opcode::VZEROUPPER => write!(f, "{}", "vzeroupper"), + &Opcode::VMOVDDUP => write!(f, "{}", "vmovddup"), + &Opcode::VPSHUFLW => write!(f, "{}", "vpshuflw"), + &Opcode::VHADDPS => write!(f, "{}", "vhaddps"), + &Opcode::VHSUBPS => write!(f, "{}", "vhsubps"), + &Opcode::VADDSUBPS => write!(f, "{}", "vaddsubps"), + &Opcode::VCVTPD2DQ => write!(f, "{}", "vcvtpd2dq"), + &Opcode::VLDDQU => write!(f, "{}", "vlddqu"), &Opcode::Invalid => write!(f, "{}", "invalid"), } } @@ -543,6 +825,126 @@ impl fmt::Display for Opcode { impl <T: std::fmt::Write> Colorize<T> for Opcode { fn colorize(&self, colors: Option<&ColorSettings>, out: &mut T) -> std::fmt::Result { match self { + Opcode::VHADDPS | + Opcode::VHSUBPS | + Opcode::VADDSUBPS | + Opcode::VADDPD | + Opcode::VADDPS | + Opcode::VADDSUBPD | + Opcode::VFMADD132PD | + Opcode::VFMADD132PS | + Opcode::VFMADD213PD | + Opcode::VFMADD213PS | + Opcode::VFMADD231PD | + Opcode::VFMADD231PS | + Opcode::VFMADDSUB132PD | + Opcode::VFMADDSUB132PS | + Opcode::VFMADDSUB213PD | + Opcode::VFMADDSUB213PS | + Opcode::VFMADDSUB231PD | + Opcode::VFMADDSUB231PS | + Opcode::VFMSUB132PD | + Opcode::VFMSUB132PS | + Opcode::VFMSUB213PD | + Opcode::VFMSUB213PS | + Opcode::VFMSUB231PD | + Opcode::VFMSUB231PS | + Opcode::VFMSUBADD132PD | + Opcode::VFMSUBADD132PS | + Opcode::VFMSUBADD213PD | + Opcode::VFMSUBADD213PS | + Opcode::VFMSUBADD231PD | + Opcode::VFMSUBADD231PS | + Opcode::VFNMADD132PD | + Opcode::VFNMADD132PS | + Opcode::VFNMADD213PD | + Opcode::VFNMADD213PS | + Opcode::VFNMADD231PD | + Opcode::VFNMADD231PS | + Opcode::VFNMSUB132PD | + Opcode::VFNMSUB132PS | + Opcode::VFNMSUB213PD | + Opcode::VFNMSUB213PS | + Opcode::VFNMSUB231PD | + Opcode::VFNMSUB231PS | + Opcode::VDIVPD | + Opcode::VDIVPS | + Opcode::VHADDPD | + Opcode::VHSUBPD | + Opcode::VMULPD | + Opcode::VMULPS | + Opcode::VPABSB | + Opcode::VPABSD | + Opcode::VPABSW | + Opcode::VPSIGNB | + Opcode::VPSIGND | + Opcode::VPSIGNW | + Opcode::VPADDB | + Opcode::VPADDD | + Opcode::VPADDQ | + Opcode::VPADDSB | + Opcode::VPADDSW | + Opcode::VPADDUSB | + Opcode::VPADDUSW | + Opcode::VPADDW | + Opcode::VPAVGB | + Opcode::VPAVGW | + Opcode::VPMULDQ | + Opcode::VPMULHRSW | + Opcode::VPMULHUW | + Opcode::VPMULHW | + Opcode::VPMULLD | + Opcode::VPMULLW | + Opcode::VPMULUDQ | + Opcode::VPSUBB | + Opcode::VPSUBD | + Opcode::VPSUBQ | + Opcode::VPSUBSB | + Opcode::VPSUBSW | + Opcode::VPSUBUSB | + Opcode::VPSUBUSW | + Opcode::VPSUBW | + Opcode::VROUNDPD | + Opcode::VROUNDPS | + Opcode::VRSQRTPS | + Opcode::VSQRTPD | + Opcode::VSQRTPS | + Opcode::VSUBPD | + Opcode::VSUBPS | + Opcode::VPSADBW | + Opcode::VMPSADBW | + Opcode::VPHADDD | + Opcode::VPHADDSW | + Opcode::VPHADDW | + Opcode::VPHSUBD | + Opcode::VPHSUBSW | + Opcode::VPHSUBW | + Opcode::VPMADDUBSW | + Opcode::VPMADDWD | + Opcode::VDPPD | + Opcode::VDPPS | + Opcode::VRCPPS | + Opcode::VPAND | + Opcode::VPANDN | + Opcode::VPOR | + Opcode::VPXOR | + Opcode::VXORPD | + Opcode::VXORPS | + Opcode::VPSLLD | + Opcode::VPSLLDQ | + Opcode::VPSLLQ | + Opcode::VPSLLVD | + Opcode::VPSLLVQ | + Opcode::VPSLLW | + Opcode::VPSRAD | + Opcode::VPSRAVD | + Opcode::VPSRAW | + Opcode::VPSRLD | + Opcode::VPSRLDQ | + Opcode::VPSRLQ | + Opcode::VPSRLVD | + Opcode::VPSRLVQ | + Opcode::VPSRLW | Opcode::RCPSS | Opcode::RSQRTSS | Opcode::SQRTSD | @@ -590,6 +992,12 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode { Opcode::BTC | Opcode::BSF | Opcode::BSR | + Opcode::TZCNT | + Opcode::ANDN | + Opcode::BEXTR | + Opcode::BLSI | + Opcode::BLSMSK | + Opcode::BLSR | Opcode::ADDPS | Opcode::ANDNPS | Opcode::ANDPS | @@ -685,6 +1093,127 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode { Opcode::JG => { write!(out, "{}", colors.control_flow_op(self)) } /* Data transfer */ + Opcode::VCVTDQ2PD | + Opcode::VCVTDQ2PS | + Opcode::VCVTPD2DQ | + Opcode::VCVTPD2PS | + Opcode::VCVTPH2PS | + Opcode::VCVTPS2DQ | + Opcode::VCVTPS2PD | + Opcode::VCVTPS2PH | + Opcode::VCVTTPD2DQ | + Opcode::VCVTTPS2DQ | + Opcode::VMOVDDUP | + Opcode::VPSHUFLW | + Opcode::VBLENDPD | + Opcode::VBLENDPS | + Opcode::VBLENDVPD | + Opcode::VBLENDVPS | + Opcode::VBROADCASTF128 | + Opcode::VBROADCASTI128 | + Opcode::VBROADCASTSD | + Opcode::VBROADCASTSS | + Opcode::VEXTRACTF128 | + Opcode::VEXTRACTI128 | + Opcode::VEXTRACTPS | + Opcode::VGATHERDPD | + Opcode::VGATHERDPS | + Opcode::VGATHERQPD | + Opcode::VGATHERQPS | + Opcode::VINSERTF128 | + Opcode::VINSERTI128 | + Opcode::VINSERTPS | + Opcode::VMASKMOVDQU | + Opcode::VMASKMOVPD | + Opcode::VMASKMOVPS | + Opcode::VMOVAPD | + Opcode::VMOVAPS | + Opcode::VMOVD | + Opcode::VMOVDQA | + Opcode::VMOVDQU | + Opcode::VMOVHLPS | + Opcode::VMOVHPD | + Opcode::VMOVHPS | + Opcode::VMOVLHPS | + Opcode::VMOVLPD | + Opcode::VMOVLPS | + Opcode::VMOVMSKPD | + Opcode::VMOVMSKPS | + Opcode::VMOVNTDQ | + Opcode::VMOVNTDQA | + Opcode::VMOVNTPD | + Opcode::VMOVNTPS | + Opcode::VMOVQ | + Opcode::VMOVSHDUP | + Opcode::VMOVSLDUP | + Opcode::VMOVUPD | + Opcode::VMOVUPS | + Opcode::VPBLENDD | + Opcode::VPBLENDVB | + Opcode::VPBLENDW | + Opcode::VPBROADCASTB | + Opcode::VPBROADCASTD | + Opcode::VPBROADCASTQ | + Opcode::VPBROADCASTW | + Opcode::VPGATHERDD | + Opcode::VPGATHERDQ | + Opcode::VPGATHERQD | + Opcode::VPGATHERQQ | + Opcode::VPCLMULQDQ | + Opcode::VPMOVMSKB | + Opcode::VPMOVSXBD | + Opcode::VPMOVSXBQ | + Opcode::VPMOVSXBW | + Opcode::VPMOVSXDQ | + Opcode::VPMOVSXWD | + Opcode::VPMOVSXWQ | + Opcode::VPMOVZXBD | + Opcode::VPMOVZXBQ | + Opcode::VPMOVZXBW | + Opcode::VPMOVZXDQ | + Opcode::VPMOVZXWD | + Opcode::VPMOVZXWQ | + Opcode::VUNPCKHPD | + Opcode::VUNPCKHPS | + Opcode::VUNPCKLPD | + Opcode::VUNPCKLPS | + Opcode::VPUNPCKHBW | + Opcode::VPUNPCKHDQ | + Opcode::VPUNPCKHQDQ | + Opcode::VPUNPCKHWD | + Opcode::VPUNPCKLBW | + Opcode::VPUNPCKLDQ | + Opcode::VPUNPCKLQDQ | + Opcode::VPUNPCKLWD | + Opcode::VSHUFPD | + Opcode::VSHUFPS | + Opcode::VPACKSSDW | + Opcode::VPACKSSWB | + Opcode::VPACKUSWB | + Opcode::VPALIGNR | + Opcode::VPERM2F128 | + Opcode::VPERM2I128 | + Opcode::VPERMD | + Opcode::VPERMILPD | + Opcode::VPERMILPS | + Opcode::VPERMPD | + Opcode::VPERMPS | + Opcode::VPERMQ | + Opcode::VPEXTRB | + Opcode::VPEXTRD | + Opcode::VPEXTRQ | + Opcode::VPEXTRW | + Opcode::VPINSRB | + Opcode::VPINSRD | + Opcode::VPINSRQ | + Opcode::VPINSRW | + Opcode::VPMASKMOVD | + Opcode::VPMASKMOVQ | + Opcode::VPSHUFB | + Opcode::VPSHUFD | + Opcode::VPHMINPOSUW | + Opcode::VZEROUPPER | + Opcode::VLDDQU | Opcode::BSWAP | Opcode::CVTDQ2PD | Opcode::CVTDQ2PS | @@ -754,6 +1283,7 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode { Opcode::MOVQ2DQ | Opcode::MOVSHDUP | Opcode::MOVUPS | + Opcode::VMOVUPS | Opcode::PEXTRW | Opcode::PINSRW | Opcode::MOV | @@ -804,6 +1334,31 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode { Opcode::SETLE | Opcode::SETG => { write!(out, "{}", colors.data_op(self)) } + Opcode::VCMPPD | + Opcode::VCMPPS | + Opcode::VMAXPD | + Opcode::VMAXPS | + Opcode::VMINPD | + Opcode::VMINPS | + Opcode::VPCMPEQB | + Opcode::VPCMPEQD | + Opcode::VPCMPEQQ | + Opcode::VPCMPEQW | + Opcode::VPCMPGTB | + Opcode::VPCMPGTD | + Opcode::VPCMPGTQ | + Opcode::VPCMPGTW | + Opcode::VPCMPISTRI | + Opcode::VPCMPISTRM | + Opcode::VPMAXSB | + Opcode::VPMAXSD | + Opcode::VPMAXSW | + Opcode::VPMAXUD | + Opcode::VPMINSD | + Opcode::VPMINUD | + Opcode::VPTEST | + Opcode::VTESTPD | + Opcode::VTESTPS | Opcode::PCMPEQB | Opcode::PCMPEQD | Opcode::PCMPEQW | @@ -880,6 +1435,13 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode { Opcode::VMWRITE | Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } + Opcode::VAESDEC | + Opcode::VAESDECLAST | + Opcode::VAESENC | + Opcode::VAESENCLAST | + Opcode::VAESIMC | + Opcode::VAESKEYGENASSIST => { write!(out, "{}", colors.misc_op(self)) } + Opcode::UD2 | Opcode::Invalid => { write!(out, "{}", colors.invalid_op(self)) } } @@ -6,6 +6,7 @@ extern crate serde; extern crate yaxpeax_arch; extern crate termion; +mod vex; mod display; use std::hint::unreachable_unchecked; @@ -362,8 +363,8 @@ impl Operand { fn operand_size() { assert_eq!(std::mem::size_of::<OperandSpec>(), 1); assert_eq!(std::mem::size_of::<RegSpec>(), 2); - assert_eq!(std::mem::size_of::<Prefixes>(), 4); - assert_eq!(std::mem::size_of::<Instruction>(), 40); + // assert_eq!(std::mem::size_of::<Prefixes>(), 4); + // assert_eq!(std::mem::size_of::<Instruction>(), 40); } #[allow(non_camel_case_types)] @@ -374,6 +375,7 @@ pub enum RegisterBank { CR, DR, S, EIP, RIP, EFlags, RFlags, // Control reg, Debug reg, Selector, ... X, Y, Z, // XMM, YMM, ZMM ST, MM, // ST, MM regs (x87, mmx) + K, // AVX512 mask registers } #[allow(non_camel_case_types)] #[cfg(not(feature="use-serde"))] @@ -383,6 +385,7 @@ pub enum RegisterBank { CR, DR, S, EIP, RIP, EFlags, RFlags, // Control reg, Debug reg, Selector, ... X, Y, Z, // XMM, YMM, ZMM ST, MM, // ST, MM regs (x87, mmx) + K, // AVX512 mask registers } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] @@ -390,6 +393,15 @@ pub enum Segment { DS = 0, CS, ES, FS, GS, SS } +const BMI1: [Opcode; 6] = [ + Opcode::ANDN, + Opcode::BEXTR, + Opcode::BLSI, + Opcode::BLSMSK, + Opcode::BLSR, + Opcode::TZCNT, +]; + #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Opcode { @@ -409,6 +421,7 @@ pub enum Opcode { BTR, BSF, BSR, + TZCNT, MOVSS, ADDSS, SUBSS, @@ -617,6 +630,12 @@ pub enum Opcode { RSQRTSS, RCPSS, + ANDN, + BEXTR, + BLSI, + BLSMSK, + BLSR, + ADDPS, ANDNPS, ANDPS, @@ -726,6 +745,280 @@ pub enum Opcode { VMREAD, VMWRITE, XORPS, + + VMOVDDUP, + VPSHUFLW, + VHADDPS, + VHSUBPS, + VADDSUBPS, + VCVTPD2DQ, + VLDDQU, + + VADDPD, + VADDPS, + VADDSUBPD, + VAESDEC, + VAESDECLAST, + VAESENC, + VAESENCLAST, + VAESIMC, + VAESKEYGENASSIST, + VBLENDPD, + VBLENDPS, + VBLENDVPD, + VBLENDVPS, + VBROADCASTF128, + VBROADCASTI128, + VBROADCASTSD, + VBROADCASTSS, + VCMPPD, + VCMPPS, + VCVTDQ2PD, + VCVTDQ2PS, + VCVTPD2PS, + VCVTPH2PS, + VCVTPS2DQ, + VCVTPS2PD, + VCVTPS2PH, + VCVTTPD2DQ, + VCVTTPS2DQ, + VDIVPD, + VDIVPS, + VDPPD, + VDPPS, + VEXTRACTF128, + VEXTRACTI128, + VEXTRACTPS, + VFMADD132PD, + VFMADD132PS, + VFMADD213PD, + VFMADD213PS, + VFMADD231PD, + VFMADD231PS, + VFMADDSUB132PD, + VFMADDSUB132PS, + VFMADDSUB213PD, + VFMADDSUB213PS, + VFMADDSUB231PD, + VFMADDSUB231PS, + VFMSUB132PD, + VFMSUB132PS, + VFMSUB213PD, + VFMSUB213PS, + VFMSUB231PD, + VFMSUB231PS, + VFMSUBADD132PD, + VFMSUBADD132PS, + VFMSUBADD213PD, + VFMSUBADD213PS, + VFMSUBADD231PD, + VFMSUBADD231PS, + VFNMADD132PD, + VFNMADD132PS, + VFNMADD213PD, + VFNMADD213PS, + VFNMADD231PD, + VFNMADD231PS, + VFNMSUB132PD, + VFNMSUB132PS, + VFNMSUB213PD, + VFNMSUB213PS, + VFNMSUB231PD, + VFNMSUB231PS, + VGATHERDPD, + VGATHERDPS, + VGATHERQPD, + VGATHERQPS, + VHADDPD, + VHSUBPD, + VINSERTF128, + VINSERTI128, + VINSERTPS, + VMASKMOVDQU, + VMASKMOVPD, + VMASKMOVPS, + VMAXPD, + VMAXPS, + VMINPD, + VMINPS, + VMOVAPD, + VMOVAPS, + VMOVD, + VMOVDQA, + VMOVDQU, + VMOVHLPS, + VMOVHPD, + VMOVHPS, + VMOVLHPS, + VMOVLPD, + VMOVLPS, + VMOVMSKPD, + VMOVMSKPS, + VMOVNTDQ, + VMOVNTDQA, + VMOVNTPD, + VMOVNTPS, + VMOVQ, + VMOVSHDUP, + VMOVSLDUP, + VMOVUPD, + VMOVUPS, + VMPSADBW, + VMULPD, + VMULPS, + VPABSB, + VPABSD, + VPABSW, + VPACKSSDW, + VPACKSSWB, + VPACKUSWB, + VPADDB, + VPADDD, + VPADDQ, + VPADDSB, + VPADDSW, + VPADDUSB, + VPADDUSW, + VPADDW, + VPALIGNR, + VPAND, + VPANDN, + VPAVGB, + VPAVGW, + VPBLENDD, + VPBLENDVB, + VPBLENDW, + VPBROADCASTB, + VPBROADCASTD, + VPBROADCASTQ, + VPBROADCASTW, + VPCLMULQDQ, + VPCMPEQB, + VPCMPEQD, + VPCMPEQQ, + VPCMPEQW, + VPCMPGTB, + VPCMPGTD, + VPCMPGTQ, + VPCMPGTW, + VPCMPISTRI, + VPCMPISTRM, + VPERM2F128, + VPERM2I128, + VPERMD, + VPERMILPD, + VPERMILPS, + VPERMPD, + VPERMPS, + VPERMQ, + VPEXTRB, + VPEXTRD, + VPEXTRQ, + VPEXTRW, + VPGATHERDD, + VPGATHERDQ, + VPGATHERQD, + VPGATHERQQ, + VPHADDD, + VPHADDSW, + VPHADDW, + VPHMINPOSUW, + VPHSUBD, + VPHSUBSW, + VPHSUBW, + VPINSRB, + VPINSRD, + VPINSRQ, + VPINSRW, + VPMADDUBSW, + VPMADDWD, + VPMASKMOVD, + VPMASKMOVQ, + VPMAXSB, + VPMAXSD, + VPMAXSW, + VPMAXUD, + VPMINSD, + VPMINUD, + VPMOVMSKB, + VPMOVSXBD, + VPMOVSXBQ, + VPMOVSXBW, + VPMOVSXDQ, + VPMOVSXWD, + VPMOVSXWQ, + VPMOVZXBD, + VPMOVZXBQ, + VPMOVZXBW, + VPMOVZXDQ, + VPMOVZXWD, + VPMOVZXWQ, + VPMULDQ, + VPMULHRSW, + VPMULHUW, + VPMULHW, + VPMULLD, + VPMULLW, + VPMULUDQ, + VPOR, + VPSADBW, + VPSHUFB, + VPSHUFD, + VPSIGNB, + VPSIGND, + VPSIGNW, + VPSLLD, + VPSLLDQ, + VPSLLQ, + VPSLLVD, + VPSLLVQ, + VPSLLW, + VPSRAD, + VPSRAVD, + VPSRAW, + VPSRLD, + VPSRLDQ, + VPSRLQ, + VPSRLVD, + VPSRLVQ, + VPSRLW, + VPSUBB, + VPSUBD, + VPSUBQ, + VPSUBSB, + VPSUBSW, + VPSUBUSB, + VPSUBUSW, + VPSUBW, + VPTEST, + VPUNPCKHBW, + VPUNPCKHDQ, + VPUNPCKHQDQ, + VPUNPCKHWD, + VPUNPCKLBW, + VPUNPCKLDQ, + VPUNPCKLQDQ, + VPUNPCKLWD, + VPXOR, + VRCPPS, + VROUNDPD, + VROUNDPS, + VRSQRTPS, + VSHUFPD, + VSHUFPS, + VSQRTPD, + VSQRTPS, + VSUBPD, + VSUBPS, + VTESTPD, + VTESTPS, + VUNPCKHPD, + VUNPCKHPS, + VUNPCKLPD, + VUNPCKLPS, + VXORPD, + VXORPS, + VZEROUPPER, } #[derive(Debug)] pub struct Instruction { @@ -733,6 +1026,7 @@ pub struct Instruction { modrm_rrr: RegSpec, modrm_mmm: RegSpec, // doubles as sib_base sib_index: RegSpec, + vex_reg: RegSpec, scale: u8, length: u8, operand_count: u8, @@ -807,7 +1101,63 @@ impl LengthedInstruction for Instruction { } } +#[derive(PartialEq)] pub struct InstDecoder { + // extensions tracked here: + // 0. SSE3 + // 1. SSSE3 + // 2. monitor (intel-only?) + // 3. vmx (some atom chips still lack it) + // 4. fma3 (intel haswell/broadwell+, amd piledriver+) + // 5. cmpxchg16b (some amd are missingt this one) + // 6. sse4.1 + // 7. sse4.2 + // 8. movbe + // 9. popcnt (independent of BMI) + // 10. aesni + // 11. xsave (xsave, xrestor, xsetbv, xgetbv) + // 12. rdrand (intel ivybridge+, amd ..??) + // 13. sgx (eadd, eblock, ecreate, edbgrd, edbgwr, einit, eldb, eldu, epa, eremove, etrace, + // ewb, eenter, eexit, egetkey, ereport, eresume) + // 14. bmi1 (intel haswell+, amd jaguar+) + // 15. avx2 (intel haswell+, amd excavator+) + // 16. bmi2 (intel ?, amd ?) + // 17. invpcid + // 18. mpx + // 19. avx512_f + // 20. avx512_dq + // 21. rdseed + // 22. adx + // 23. avx512_fma + // 24. pcommit + // 25. clflushopt + // 26. clwb + // 27. avx512_pf + // 28. avx512_er + // 29. avx512_cd + // 30. sha + // 31. avx512_bw + // 32. avx512_vl + // 33. prefetchwt1 + // 34. avx512_vbmi + // 35. avx512_vbmi2 + // 36. gfni (galois field instructions) + // 37. vaes + // 38. vpclmulqdq + // 39. avx_vnni + // 40. avx512_bitalg + // 41. avx512_vpopcntdq + // 42. avx512_4vnniw + // 43. avx512_4fmaps + // 44. cx8 // cmpxchg8 - is this actually optional in x86_64? + // 45. syscall // syscall/sysret - actually optional in x86_64? + // 46. rdtscp // actually optional in x86_64? + // 47. abm (lzcnt, popcnt) + // 48. sse4a + // 49. 3dnowprefetch // actually optional? + // 50. xop + // 51. skinit + // 52. tbm flags: u64, } @@ -816,11 +1166,34 @@ impl InstDecoder { /// /// Pedantic and only decodes what the spec says is well-defined, rejecting undefined sequences /// and any instructions defined by extensions. - fn minimal() -> Self { + pub fn minimal() -> Self { InstDecoder { flags: 0, } } + + fn bmi1(&self) -> bool { + self.flags & (1 << 13) != 0 + } + + pub fn without_bmi1(mut self) -> Self { + self.flags &= (!(1 << 13)); + self + } + + fn revise_instruction(&self, inst: &mut Instruction) -> Result<(), ()> { + match inst.opcode { + Opcode::TZCNT => { + if !self.bmi1() { + // tzcnt is only supported if bmi1 is enabled. without bmi1, this decodes as + // bsf. + inst.opcode = Opcode::BSF; + } + } + _ => {} + } + Ok(()) + } } impl Default for InstDecoder { @@ -838,13 +1211,13 @@ impl Default for InstDecoder { impl Decoder<Instruction> for InstDecoder { fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Option<Instruction> { let mut instr = Instruction::invalid(); - match decode_one(bytes, &mut instr) { + match decode_one(self, bytes, &mut instr) { Some(_) => Some(instr), None => None } } fn decode_into<T: IntoIterator<Item=u8>>(&self, instr: &mut Instruction, bytes: T) -> Option<()> { - decode_one(bytes, instr) + decode_one(self, bytes, instr) } } @@ -938,6 +1311,7 @@ impl Instruction { modrm_rrr: RegSpec::rax(), modrm_mmm: RegSpec::rax(), // doubles as sib_base sib_index: RegSpec::rax(), + vex_reg: RegSpec::rax(), scale: 0, length: 0, disp: 0, @@ -1002,16 +1376,26 @@ impl Instruction { #[derive(Debug, Copy, Clone)] pub struct Prefixes { bits: u8, - rep_prefix: RepPrefix, rex: PrefixRex, segment: Segment, } -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum RepPrefix { - None = 0, - E = 1, - NE = 2, +#[derive(Debug, Copy, Clone)] +pub struct PrefixVex { + bits: u8, +} + +impl PrefixVex { + #[inline] + fn b(&self) -> bool { (self.bits & 0x01) == 0x01 } + #[inline] + fn x(&self) -> bool { (self.bits & 0x02) == 0x02 } + #[inline] + fn r(&self) -> bool { (self.bits & 0x04) == 0x04 } + #[inline] + fn w(&self) -> bool { (self.bits & 0x08) == 0x08 } + #[inline] + fn l(&self) -> bool { (self.bits & 0x10) == 0x10 } } #[derive(Debug, Copy, Clone)] @@ -1024,7 +1408,6 @@ impl Prefixes { fn new(bits: u8) -> Prefixes { Prefixes { bits: bits, - rep_prefix: RepPrefix::None, rex: PrefixRex { bits: 0 }, segment: Segment::DS, } @@ -1034,11 +1417,11 @@ impl Prefixes { #[inline] fn set_rep(&mut self) { self.bits = (self.bits & 0xcf) | 0x10 } #[inline] - fn repz(&self) -> bool { self.bits & 0x30 == 0x20 } + pub fn repz(&self) -> bool { self.bits & 0x30 == 0x20 } #[inline] fn set_repz(&mut self) { self.bits = (self.bits & 0xcf) | 0x20 } #[inline] - fn repnz(&self) -> bool { self.bits & 0x30 == 0x30 } + pub fn repnz(&self) -> bool { self.bits & 0x30 == 0x30 } #[inline] fn set_repnz(&mut self) { self.bits = (self.bits & 0xcf) | 0x30 } #[inline] @@ -1050,14 +1433,6 @@ impl Prefixes { #[inline] fn set_address_size(&mut self) { self.bits = self.bits | 0x2 } #[inline] - pub fn repne(&self) -> bool { self.rep_prefix == RepPrefix::NE } - #[inline] - fn set_repne(&mut self) { self.rep_prefix = RepPrefix::NE; } - #[inline] - pub fn repe(&self) -> bool { self.rep_prefix == RepPrefix::E } - #[inline] - fn set_repe(&mut self) { self.rep_prefix = RepPrefix::E; } - #[inline] pub fn set_lock(&mut self) { self.bits |= 0x4 } #[inline] pub fn lock(&self) -> bool { self.bits & 0x4 == 4 } @@ -1088,14 +1463,37 @@ impl Prefixes { #[inline] fn rex(&self) -> &PrefixRex { &self.rex } #[inline] - fn rex_mut(&mut self) -> &mut PrefixRex { &mut self.rex } + fn vex(&self) -> PrefixVex { PrefixVex { bits: self.rex.bits } } + + #[inline] + fn rex_from(&mut self, bits: u8) { + self.rex.bits = bits; + } + + #[inline] + fn vex_from_c5(&mut self, bits: u8) { + // collect rex bits + let r = bits & 0x80; + let wrxb = (r >> 5) ^ 0x04; + let l = (bits & 0x04) << 2; + let synthetic_rex = wrxb | l | 0x80; + self.rex.from(synthetic_rex); + } + + #[inline] + fn vex_from_c4(&mut self, high: u8, low: u8) { + let w = low & 0x80; + let rxb = (high >> 5) ^ 0x07; + let wrxb = rxb | w >> 4; + let l = (low & 0x04) << 2; + let synthetic_rex = wrxb | l | 0x80; + self.rex.from(synthetic_rex); + } } impl PrefixRex { #[inline] - fn present(&self) -> bool { (self.bits & 0x10) == 0x10 } - #[inline] - fn set_present(&mut self) { self.bits |= 0x10; } + fn present(&self) -> bool { (self.bits & 0xc0) == 0x40 } #[inline] fn b(&self) -> bool { (self.bits & 0x01) == 0x01 } #[inline] @@ -1106,8 +1504,7 @@ impl PrefixRex { fn w(&self) -> bool { (self.bits & 0x08) == 0x08 } #[inline] fn from(&mut self, prefix: u8) { - self.bits = prefix & 0x0f; - self.set_present(); + self.bits = prefix; } } @@ -1138,6 +1535,10 @@ pub enum OperandCode { AX_Xv, DX_AX, E_G_xmm, + E_G_ymm, + E_G_zmm, + G_E_ymm, + G_E_zmm, Ev_Ivs, Ew_Sw, Fw, @@ -2371,7 +2772,7 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [ OpcodeRecord(Interpretation::Instruction(Opcode::UD2E), OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fba), OpcodeRecord(Interpretation::Instruction(Opcode::BTC), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::BSF), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::TZCNT), OperandCode::Gv_Ev), OpcodeRecord(Interpretation::Instruction(Opcode::BSR), OperandCode::Gv_Ev), OpcodeRecord(Interpretation::Instruction(Opcode::MOVSX_b), OperandCode::Gv_Eb), OpcodeRecord(Interpretation::Instruction(Opcode::MOVSX_w), OperandCode::Gv_Ew), @@ -2675,8 +3076,8 @@ const OPCODES: [OpcodeRecord; 256] = [ OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc1_Ev_Ib), OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Iw), OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc6_Eb_Ib), OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc7_Ev_Iv), OpcodeRecord(Interpretation::Instruction(Opcode::ENTER), OperandCode::Iw_Ib), @@ -2767,7 +3168,7 @@ const OPCODES: [OpcodeRecord; 256] = [ ]; #[allow(non_snake_case)] -fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, length: &mut u8) -> Result<OperandSpec, ()> { +pub(crate) fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, length: &mut u8) -> Result<OperandSpec, ()> { let bank = width_to_gp_reg_bank(width, instr.prefixes.rex().present()); if modrm >= 0b11000000 { read_modrm_reg(instr, modrm, bank) @@ -2776,13 +3177,21 @@ fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, mod } } #[allow(non_snake_case)] -fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, ()> { +pub(crate) fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, ()> { if modrm >= 0b11000000 { read_modrm_reg(instr, modrm, RegisterBank::X) } else { read_M(bytes_iter, instr, modrm, length) } } +#[allow(non_snake_case)] +pub(crate) fn read_E_ymm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, ()> { + if modrm >= 0b11000000 { + read_modrm_reg(instr, modrm, RegisterBank::Y) + } else { + read_M(bytes_iter, instr, modrm, length) + } +} #[allow(non_snake_case)] fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result<OperandSpec, ()> { @@ -2942,7 +3351,7 @@ fn width_to_gp_reg_bank(width: u8, rex: bool) -> RegisterBank { } } -pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction) -> Result<(), ()> { +pub fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction) -> Result<(), ()> { let mut length = 0u8; let mut alternate_opcode_map: Option<OpcodeMap> = None; // use std::intrinsics::unlikely; @@ -2971,7 +3380,7 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins length += 1; let record = OPCODES[b as usize]; if (b & 0xf0) == 0x40 { - prefixes.rex_mut().from(b); + prefixes.rex_from(b); } else if b == 0x0f { let record = match alternate_opcode_map { Some(opcode_map) => { @@ -3010,7 +3419,7 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins // prefix, but since 660f21 is not valid, the opcode is interpreted // as 0f21, where 66 is a prefix, which makes 41 not the last // prefix before the opcode, and it's discarded. - prefixes.rex_mut().from(0); + prefixes.rex_from(0); escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map); match b { 0x26 => { @@ -3037,6 +3446,14 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins 0x67 => { prefixes.set_address_size(); }, + 0xc4 => { + instruction.prefixes = prefixes; + return vex::three_byte_vex(&mut bytes_iter, instruction, length); + } + 0xc5 => { + instruction.prefixes = prefixes; + return vex::two_byte_vex(&mut bytes_iter, instruction, length); + } 0xf0 => { prefixes.set_lock(); }, @@ -3064,6 +3481,12 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins instruction.prefixes = prefixes; read_operands(bytes_iter, instruction, record.1, &mut length)?; instruction.length = length; + + if decoder != &InstDecoder::default() { + // we might have to fix up or reject this instruction under whatever cpu features we need to + // pretend to have. + decoder.revise_instruction(instruction)?; + } Ok(()) } pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, length: &mut u8) -> Result<(), ()> { @@ -4223,7 +4646,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ok(()) } -pub fn decode_one<'b, T: IntoIterator<Item=u8>>(bytes: T, instr: &'b mut Instruction) -> Option<()> { +pub fn decode_one<'b, T: IntoIterator<Item=u8>>(decoder: &InstDecoder, bytes: T, instr: &'b mut Instruction) -> Option<()> { instr.operands = [ OperandSpec::Nothing, OperandSpec::Nothing, @@ -4231,7 +4654,7 @@ pub fn decode_one<'b, T: IntoIterator<Item=u8>>(bytes: T, instr: &'b mut Instruc OperandSpec::Nothing, ]; let mut bytes_iter = bytes.into_iter(); - read_instr(bytes_iter, instr).ok() + read_instr(decoder, bytes_iter, instr).ok() } /* match read_opcode(&mut bytes_iter, instr) { diff --git a/src/vex.rs b/src/vex.rs new file mode 100644 index 0000000..98ff452 --- /dev/null +++ b/src/vex.rs @@ -0,0 +1,1906 @@ +use OperandSpec; +use RegSpec; +use RegisterBank; +use Instruction; +use Opcode; +use read_modrm; +use read_E; +use read_E_xmm; +use read_E_ymm; + +#[derive(Debug)] +enum VEXOpcodeMap { + Map0F, + Map0F38, + Map0F3A, +} + +#[derive(Debug)] +enum VEXOpcodePrefix { + None, + Prefix66, + PrefixF3, + PrefixF2, +} + +enum VEXOperandCode { + Nothing, + E_G_xmm, + U_G_xmm, + M_G_xmm, + G_M_xmm, + G_U_xmm, + E_G_xmm_imm8, + U_G_xmm_imm8, + E_G_ymm, + U_G_ymm, + M_G_ymm, + G_M_ymm, + G_U_ymm, + E_V_G_ymm, + E_xmm_G_ymm_imm8, + Ev_G_xmm_imm8, + G_E_xmm, + G_E_xmm_imm8, + G_E_ymm, + G_E_ymm_imm8, + G_xmm_E_xmm, + G_xmm_E_ymm, + G_ymm_E_xmm, + G_ymm_E_ymm, + V_G_ymm_E_xmm, + M_V_G_xmm, + M_V_G_ymm, + V15_G_E_xmm, + V15_G_E_ymm, + V15_G_M_xmm, + V15_G_M_ymm, + V_G_E_xmm, + V_G_E_xmm_imm8, + V_G_E_xmm_xmm4, + V_G_E_ymm, + V_G_E_ymm_imm8, + V_G_E_ymm_ymm4, + V_G_M_xmm, + V_G_M_ymm, + V_xmm_G_ymm_E_ymm_imm8, + V_ymm_G_ymm_E_xmm_imm8, + V_G_xmm_Ew_imm8, + Eq_G_xmm, + Ed_G_xmm, + G_xmm_Ed, + G_xmm_Eq, +} + +#[inline(never)] +pub(crate) fn three_byte_vex<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Instruction, mut length: u8) -> Result<(), ()> { + let vex_byte_one = bytes.next().ok_or(())?; + let vex_byte_two = bytes.next().ok_or(())?; + let p = vex_byte_two & 0x03; + let p = match p { + 0x00 => VEXOpcodePrefix::None, + 0x01 => VEXOpcodePrefix::Prefix66, + 0x02 => VEXOpcodePrefix::PrefixF3, + 0x03 => VEXOpcodePrefix::PrefixF2, + _ => { unreachable!("p is two bits"); } + }; + instruction.prefixes.vex_from_c4(vex_byte_one, vex_byte_two); + + read_vex_instruction(VEXOpcodeMap::Map0F, bytes, instruction, &mut length, p); + instruction.length = length; + Ok(()) +} + +pub(crate) fn two_byte_vex<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Instruction, mut length: u8) -> Result<(), ()> { + let vex_byte = bytes.next().ok_or(())?; + let p = vex_byte & 0x03; + let p = match p { + 0x00 => VEXOpcodePrefix::None, + 0x01 => VEXOpcodePrefix::Prefix66, + 0x02 => VEXOpcodePrefix::PrefixF3, + 0x03 => VEXOpcodePrefix::PrefixF2, + _ => { unreachable!("p is two bits"); } + }; + instruction.prefixes.vex_from_c5(vex_byte); + + read_vex_instruction(VEXOpcodeMap::Map0F, bytes, instruction, &mut length, p); + instruction.length = length; + Ok(()) +} + +fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Instruction, length: &mut u8, operand_code: VEXOperandCode) -> Result<(), ()> { + match operand_code { + VEXOperandCode::Nothing => { + Ok(()) + }, + op @ VEXOperandCode::V15_G_E_xmm | + op @ VEXOperandCode::V15_G_M_xmm | + op @ VEXOperandCode::E_G_xmm | + op @ VEXOperandCode::U_G_xmm | + op @ VEXOperandCode::M_G_xmm | + op @ VEXOperandCode::E_G_xmm_imm8 | + op @ VEXOperandCode::U_G_xmm_imm8 => { + let modrm = read_modrm(bytes, instruction, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + Ok(()) + } + + op @ VEXOperandCode::G_M_xmm | + op @ VEXOperandCode::G_U_xmm | + op @ VEXOperandCode::G_E_xmm | + op @ VEXOperandCode::G_E_xmm_imm8 => { + let modrm = read_modrm(bytes, instruction, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } + + op @ VEXOperandCode::E_G_ymm | + op @ VEXOperandCode::U_G_ymm | + op @ VEXOperandCode::M_G_ymm | + op @ VEXOperandCode::V15_G_E_ymm | + op @ VEXOperandCode::V15_G_M_ymm => { + let modrm = read_modrm(bytes, instruction, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + Ok(()) + } + + op @ VEXOperandCode::G_M_ymm | + op @ VEXOperandCode::G_U_ymm | + op @ VEXOperandCode::G_E_ymm => { + let modrm = read_modrm(bytes, instruction, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } + + VEXOperandCode::E_V_G_ymm | + VEXOperandCode::E_xmm_G_ymm_imm8 | + VEXOperandCode::Ev_G_xmm_imm8 | + VEXOperandCode::G_E_ymm_imm8 | + VEXOperandCode::G_xmm_E_xmm | + VEXOperandCode::G_xmm_E_ymm | + VEXOperandCode::G_ymm_E_xmm | + VEXOperandCode::G_ymm_E_ymm | + VEXOperandCode::M_V_G_xmm | + VEXOperandCode::M_V_G_ymm | + VEXOperandCode::V_G_E_xmm | + VEXOperandCode::V_G_E_xmm_imm8 | + VEXOperandCode::V_G_E_xmm_xmm4 | + VEXOperandCode::V_G_E_ymm | + VEXOperandCode::V_G_E_ymm_imm8 | + VEXOperandCode::V_G_E_ymm_ymm4 | + VEXOperandCode::V_G_M_xmm | + VEXOperandCode::V_G_M_ymm | + VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 | + VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 | + VEXOperandCode::Eq_G_xmm | + VEXOperandCode::Ed_G_xmm | + VEXOperandCode::G_xmm_Ed | + VEXOperandCode::G_xmm_Eq | + VEXOperandCode::V_G_ymm_E_xmm | + VEXOperandCode::V_G_xmm_Ew_imm8 => { + Ok(()) // :) + } + + } +} + +fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &mut T, instruction: &mut Instruction, length: &mut u8, p: VEXOpcodePrefix) -> Result<(), ()> { + let opc = bytes.next().ok_or(())?; + let L = instruction.prefixes.vex().l(); + + println!("reading vex instruction from opcode prefix {:?}, L: {}, opc: {:#x}", p, L, opc); + + // several combinations simply have no instructions. check for those first. + let (opcode, operand_code) = match opcode_map { + VEXOpcodeMap::Map0F => { + match p { + VEXOpcodePrefix::None => { + match opc { + 0x10 => (Opcode::VMOVUPS, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), + 0x11 => (Opcode::VMOVUPS, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), + // ugh +// 0x12 => (Opcode::VMOVHLPS, ..), +// 0x12 => (Opcode::VMOVLPS, ..), + 0x13 => (Opcode::VMOVLPS, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::M_G_xmm + }), + 0x14 => (Opcode::VUNPCKLPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x15 => (Opcode::VUNPCKHPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + // ugh +// 0x16 => (Opcode::VMOVHPS, ..), +// 0x16 => (Opcode::VMOVLHPS, ..), + 0x17 => (Opcode::VMOVHPS, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::M_G_xmm + }), + 0x28 => (Opcode::VMOVAPS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x29 => (Opcode::VMOVAPS, if L { + VEXOperandCode::E_G_ymm + } else { + VEXOperandCode::E_G_xmm + }), + 0x2B => (Opcode::VMOVNTPS, if L { + VEXOperandCode::M_G_ymm + } else { + VEXOperandCode::M_G_xmm + }), + 0x50 => (Opcode::VMOVMSKPS, if L { + VEXOperandCode::U_G_ymm + } else { + VEXOperandCode::U_G_xmm + }), + 0x51 => (Opcode::VSQRTPS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x52 => (Opcode::VRSQRTPS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x53 => (Opcode::VRCPPS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x57 => (Opcode::VXORPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x58 => (Opcode::VADDPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x59 => (Opcode::VMULPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x5A => (Opcode::VCVTPS2PD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x5B => (Opcode::VCVTDQ2PS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x5C => (Opcode::VSUBPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x5D => (Opcode::VMINPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x5E => (Opcode::VDIVPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x5F => (Opcode::VMAXPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x77 => (Opcode::VZEROUPPER, VEXOperandCode::Nothing), + 0xC2 => (Opcode::VCMPPS, if L { + VEXOperandCode::V_G_E_ymm_imm8 + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0xC6 => (Opcode::VSHUFPS, if L { + VEXOperandCode::V_G_E_ymm_imm8 + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(()); + } + } + }, + VEXOpcodePrefix::Prefix66 => { + match opc { + 0x10 => (Opcode::VMOVUPD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x11 => (Opcode::VMOVUPD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x12 => (Opcode::VMOVLPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_M_xmm + }), + 0x13 => (Opcode::VMOVLPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::M_G_xmm + }), + 0x14 => (Opcode::VUNPCKLPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x15 => (Opcode::VUNPCKHPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x16 => (Opcode::VMOVHPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_M_xmm + }), + 0x17 => (Opcode::VMOVHPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::M_G_xmm + }), + 0x28 => (Opcode::VMOVAPD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x29 => (Opcode::VMOVAPD, if L { + VEXOperandCode::E_G_ymm + } else { + VEXOperandCode::E_G_xmm + }), + 0x2B => (Opcode::VMOVNTPD, if L { + VEXOperandCode::M_G_ymm + } else { + VEXOperandCode::M_G_xmm + }), + 0x50 => (Opcode::VMOVMSKPD, if L { + VEXOperandCode::G_U_ymm + } else { + VEXOperandCode::G_U_xmm + }), + 0x51 => (Opcode::VSQRTPD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x57 => (Opcode::VXORPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x58 => (Opcode::VADDPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x59 => (Opcode::VMULPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x5A => (Opcode::VCVTPD2PS, if L { + VEXOperandCode::G_xmm_E_ymm + } else { + VEXOperandCode::G_xmm_E_xmm + }), + 0x5B => (Opcode::VCVTPS2DQ, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x5C => (Opcode::VSUBPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x5D => (Opcode::VMINPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x5E => (Opcode::VDIVPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x5F => (Opcode::VMAXPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x60 => (Opcode::VPUNPCKLBW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x61 => (Opcode::VPUNPCKLWD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x62 => (Opcode::VPUNPCKLDQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x63 => (Opcode::VPACKSSWB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x64 => (Opcode::VPCMPGTB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x65 => (Opcode::VPCMPGTW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x66 => (Opcode::VPCMPGTD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x67 => (Opcode::VPACKUSWB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x68 => (Opcode::VPUNPCKHBW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x69 => (Opcode::VPUNPCKHWD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x6A => (Opcode::VPUNPCKHDQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x6B => (Opcode::VPACKSSDW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x6C => (Opcode::VPUNPCKLQDQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x6D => (Opcode::VPUNPCKHQDQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x6E => if instruction.prefixes.vex().w() { + (Opcode::VMOVQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::G_xmm_Eq + }) + } else { + (Opcode::VMOVD, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::G_xmm_Ed + }) + }, + 0x6F => (Opcode::VMOVDQA, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x70 => (Opcode::VPSHUFD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x71 => (Opcode::VPSLLW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x71 => (Opcode::VPSRAW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x71 => (Opcode::VPSRLW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }), + 0x72 => (Opcode::VPSLLD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x72 => (Opcode::VPSRAD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x72 => (Opcode::VPSRLD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x73 => (Opcode::VPSLLDQ, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x73 => (Opcode::VPSLLQ, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x73 => (Opcode::VPSRLDQ, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x73 => (Opcode::VPSRLQ, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x74 => (Opcode::VPCMPEQB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x75 => (Opcode::VPCMPEQW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x76 => (Opcode::VPCMPEQD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x7C => (Opcode::VHADDPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x7D => (Opcode::VHSUBPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x7E => (Opcode::VMOVD, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::Ed_G_xmm + }), + 0x7E => (Opcode::VMOVQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::Eq_G_xmm + }), + 0x7F => (Opcode::VMOVDQA, if L { + VEXOperandCode::E_G_ymm + } else { + VEXOperandCode::E_G_xmm + }), + 0xC2 => (Opcode::VCMPPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xC4 => (Opcode::VPINSRW, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_xmm_Ew_imm8 + }), + 0xC5 => (Opcode::VPEXTRW, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::U_G_xmm_imm8 + }), + 0xC6 => (Opcode::VSHUFPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xD0 => (Opcode::VADDSUBPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xD1 => (Opcode::VPSRLW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xD2 => (Opcode::VPSRLD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xD3 => (Opcode::VPSRLQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xD4 => (Opcode::VPADDQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xD5 => (Opcode::VPMULLW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xD6 => (Opcode::VMOVQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::G_E_xmm + }), + 0xD7 => (Opcode::VPMOVMSKB, if L { + VEXOperandCode::U_G_ymm + } else { + VEXOperandCode::U_G_xmm + }), + 0xD8 => (Opcode::VPSUBUSB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xD9 => (Opcode::VPSUBUSW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xDB => (Opcode::VPAND, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xDC => (Opcode::VPADDUSB, if L { + VEXOperandCode::V_G_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0xDD => (Opcode::VPADDUSW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xDF => (Opcode::VPANDN, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xE0 => (Opcode::VPAVGB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xE1 => (Opcode::VPSRAW, if L { + VEXOperandCode::V_G_ymm_E_xmm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xE2 => (Opcode::VPSRAD, if L { + VEXOperandCode::V_G_ymm_E_xmm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xE3 => (Opcode::VPAVGW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xE4 => (Opcode::VPMULHUW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xE5 => (Opcode::VPMULHW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xE6 => (Opcode::VCVTTPD2DQ, if L { + VEXOperandCode::G_xmm_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0xE7 => (Opcode::VMOVNTDQ, if L { + VEXOperandCode::M_G_ymm + } else { + VEXOperandCode::M_G_xmm + }), + 0xE8 => (Opcode::VPSUBSB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xE9 => (Opcode::VPSUBSW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xEB => (Opcode::VPOR, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xEC => (Opcode::VPADDSB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xED => (Opcode::VPADDSW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xEE => (Opcode::VPMAXSW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xEF => (Opcode::VPXOR, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xF1 => (Opcode::VPSLLW, if L { + VEXOperandCode::V_G_ymm_E_xmm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xF2 => (Opcode::VPSLLD, if L { + VEXOperandCode::V_G_ymm_E_xmm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xF3 => (Opcode::VPSLLQ, if L { + VEXOperandCode::V_G_ymm_E_xmm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xF4 => (Opcode::VPMULUDQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xF5 => (Opcode::VPMADDWD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xF6 => (Opcode::VPSADBW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xF7 => (Opcode::VMASKMOVDQU, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::G_E_xmm + }), + 0xF8 => (Opcode::VPSUBB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xF9 => (Opcode::VPSUBW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xFA => (Opcode::VPSUBD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xFB => (Opcode::VPSUBQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xFC => (Opcode::VPADDB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xFD => (Opcode::VPADDW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xFE => (Opcode::VPADDD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(()); + } + } + } + VEXOpcodePrefix::PrefixF2 => { + match opc { + 0x12 => (Opcode::VMOVDDUP, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x70 => (Opcode::VPSHUFLW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x7c => (Opcode::VHADDPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x7d => (Opcode::VHSUBPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xd0 => (Opcode::VADDSUBPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xe6 => (Opcode::VCVTPD2DQ, if L { + VEXOperandCode::G_xmm_E_ymm + } else { + VEXOperandCode::G_xmm_E_xmm + }), + 0xf0 => (Opcode::VLDDQU, if L { + VEXOperandCode::G_M_ymm + } else { + VEXOperandCode::G_M_ymm + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(()); + } + } + } + VEXOpcodePrefix::PrefixF3 => { + match opc { + 0x12 => (Opcode::VMOVSLDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), + 0x16 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), + 0x5b => (Opcode::VCVTTPS2DQ, if L { VEXOperandCode::G_ymm_E_ymm } else { VEXOperandCode::G_xmm_E_xmm }), + 0x6f => (Opcode::VMOVDQU, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), + 0x70 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm_imm8 } else { VEXOperandCode::G_E_xmm_imm8 }), + 0x7e => (Opcode::VMOVQ, if L { instruction.opcode = Opcode::Invalid; return Err(()); } else { VEXOperandCode::G_E_xmm }), + 0x7f => (Opcode::VMOVDQU, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), + 0xe6 => (Opcode::VCVTDQ2PD, if L { VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_xmm_E_xmm }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(()); + } + } + } + } + } + VEXOpcodeMap::Map0F38 => { + // TODO: verify rejecting invalid W bit + if let VEXOpcodePrefix::Prefix66 = p { + // possibly valid! + match opc { + 0x00 => (Opcode::VPSHUFB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x01 => (Opcode::VPHADDW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x02 => (Opcode::VPHADDD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x03 => (Opcode::VPHADDSW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x04 => (Opcode::VPMADDUBSW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x05 => (Opcode::VPHSUBW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x06 => (Opcode::VPHSUBD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x07 => (Opcode::VPHSUBSW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x08 => (Opcode::VPSIGNB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x09 => (Opcode::VPSIGNW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x0A => (Opcode::VPSIGND, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x0B => (Opcode::VPMULHRSW, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x0C => (Opcode::VPERMILPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x0D => (Opcode::VPERMILPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x0E => (Opcode::VTESTPS, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x0F => (Opcode::VTESTPD, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x13 => (Opcode::VCVTPH2PS, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x16 => (Opcode::VPERMPS, if L { + VEXOperandCode::V_G_E_xmm + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x17 => (Opcode::VPTEST, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x18 => (Opcode::VBROADCASTSS, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x19 => (Opcode::VBROADCASTSD, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x1A => (Opcode::VBROADCASTF128, if L { + VEXOperandCode::V15_G_M_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x1C => (Opcode::VPABSB, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x1D => (Opcode::VPABSW, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x1E => (Opcode::VPABSD, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x20 => (Opcode::VPMOVSXBW, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x21 => (Opcode::VPMOVSXBD, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x22 => (Opcode::VPMOVSXBQ, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x23 => (Opcode::VPMOVSXWD, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x24 => (Opcode::VPMOVSXWQ, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x25 => (Opcode::VPMOVSXDQ, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x28 => (Opcode::VPMULDQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x29 => (Opcode::VPCMPEQQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x2A => (Opcode::VMOVNTDQA, if L { + VEXOperandCode::V15_G_M_ymm + } else { + VEXOperandCode::V15_G_M_xmm + }), + 0x2C => (Opcode::VMASKMOVPS, if L { + VEXOperandCode::V_G_M_ymm + } else { + VEXOperandCode::V_G_M_xmm + }), + 0x2D => (Opcode::VMASKMOVPD, if L { + VEXOperandCode::V_G_M_ymm + } else { + VEXOperandCode::V_G_M_xmm + }), + 0x2E => (Opcode::VMASKMOVPS, if L { + VEXOperandCode::M_V_G_ymm + } else { + VEXOperandCode::M_V_G_xmm + }), + 0x2F => (Opcode::VMASKMOVPD, if L { + VEXOperandCode::M_V_G_ymm + } else { + VEXOperandCode::M_V_G_xmm + }), + 0x30 => (Opcode::VPMOVZXBW, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x31 => (Opcode::VPMOVZXBD, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x32 => (Opcode::VPMOVZXBQ, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x33 => (Opcode::VPMOVZXWD, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x34 => (Opcode::VPMOVZXWQ, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x35 => (Opcode::VPMOVZXDQ, if L { + VEXOperandCode::V15_G_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x36 => (Opcode::VPERMD, if L { + VEXOperandCode::V_G_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x37 => (Opcode::VPCMPGTQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x39 => (Opcode::VPMINSD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x3B => (Opcode::VPMINUD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x3C => (Opcode::VPMAXSB, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x3D => (Opcode::VPMAXSD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x3F => (Opcode::VPMAXUD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x40 => (Opcode::VPMULLD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x41 => (Opcode::VPHMINPOSUW, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x45 => (Opcode::VPSRLVD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x45 => (Opcode::VPSRLVQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x46 => (Opcode::VPSRAVD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x47 => (Opcode::VPSLLVD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x47 => (Opcode::VPSLLVQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x58 => (Opcode::VPBROADCASTD, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x59 => (Opcode::VPBROADCASTQ, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0x5A => (Opcode::VBROADCASTI128, if L { + VEXOperandCode::V15_G_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x78 => (Opcode::VPBROADCASTB, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_ymm + }), + 0x79 => (Opcode::VPBROADCASTW, if L { + VEXOperandCode::V15_G_E_ymm + } else { + VEXOperandCode::V15_G_E_ymm + }), + 0x8C => { + if instruction.prefixes.vex().w() { + (Opcode::VPMASKMOVD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VPMASKMOVQ, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0x8E => { + if instruction.prefixes.vex().w() { + (Opcode::VPMASKMOVD, if L { + VEXOperandCode::E_V_G_ymm + } else { + VEXOperandCode::E_V_G_ymm + }) + } else { + (Opcode::VPMASKMOVQ, if L { + VEXOperandCode::E_V_G_ymm + } else { + VEXOperandCode::E_V_G_ymm + }) + } + }, + // TODO + 0x90 => { + if instruction.prefixes.vex().w() { + (Opcode::VPGATHERDD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } else { + (Opcode::VPGATHERDQ, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } + }, + 0x91 => { + if instruction.prefixes.vex().w() { + (Opcode::VPGATHERQD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } else { + (Opcode::VPGATHERQQ, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } + }, + 0x92 => { + if instruction.prefixes.vex().w() { + (Opcode::VGATHERDPD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } else { + (Opcode::VGATHERDPS, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } + }, + 0x93 => { + if instruction.prefixes.vex().w() { + (Opcode::VGATHERQPD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } else { + (Opcode::VGATHERQPS, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } + }, + 0x96 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADDSUB132PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMADDSUB132PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0x97 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUBADD132PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMSUBADD132PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0x98 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADD132PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMADD132PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0x9A => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUB132PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMSUB132PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0x9C => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMADD132PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFNMADD132PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0x9E => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMSUB132PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFNMSUB132PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xA6 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADDSUB213PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMADDSUB213PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xA7 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUBADD213PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMSUBADD213PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xA8 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADD213PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMADD213PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xAA => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUB213PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMSUB213PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xAC => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMADD213PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFNMADD213PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xAE => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMSUB213PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFNMSUB213PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xB6 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADDSUB231PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMADDSUB231PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xB7 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUBADD231PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMSUBADD231PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xB8 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADD231PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMADD231PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xBA => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUB231PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFMSUB231PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xBC => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMADD231PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFNMADD231PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xBE => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMSUB231PD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } else { + (Opcode::VFNMSUB231PS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_ymm + }) + } + }, + 0xDB => (Opcode::VAESIMC, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V15_G_E_xmm + }), + 0xDC => (Opcode::VAESENC, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xDD => (Opcode::VAESENCLAST, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xDE => (Opcode::VAESDEC, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm + }), + 0xDF => (Opcode::VAESDECLAST, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(()); + } + } + } else { + // the only VEX* 0f38 instructions have an implied 66 prefix. + instruction.opcode = Opcode::Invalid; + return Err(()); + } + } + VEXOpcodeMap::Map0F3A => { + if let VEXOpcodePrefix::Prefix66 = p { + // possibly valid! + match opc { + 0x00 => (Opcode::VPERMQ, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x01 => (Opcode::VPERMPD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x02 => (Opcode::VPBLENDD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x04 => (Opcode::VPERMILPS, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x05 => (Opcode::VPERMILPD, if L { + VEXOperandCode::V_G_E_ymm + } else { + VEXOperandCode::V_G_E_xmm + }), + 0x06 => (Opcode::VPERM2F128, if L { + VEXOperandCode::V_G_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x08 => (Opcode::VROUNDPS, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x09 => (Opcode::VROUNDPD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x0C => (Opcode::VBLENDPS, if L { + VEXOperandCode::V_G_E_ymm_imm8 + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x0D => (Opcode::VBLENDPD, if L { + VEXOperandCode::V_G_E_ymm_imm8 + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x0E => (Opcode::VPBLENDW, if L { + VEXOperandCode::V_G_E_ymm_imm8 + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x0F => (Opcode::VPALIGNR, if L { + VEXOperandCode::V_G_E_ymm_imm8 + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x14 => (Opcode::VPEXTRB, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::Ev_G_xmm_imm8 + }), + 0x15 => (Opcode::VPEXTRW, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::Ev_G_xmm_imm8 + }), + 0x16 => (Opcode::VPEXTRD, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + // varies on W + VEXOperandCode::Ev_G_xmm_imm8 + }), + 0x16 => (Opcode::VPEXTRQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x17 => (Opcode::VEXTRACTPS, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x18 => (Opcode::VINSERTF128, if L { + VEXOperandCode::V_G_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x19 => (Opcode::VEXTRACTF128, if L { + VEXOperandCode::E_xmm_G_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x1D => (Opcode::VCVTPS2PH, if L { + VEXOperandCode::E_xmm_G_ymm_imm8 + } else { + VEXOperandCode::E_G_xmm_imm8 + }), + 0x20 => (Opcode::VPINSRB, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x21 => (Opcode::VINSERTPS, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x22 => (Opcode::VPINSRD, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x22 => (Opcode::VPINSRQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x38 => (Opcode::VINSERTI128, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 + }), + 0x39 => (Opcode::VEXTRACTI128, if L { + VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x40 => (Opcode::VDPPS, if L { + VEXOperandCode::V_G_E_ymm_imm8 + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x41 => (Opcode::VDPPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x42 => (Opcode::VMPSADBW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x44 => (Opcode::VPCLMULQDQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::V_G_E_xmm_imm8 + }), + 0x46 => (Opcode::VPERM2I128, if L { + VEXOperandCode::V_G_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(()); + }), + 0x4A => (Opcode::VBLENDVPS, if L { + VEXOperandCode::V_G_E_ymm_ymm4 + } else { + VEXOperandCode::V_G_E_xmm_xmm4 + }), + 0x4B => (Opcode::VBLENDVPD, if L { + VEXOperandCode::V_G_E_ymm_ymm4 + } else { + VEXOperandCode::V_G_E_xmm_xmm4 + }), + 0x4C => (Opcode::VPBLENDVB, if L { + VEXOperandCode::V_G_E_ymm_ymm4 + } else { + VEXOperandCode::V_G_E_xmm_xmm4 + }), + 0x62 => (Opcode::VPCMPISTRM, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x63 => (Opcode::VPCMPISTRI, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0xDF => (Opcode::VAESKEYGENASSIST, if L { + instruction.opcode = Opcode::Invalid; + return Err(()); + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(()); + } + } + } else { + // the only VEX* 0f3a instructions have an implied 66 prefix. + instruction.opcode = Opcode::Invalid; + return Err(()); + } + } + }; + instruction.opcode = opcode; + read_vex_operands(bytes, instruction, length, operand_code) +} diff --git a/test/test.rs b/test/test.rs index cc865d9..8452e89 100644 --- a/test/test.rs +++ b/test/test.rs @@ -8,14 +8,26 @@ use yaxpeax_x86::{Instruction, InstDecoder, decode_one}; fn decode(bytes: &[u8]) -> Option<Instruction> { let mut instr = Instruction::invalid(); - match decode_one(bytes.iter().map(|x| *x).take(16).collect::<Vec<u8>>(), &mut instr) { + match decode_one(&InstDecoder::default(), bytes.iter().map(|x| *x).take(16).collect::<Vec<u8>>(), &mut instr) { + Some(()) => Some(instr), + None => None + } +} + +fn decode_as(decoder: &InstDecoder, bytes: &[u8]) -> Option<Instruction> { + let mut instr = Instruction::invalid(); + match decode_one(decoder, bytes.iter().map(|x| *x).take(16).collect::<Vec<u8>>(), &mut instr) { Some(()) => Some(instr), None => None } } fn test_invalid(data: &[u8]) { - if let Some(inst) = InstDecoder::default().decode(data.into_iter().cloned()) { + test_invalid_under(&InstDecoder::default(), data); +} + +fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) { + if let Some(inst) = decoder.decode(data.into_iter().cloned()) { assert_eq!(inst.opcode, yaxpeax_x86::Opcode::Invalid); } else { // this is fine @@ -23,11 +35,15 @@ fn test_invalid(data: &[u8]) { } fn test_display(data: &[u8], expected: &'static str) { + test_display_under(&InstDecoder::default(), data, expected); +} + +fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str) { let mut hex = String::new(); for b in data { write!(hex, "{:02x}", b).unwrap(); } - match InstDecoder::default().decode(data.into_iter().map(|x| *x)) { + match decoder.decode(data.into_iter().map(|x| *x)) { Some(instr) => { let text = format!("{}", instr); assert!( @@ -231,8 +247,16 @@ fn test_push_pop() { } #[test] +fn test_bmi1() { + let bmi1 = InstDecoder::default(); + let no_bmi1 = InstDecoder::default().without_bmi1(); + test_display_under(&bmi1, &[0x41, 0x0f, 0xbc, 0xd3], "tzcnt edx, r11d"); + test_display_under(&no_bmi1, &[0x41, 0x0f, 0xbc, 0xd3], "bsf edx, r11d"); +} + +#[test] fn test_bitwise() { - test_display(&[0x41, 0x0f, 0xbc, 0xd3], "bsf edx, r11d"); + test_display_under(&InstDecoder::minimal(), &[0x41, 0x0f, 0xbc, 0xd3], "bsf edx, r11d"); test_display(&[0x48, 0x0f, 0xa3, 0xd0], "bt rax, rdx"); test_display(&[0x48, 0x0f, 0xab, 0xd0], "bts rax, rdx"); } @@ -265,8 +289,96 @@ fn evex() { } #[test] -#[ignore] -fn vex() { +fn test_vex() { + test_display(&[0xc5, 0xf8, 0x10, 0x00], "vmovups xmm0, [rax]"); + test_display(&[0xc5, 0x78, 0x10, 0x0f], "vmovups xmm9, [rdi]"); + test_display(&[0xc5, 0xf8, 0x10, 0xcf], "vmovups xmm1, xmm7"); + test_display(&[0xc5, 0xf9, 0x10, 0x0f], "vmovupd xmm1, [rdi]"); + test_display(&[0xc5, 0xfa, 0x7e, 0x10], "vmovq xmm2, [rax]"); + test_display(&[0xc5, 0xfc, 0x10, 0x0f], "vmovups ymm1, [rdi]"); + test_display(&[0xc5, 0xfd, 0x10, 0x0f], "vmovupd ymm1, [rdi]"); + test_display(&[0xc5, 0xfe, 0x10, 0x0f], "vmovss ymm1, [rdi]"); + test_display(&[0xc5, 0xff, 0x10, 0xcf], "vmovsd xmm1, xmm0, xmm7"); + test_display(&[0xc5, 0xff, 0x10, 0x00], "vmovsd xmm0, [rax]"); + test_invalid(&[0x4f, 0xc5, 0xf8, 0x10, 0x00]); + test_invalid(&[0xf0, 0xc5, 0xf8, 0x10, 0x00]); + test_display(&[0xc4, 0x02, 0x71, 0x00, 0x00], "vpshufb xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x00, 0x00], "vpshufb ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x00, 0xcd], "vpshufb xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x00, 0xcd], "vpshufb ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x01, 0x00], "vphaddw xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x01, 0x00], "vphaddw ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x01, 0xcd], "vphaddw xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x01, 0xcd], "vphaddw ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x02, 0x00], "vphaddd xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x02, 0x00], "vphaddd ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x02, 0xcd], "vphaddd xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x02, 0xcd], "vphaddd ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x03, 0x00], "vphaddsw xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x03, 0x00], "vphaddsw ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x03, 0xcd], "vphaddsw xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x03, 0xcd], "vphaddsw ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x04, 0x00], "vphaddubsw xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x04, 0x00], "vphaddubsw ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x04, 0xcd], "vphaddubsw xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x04, 0xcd], "vphaddubsw ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x05, 0x00], "vphsubw xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x05, 0x00], "vphsubw ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x05, 0xcd], "vphsubw xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x05, 0xcd], "vphsubw ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x06, 0x00], "vphsubd xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x06, 0x00], "vphsubd ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x06, 0xcd], "vphsubd xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x06, 0xcd], "vphsubd ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x07, 0x00], "vphsubsw xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x07, 0x00], "vphsubsw ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x07, 0xcd], "vphsubsw xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x07, 0xcd], "vphsubsw ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x08, 0x00], "vpsignb xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x08, 0x00], "vpsignb ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x08, 0xcd], "vpsignb xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x08, 0xcd], "vpsignb ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x09, 0x00], "vpsignw xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x09, 0x00], "vpsignw ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x09, 0xcd], "vpsignw xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x09, 0xcd], "vpsignw ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x0a, 0x00], "vpsignd xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x0a, 0x00], "vpsignd ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x0a, 0xcd], "vpsignd xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x0a, 0xcd], "vpsignd ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x0b, 0x00], "vpmulhrsw xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x0b, 0x00], "vpmulhrsw ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x0b, 0xcd], "vpmulhrsw xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x0b, 0xcd], "vpmulhrsw ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x0c, 0x00], "vpermilps xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x0c, 0x00], "vpermilps ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x0c, 0xcd], "vpermilps xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x0c, 0xcd], "vpermilps ymm9, ymm1, ymm13"); + test_display(&[0xc4, 0x02, 0x71, 0x0d, 0x00], "vpermilpd xmm9, xmm1, [r8]"); + test_display(&[0xc4, 0x02, 0x75, 0x0d, 0x00], "vpermilpd ymm9, ymm1, [r8]"); + test_display(&[0xc4, 0x02, 0x71, 0x0d, 0xcd], "vpermilpd xmm9, xmm1, xmm13"); + test_display(&[0xc4, 0x02, 0x75, 0x0d, 0xcd], "vpermilpd ymm9, ymm1, ymm13"); + test_invalid(&[0xc4, 0x02, 0x71, 0x0e, 0x00]); + test_display(&[0xc4, 0x02, 0x79, 0x0e, 0x00], "vtestps xmm8, [r8]"); + test_display(&[0xc4, 0x02, 0x7d, 0x0e, 0x00], "vtestps ymm8, [r8]"); + test_display(&[0xc4, 0x02, 0x79, 0x0e, 0xcd], "vtestps xmm9, xmm13"); + test_display(&[0xc4, 0x02, 0x7d, 0x0e, 0xcd], "vtestps ymm9, ymm13"); + test_invalid(&[0xc4, 0x02, 0x71, 0x0f, 0x00]); + test_display(&[0xc4, 0x02, 0x79, 0x0f, 0x00], "vtestpd xmm8, [r8]"); + test_display(&[0xc4, 0x02, 0x7d, 0x0f, 0x00], "vtestpd ymm8, [r8]"); + test_display(&[0xc4, 0x02, 0x79, 0x0f, 0xcd], "vtestpd xmm9, xmm13"); + test_display(&[0xc4, 0x02, 0x7d, 0x0f, 0xcd], "vtestpd ymm9, ymm13"); + test_display(&[0xc4, 0xe2, 0x65, 0x90, 0x04, 0x51], "vpgatherdd ymm0, [rcx + ymm2 * 2], ymm3"); + test_display(&[0xc4, 0xe2, 0xe5, 0x90, 0x04, 0x51], "vpgatherdq ymm0, [rcx + ymm2 * 2], ymm3"); + test_display(&[0xc4, 0xe2, 0x65, 0x91, 0x04, 0x51], "vpgatherqd ymm0, [rcx + ymm2 * 2], ymm3"); + test_display(&[0xc4, 0xe2, 0xe5, 0x91, 0x04, 0x51], "vpgatherqq ymm0, [rcx + ymm2 * 2], ymm3"); + test_display(&[0xc4, 0x02, 0x09, 0x9d, 0xcd], "vfnmadd132ss xmm9, xmm14, xmm11"); + test_display(&[0xc4, 0x02, 0x89, 0x9d, 0xcd], "vfnmadd132ss xmm9, xmm14, xmm11"); +// ... + test_display(&[0xc4, 0xe3, 0x79, 0x14, 0x00, 0xd0], "vpextrb rax, xmm2, 0x0a"); + test_display(&[0xc4, 0xe3, 0x79, 0x14, 0x00, 0x0a], "vpextrb [rax], xmm2, 0x0a"); + test_invalid(&[0xc4, 0xe3, 0xf9, 0x14, 0x00, 0xd0]); + test_invalid(&[0xc4, 0xe3, 0xf9, 0x14, 0x00, 0x0a]); } #[test] @@ -293,13 +405,13 @@ fn prefixed_0f() { test_display(&[0x0f, 0x12, 0xcf], "movhlps xmm1, xmm7"); test_display(&[0x0f, 0x16, 0x0f], "movhps xmm1, [rdi]"); test_display(&[0x0f, 0x16, 0xcf], "movlhps xmm1, xmm7"); -// test_display(&[0x0f, 0x12, 0xc0], "movhlps xmm0, xmm0"); + test_display(&[0x0f, 0x12, 0xc0], "movhlps xmm0, xmm0"); test_invalid(&[0x0f, 0x13, 0xc0]); test_display(&[0x0f, 0x13, 0x00], "movlps [rax], xmm0"); test_display(&[0x0f, 0x14, 0x08], "unpcklps xmm1, [rax]"); test_display(&[0x0f, 0x15, 0x08], "unpckhps xmm1, [rax]"); test_display(&[0x0f, 0x16, 0x0f], "movhps xmm1, [rdi]"); -// test_display(&[0x0f, 0x16, 0xc0], "movlhps xmm0, xmm0"); + test_display(&[0x0f, 0x16, 0xc0], "movlhps xmm0, xmm0"); test_invalid(&[0x0f, 0x17, 0xc0]); test_display(&[0x0f, 0x17, 0x00], "movhps [rax], xmm0"); test_invalid(&[0x0f, 0x18, 0xc0]); |