From 27aed160a26583990e4f8c26c58327e985e8c9bc Mon Sep 17 00:00:00 2001 From: iximeow Date: Fri, 11 Jun 2021 17:11:20 -0700 Subject: add extensive avx and initial avx2 tests, fix several bugs and missing instructions --- src/long_mode/display.rs | 581 ++++++++++++++++++++++++++++++++- src/long_mode/mod.rs | 307 ++++++++++++++++- src/long_mode/vex.rs | 831 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 1583 insertions(+), 136 deletions(-) (limited to 'src/long_mode') diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index f84ff7a..02d8382 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -664,6 +664,7 @@ const MNEMONICS: &[&'static str] = &[ "xorpd", "vmovddup", "vpshuflw", + "vpshufhw", "vhaddps", "vhsubps", "vaddsubps", @@ -835,6 +836,7 @@ const MNEMONICS: &[&'static str] = &[ "vpabsd", "vpabsw", "vpackssdw", + "vpackusdw", "vpacksswb", "vpackuswb", "vpaddb", @@ -846,12 +848,12 @@ const MNEMONICS: &[&'static str] = &[ "vpaddusw", "vpaddw", "vpalignr", - "vandps", "vandpd", - "vorps", + "vandps", "vorpd", - "vandnps", + "vorps", "vandnpd", + "vandnps", "vpand", "vpandn", "vpavgb", @@ -872,6 +874,8 @@ const MNEMONICS: &[&'static str] = &[ "vpcmpgtd", "vpcmpgtq", "vpcmpgtw", + "vpcmpestri", + "vpcmpestrm", "vpcmpistri", "vpcmpistrm", "vperm2f128", @@ -893,7 +897,7 @@ const MNEMONICS: &[&'static str] = &[ "vphaddd", "vphaddsw", "vphaddw", - "vphaddubsw", + "vpmaddubsw", "vphminposuw", "vphsubd", "vphsubsw", @@ -911,8 +915,11 @@ const MNEMONICS: &[&'static str] = &[ "vpmaxub", "vpmaxuw", "vpmaxud", + "vpminsb", "vpminsw", "vpminsd", + "vpminub", + "vpminuw", "vpminud", "vpmovmskb", "vpmovsxbd", @@ -1001,6 +1008,9 @@ const MNEMONICS: &[&'static str] = &[ "vxorpd", "vxorps", "vzeroupper", + "vzeroall", + "vldmxcsr", + "vstmxcsr", "pclmulqdq", "aeskeygenassist", "aesimc", @@ -1315,6 +1325,287 @@ const MNEMONICS: &[&'static str] = &[ // TSXLDTRK "xsusldtrk", "xresldtrk", + + // AVX512F + "valignd", + "valignq", + "vblendmpd", + "vblendmps", + "vcompresspd", + "vcompressps", + "vcvtpd2udq", + "vcvttpd2udq", + "vcvtps2udq", + "vcvttps2udq", + "vcvtqq2pd", + "vcvtqq2ps", + "vcvtsd2usi", + "vcvttsd2usi", + "vcvtss2usi", + "vcvttss2usi", + "vcvtudq2pd", + "vcvtudq2ps", + "vcvtusi2usd", + "vcvtusi2uss", + "vexpandpd", + "vexpandps", + "vextractf32x4", + "vextractf64x4", + "vextracti32x4", + "vextracti64x4", + "vfixupimmpd", + "vfixupimmps", + "vfixupimmsd", + "vfixupimmss", + "vgetexppd", + "vgetexpps", + "vgetexpsd", + "vgetexpss", + "vgetmantpd", + "vgetmantps", + "vgetmantsd", + "vgetmantss", + "vinsertf32x4", + "vinsertf64x4", + "vmovdqa32", + "vmovdqa64", + "vmovdqu32", + "vmovdqu64", + "vpblendmd", + "vpblendmq", + "vpcmpd", + "vpcmpud", + "vpcmpq", + "vpcmpuq", + "vpcompressq", + "vpcompressd", + "vpermi2d", + "vpermi2q", + "vpermi2pd", + "vpermi2ps", + "vpermt2d", + "vpermt2q", + "vpermt2pd", + "vpermt2ps", + "vpmaxsq", + "vpmaxuq", + "vpminsq", + "vpminuq", + "vpmovsqb", + "vpmovusqb", + "vpmovsqw", + "vpmovusqw", + "vpmovsqd", + "vpmovusqd", + "vpmovsdb", + "vpmovusdb", + "vpmovsdw", + "vpmovusdw", + "vprold", + "vprolq", + "vprolvd", + "vprolvq", + "vprord", + "vprorq", + "vprorrd", + "vprorrq", + "vpscatterdd", + "vpscatterdq", + "vpscatterqd", + "vpscatterqq", + "vpsraq", + "vpsravq", + "vptestnmd", + "vptestnmq", + "vpterlogd", + "vpterlogq", + "vptestmd", + "vptestmq", + "vrcp14pd", + "vrcp14ps", + "vrcp14sd", + "vrcp14ss", + "vrndscalepd", + "vrndscaleps", + "vrndcsalesd", + "vrndscaless", + "vrsqrt14pd", + "vrsqrt14ps", + "vrsqrt14sd", + "vrsqrt14ss", + "vscaledpd", + "vscaledps", + "vscaledsd", + "vscaledss", + "vscatterdd", + "vscatterdq", + "vscatterqd", + "vscatterqq", + "vshuff32x4", + "vshuff64x2", + "vshufi32x4", + "vshufi64x2", + + // AVX512DQ + "vcvttpd2qq", + "vcvtpd2qq", + "vcvttpd2uqq", + "vcvtpd2uqq", + "vcvttps2qq", + "vcvtps2qq", + "vcvttps2uqq", + "vcvtps2uqq", + "vcvtuqq2pd", + "vcvtuqq2ps", + "vextractf64x2", + "vextracti64x2", + "vfpclasspd", + "vfpclassps", + "vfpclasssd", + "vfpclassss", + "vinsertf64x2", + "vinserti64x2", + "vpmovm2d", + "vpmovm2q", + "vpmovb2d", + "vpmovq2m", + "vpmulllq", + "vrangepd", + "vrangeps", + "vrangesd", + "vrangess", + "vreducepd", + "vreduceps", + "vreducesd", + "vreducess", + + // AVX512BW + "vdbpsadbw", + "vmovdqu8", + "vmovdqu16", + "vpblendmb", + "vpblendmw", + "vpcmpb", + "vpcmpub", + "vpcmpw", + "vpcmpuw", + "vpermw", + "vpermi2b", + "vpermi2w", + "vpmovm2b", + "vpmovm2w", + "vpmovb2m", + "vpmovw2m", + "vpmovswb", + "vpmovuswb", + "vpsllvw", + "vpsravw", + "vpsrlvw", + "vptestnmb", + "vptestnmw", + "vptestmb", + "vptestmw", + + // AVX512CD + "vpbroadcastm", + "vpconflictd", + "vpconflictq", + "vplzcntd", + "vplzcntq", + + "kunpckbw", + "kunpckwd", + "kunpckdq", + + "kaddb", + "kandb", + "kandnb", + "kmovb", + "knotb", + "korb", + "kortestb", + "kshiftlb", + "kshiftrb", + "ktestb", + "kxnorb", + "kxorb", + "kaddw", + "kandw", + "kandnw", + "kmovw", + "knotw", + "korw", + "kortestw", + "kshiftlw", + "kshiftrw", + "ktestw", + "kxnorw", + "kxorw", + "kaddd", + "kandd", + "kandnd", + "kmovd", + "knotd", + "kord", + "kortestd", + "kshiftld", + "kshiftrd", + "ktestd", + "kxnord", + "kxord", + "kaddq", + "kandq", + "kandnq", + "kmovq", + "knotq", + "korq", + "kortestq", + "kshiftlq", + "kshiftrq", + "ktestq", + "kxnorq", + "kxorq", + + // AVX512ER + "vexp2pd", + "vexp2ps", + "vexp2sd", + "vexp2ss", + "vrcp28pd", + "vrcp28ps", + "vrcp28sd", + "vrcp28ss", + "vrsqrt28pd", + "vrsqrt28ps", + "vrsqrt28sd", + "vrsqrt28ss", + + // AVX512PF + "vgatherpf0dpd", + "vgatherpf0dps", + "vgatherpf0qpd", + "vgatherpf0qps", + "vgatherpf1dpd", + "vgatherpf1dps", + "vgatherpf1qpd", + "vgatherpf1qps", + "vscatterpf0dpd", + "vscatterpf0dps", + "vscatterpf0qpd", + "vscatterpf0qps", + "vscatterpf1dpd", + "vscatterpf1dps", + "vscatterpf1qpd", + "vscatterpf1qps", + + // MPX + "bndmk", + "bndcl", + "bndcu", + "bndcn", + "bndmov", + "bndldx", + "bndstx", ]; impl Opcode { @@ -1325,6 +1616,11 @@ impl Opcode { } } + // AVX512CD + + + // MPX + impl Colorize for Opcode { fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result { match self { @@ -1408,6 +1704,7 @@ impl Colorize for Opcode { Opcode::VMULPS | Opcode::VMULSD | Opcode::VMULSS | + Opcode::VPMULLLQ | Opcode::VPABSB | Opcode::VPABSD | Opcode::VPABSW | @@ -1451,6 +1748,34 @@ impl Colorize for Opcode { Opcode::VPSUBW | Opcode::VROUNDPD | Opcode::VROUNDPS | + Opcode::VEXP2PD | + Opcode::VEXP2PS | + Opcode::VEXP2SD | + Opcode::VEXP2SS | + Opcode::VRCP28PD | + Opcode::VRCP28PS | + Opcode::VRCP28SD | + Opcode::VRCP28SS | + Opcode::VRCP14PD | + Opcode::VRCP14PS | + Opcode::VRCP14SD | + Opcode::VRCP14SS | + Opcode::VRNDSCALEPD | + Opcode::VRNDSCALEPS | + Opcode::VRNDCSALESD | + Opcode::VRNDSCALESS | + Opcode::VRSQRT14PD | + Opcode::VRSQRT14PS | + Opcode::VRSQRT14SD | + Opcode::VRSQRT14SS | + Opcode::VSCALEDPD | + Opcode::VSCALEDPS | + Opcode::VSCALEDSD | + Opcode::VSCALEDSS | + Opcode::VRSQRT28PD | + Opcode::VRSQRT28PS | + Opcode::VRSQRT28SD | + Opcode::VRSQRT28SS | Opcode::VRSQRTPS | Opcode::VSQRTPD | Opcode::VSQRTPS | @@ -1470,13 +1795,14 @@ impl Colorize for Opcode { Opcode::VSQRTSS | Opcode::VPSADBW | Opcode::VMPSADBW | + Opcode::VDBPSADBW | Opcode::VPHADDD | Opcode::VPHADDSW | Opcode::VPHADDW | Opcode::VPHSUBD | Opcode::VPHSUBSW | Opcode::VPHSUBW | - Opcode::VPHADDUBSW | + Opcode::VPMADDUBSW | Opcode::VPMADDWD | Opcode::VDPPD | Opcode::VDPPS | @@ -1499,6 +1825,19 @@ impl Colorize for Opcode { Opcode::VPSLLVD | Opcode::VPSLLVQ | Opcode::VPSLLW | + Opcode::VPROLD | + Opcode::VPROLQ | + Opcode::VPROLVD | + Opcode::VPROLVQ | + Opcode::VPRORD | + Opcode::VPRORQ | + Opcode::VPRORRD | + Opcode::VPRORRQ | + Opcode::VPSLLVW | + Opcode::VPSRAQ | + Opcode::VPSRAVQ | + Opcode::VPSRAVW | + Opcode::VPSRLVW | Opcode::VPSRAD | Opcode::VPSRAVD | Opcode::VPSRAW | @@ -1584,6 +1923,8 @@ impl Colorize for Opcode { Opcode::SUB | Opcode::POPCNT | Opcode::LZCNT | + Opcode::VPLZCNTD | + Opcode::VPLZCNTQ | Opcode::BT | Opcode::BTS | Opcode::BTR | @@ -1702,6 +2043,42 @@ impl Colorize for Opcode { Opcode::FXTRACT | Opcode::FYL2X | Opcode::FYL2XP1 | + Opcode::KADDB | + Opcode::KANDB | + Opcode::KANDNB | + Opcode::KNOTB | + Opcode::KORB | + Opcode::KSHIFTLB | + Opcode::KSHIFTRB | + Opcode::KXNORB | + Opcode::KXORB | + Opcode::KADDW | + Opcode::KANDW | + Opcode::KANDNW | + Opcode::KNOTW | + Opcode::KORW | + Opcode::KSHIFTLW | + Opcode::KSHIFTRW | + Opcode::KXNORW | + Opcode::KXORW | + Opcode::KADDD | + Opcode::KANDD | + Opcode::KANDND | + Opcode::KNOTD | + Opcode::KORD | + Opcode::KSHIFTLD | + Opcode::KSHIFTRD | + Opcode::KXNORD | + Opcode::KXORD | + Opcode::KADDQ | + Opcode::KANDQ | + Opcode::KANDNQ | + Opcode::KNOTQ | + Opcode::KORQ | + Opcode::KSHIFTLQ | + Opcode::KSHIFTRQ | + Opcode::KXNORQ | + Opcode::KXORQ | Opcode::IMUL => { write!(out, "{}", colors.arithmetic_op(self)) } Opcode::POPF | Opcode::PUSHF | @@ -1778,12 +2155,43 @@ impl Colorize for Opcode { Opcode::VCVTSS2SI | Opcode::VCVTTSD2SI | Opcode::VCVTTSS2SI | + Opcode::VCVTPD2UDQ | + Opcode::VCVTTPD2UDQ | + Opcode::VCVTPS2UDQ | + Opcode::VCVTTPS2UDQ | + Opcode::VCVTQQ2PD | + Opcode::VCVTQQ2PS | + Opcode::VCVTSD2USI | + Opcode::VCVTTSD2USI | + Opcode::VCVTSS2USI | + Opcode::VCVTTSS2USI | + Opcode::VCVTUDQ2PD | + Opcode::VCVTUDQ2PS | + Opcode::VCVTUSI2USD | + Opcode::VCVTUSI2USS | + Opcode::VCVTTPD2QQ | + Opcode::VCVTPD2QQ | + Opcode::VCVTTPD2UQQ | + Opcode::VCVTPD2UQQ | + Opcode::VCVTTPS2QQ | + Opcode::VCVTPS2QQ | + Opcode::VCVTTPS2UQQ | + Opcode::VCVTPS2UQQ | + Opcode::VCVTUQQ2PD | + Opcode::VCVTUQQ2PS | Opcode::VMOVDDUP | Opcode::VPSHUFLW | + Opcode::VPSHUFHW | + Opcode::VBLENDMPD | + Opcode::VBLENDMPS | + Opcode::VPBLENDMD | + Opcode::VPBLENDMQ | Opcode::VBLENDPD | Opcode::VBLENDPS | Opcode::VBLENDVPD | Opcode::VBLENDVPS | + Opcode::VPBLENDMB | + Opcode::VPBLENDMW | Opcode::PBLENDVB | Opcode::PBLENDW | Opcode::BLENDPD | @@ -1795,6 +2203,7 @@ impl Colorize for Opcode { Opcode::VBROADCASTI128 | Opcode::VBROADCASTSD | Opcode::VBROADCASTSS | + Opcode::VPBROADCASTM | Opcode::VEXTRACTF128 | Opcode::VEXTRACTI128 | Opcode::VEXTRACTPS | @@ -1803,10 +2212,48 @@ impl Colorize for Opcode { Opcode::VGATHERDPS | Opcode::VGATHERQPD | Opcode::VGATHERQPS | + Opcode::VGATHERPF0DPD | + Opcode::VGATHERPF0DPS | + Opcode::VGATHERPF0QPD | + Opcode::VGATHERPF0QPS | + Opcode::VGATHERPF1DPD | + Opcode::VGATHERPF1DPS | + Opcode::VGATHERPF1QPD | + Opcode::VGATHERPF1QPS | + Opcode::VSCATTERDD | + Opcode::VSCATTERDQ | + Opcode::VSCATTERQD | + Opcode::VSCATTERQQ | + Opcode::VPSCATTERDD | + Opcode::VPSCATTERDQ | + Opcode::VPSCATTERQD | + Opcode::VPSCATTERQQ | + Opcode::VSCATTERPF0DPD | + Opcode::VSCATTERPF0DPS | + Opcode::VSCATTERPF0QPD | + Opcode::VSCATTERPF0QPS | + Opcode::VSCATTERPF1DPD | + Opcode::VSCATTERPF1DPS | + Opcode::VSCATTERPF1QPD | + Opcode::VSCATTERPF1QPS | Opcode::VINSERTF128 | Opcode::VINSERTI128 | Opcode::VINSERTPS | Opcode::INSERTPS | + Opcode::VEXTRACTF32X4 | + Opcode::VEXTRACTF64X2 | + Opcode::VEXTRACTF64X4 | + Opcode::VEXTRACTI32X4 | + Opcode::VEXTRACTI64X2 | + Opcode::VEXTRACTI64X4 | + Opcode::VINSERTF32X4 | + Opcode::VINSERTF64X2 | + Opcode::VINSERTF64X4 | + Opcode::VINSERTI64X2 | + Opcode::VSHUFF32X4 | + Opcode::VSHUFF64X2 | + Opcode::VSHUFI32X4 | + Opcode::VSHUFI64X2 | Opcode::VMASKMOVDQU | Opcode::VMASKMOVPD | Opcode::VMASKMOVPS | @@ -1837,6 +2284,32 @@ impl Colorize for Opcode { Opcode::VMOVUPS | Opcode::VMOVSD | Opcode::VMOVSS | + Opcode::VMOVDQA32 | + Opcode::VMOVDQA64 | + Opcode::VMOVDQU32 | + Opcode::VMOVDQU64 | + Opcode::VPMOVM2B | + Opcode::VPMOVM2W | + Opcode::VPMOVB2M | + Opcode::VPMOVW2M | + Opcode::VPMOVSWB | + Opcode::VPMOVUSWB | + Opcode::VPMOVSQB | + Opcode::VPMOVUSQB | + Opcode::VPMOVSQW | + Opcode::VPMOVUSQW | + Opcode::VPMOVSQD | + Opcode::VPMOVUSQD | + Opcode::VPMOVSDB | + Opcode::VPMOVUSDB | + Opcode::VPMOVSDW | + Opcode::VPMOVUSDW | + Opcode::VPMOVM2D | + Opcode::VPMOVM2Q | + Opcode::VPMOVB2D | + Opcode::VPMOVQ2M | + Opcode::VMOVDQU8 | + Opcode::VMOVDQU16 | Opcode::VPBLENDD | Opcode::VPBLENDVB | @@ -1875,6 +2348,9 @@ impl Colorize for Opcode { Opcode::PMOVZXDQ | Opcode::PMOVZXWD | Opcode::PMOVZXWQ | + Opcode::KUNPCKBW | + Opcode::KUNPCKWD | + Opcode::KUNPCKDQ | Opcode::VUNPCKHPD | Opcode::VUNPCKHPS | Opcode::VUNPCKLPD | @@ -1890,9 +2366,12 @@ impl Colorize for Opcode { Opcode::VSHUFPD | Opcode::VSHUFPS | Opcode::VPACKSSDW | + Opcode::VPACKUSDW | Opcode::PACKUSDW | Opcode::VPACKSSWB | Opcode::VPACKUSWB | + Opcode::VALIGND | + Opcode::VALIGNQ | Opcode::VPALIGNR | Opcode::PALIGNR | Opcode::VPERM2F128 | @@ -1903,6 +2382,17 @@ impl Colorize for Opcode { Opcode::VPERMPD | Opcode::VPERMPS | Opcode::VPERMQ | + Opcode::VPERMI2D | + Opcode::VPERMI2Q | + Opcode::VPERMI2PD | + Opcode::VPERMI2PS | + Opcode::VPERMT2D | + Opcode::VPERMT2Q | + Opcode::VPERMT2PD | + Opcode::VPERMT2PS | + Opcode::VPERMI2B | + Opcode::VPERMI2W | + Opcode::VPERMW | Opcode::VPEXTRB | Opcode::VPEXTRD | Opcode::VPEXTRQ | @@ -1921,11 +2411,34 @@ impl Colorize for Opcode { Opcode::VPINSRW | Opcode::VPMASKMOVD | Opcode::VPMASKMOVQ | + Opcode::VCOMPRESSPD | + Opcode::VCOMPRESSPS | + Opcode::VPCOMPRESSQ | + Opcode::VPCOMPRESSD | + Opcode::VEXPANDPD | + Opcode::VEXPANDPS | Opcode::VPSHUFB | Opcode::VPSHUFD | Opcode::VPHMINPOSUW | Opcode::PHMINPOSUW | Opcode::VZEROUPPER | + Opcode::VZEROALL | + Opcode::VFIXUPIMMPD | + Opcode::VFIXUPIMMPS | + Opcode::VFIXUPIMMSD | + Opcode::VFIXUPIMMSS | + Opcode::VREDUCEPD | + Opcode::VREDUCEPS | + Opcode::VREDUCESD | + Opcode::VREDUCESS | + Opcode::VGETEXPPD | + Opcode::VGETEXPPS | + Opcode::VGETEXPSD | + Opcode::VGETEXPSS | + Opcode::VGETMANTPD | + Opcode::VGETMANTPS | + Opcode::VGETMANTSD | + Opcode::VGETMANTSS | Opcode::VLDDQU | Opcode::BSWAP | Opcode::CVTDQ2PD | @@ -1993,6 +2506,11 @@ impl Colorize for Opcode { Opcode::SHUFPD | Opcode::SHUFPS | Opcode::PMOVMSKB | + Opcode::KMOVB | + Opcode::KMOVW | + Opcode::KMOVD | + Opcode::KMOVQ | + Opcode::BNDMOV | Opcode::LDDQU | Opcode::CMC | Opcode::CLC | @@ -2109,6 +2627,32 @@ impl Colorize for Opcode { Opcode::VCOMISS | Opcode::VUCOMISD | Opcode::VUCOMISS | + Opcode::KORTESTB | + Opcode::KTESTB | + Opcode::KORTESTW | + Opcode::KTESTW | + Opcode::KORTESTD | + Opcode::KTESTD | + Opcode::KORTESTQ | + Opcode::KTESTQ | + Opcode::VPTESTNMD | + Opcode::VPTESTNMQ | + Opcode::VPTERLOGD | + Opcode::VPTERLOGQ | + Opcode::VPTESTMD | + Opcode::VPTESTMQ | + Opcode::VPTESTNMB | + Opcode::VPTESTNMW | + Opcode::VPTESTMB | + Opcode::VPTESTMW | + Opcode::VPCMPD | + Opcode::VPCMPUD | + Opcode::VPCMPQ | + Opcode::VPCMPUQ | + Opcode::VPCMPB | + Opcode::VPCMPUB | + Opcode::VPCMPW | + Opcode::VPCMPUW | Opcode::VCMPPD | Opcode::VCMPPS | Opcode::VCMPSD | @@ -2117,6 +2661,10 @@ impl Colorize for Opcode { Opcode::VMAXPS | Opcode::VMAXSD | Opcode::VMAXSS | + Opcode::VPMAXSQ | + Opcode::VPMAXUQ | + Opcode::VPMINSQ | + Opcode::VPMINUQ | Opcode::VMINPD | Opcode::VMINPS | Opcode::VMINSD | @@ -2129,6 +2677,8 @@ impl Colorize for Opcode { Opcode::VPCMPGTD | Opcode::VPCMPGTQ | Opcode::VPCMPGTW | + Opcode::VPCMPESTRI | + Opcode::VPCMPESTRM | Opcode::VPCMPISTRI | Opcode::VPCMPISTRM | Opcode::VPMAXSB | @@ -2137,9 +2687,22 @@ impl Colorize for Opcode { Opcode::VPMAXUB | Opcode::VPMAXUW | Opcode::VPMAXUD | + Opcode::VPMINSB | Opcode::VPMINSW | Opcode::VPMINSD | + Opcode::VPMINUB | + Opcode::VPMINUW | Opcode::VPMINUD | + Opcode::VFPCLASSPD | + Opcode::VFPCLASSPS | + Opcode::VFPCLASSSD | + Opcode::VFPCLASSSS | + Opcode::VRANGEPD | + Opcode::VRANGEPS | + Opcode::VRANGESD | + Opcode::VRANGESS | + Opcode::VPCONFLICTD | + Opcode::VPCONFLICTQ | Opcode::VPTEST | Opcode::VTESTPD | Opcode::VTESTPS | @@ -2220,6 +2783,8 @@ impl Colorize for Opcode { Opcode::FXRSTOR | Opcode::LDMXCSR | Opcode::STMXCSR | + Opcode::VLDMXCSR | + Opcode::VSTMXCSR | Opcode::XSAVE | Opcode::XSAVEC | Opcode::XSAVES | @@ -2327,6 +2892,12 @@ impl Colorize for Opcode { Opcode::SENDUIPI | Opcode::XSUSLDTRK | Opcode::XRESLDTRK | + Opcode::BNDMK | + Opcode::BNDCL | + Opcode::BNDCU | + Opcode::BNDCN | + Opcode::BNDLDX | + Opcode::BNDSTX | Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } Opcode::CRC32 | diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 57508e4..88cae67 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -1293,6 +1293,7 @@ pub enum Opcode { VMOVDDUP, VPSHUFLW, + VPSHUFHW, VHADDPS, VHSUBPS, VADDSUBPS, @@ -1465,6 +1466,7 @@ pub enum Opcode { VPABSD, VPABSW, VPACKSSDW, + VPACKUSDW, VPACKSSWB, VPACKUSWB, VPADDB, @@ -1502,6 +1504,8 @@ pub enum Opcode { VPCMPGTD, VPCMPGTQ, VPCMPGTW, + VPCMPESTRI, + VPCMPESTRM, VPCMPISTRI, VPCMPISTRM, VPERM2F128, @@ -1523,7 +1527,7 @@ pub enum Opcode { VPHADDD, VPHADDSW, VPHADDW, - VPHADDUBSW, + VPMADDUBSW, VPHMINPOSUW, VPHSUBD, VPHSUBSW, @@ -1541,8 +1545,11 @@ pub enum Opcode { VPMAXUB, VPMAXUW, VPMAXUD, + VPMINSB, VPMINSW, VPMINSD, + VPMINUB, + VPMINUW, VPMINUD, VPMOVMSKB, VPMOVSXBD, @@ -1631,6 +1638,9 @@ pub enum Opcode { VXORPD, VXORPS, VZEROUPPER, + VZEROALL, + VLDMXCSR, + VSTMXCSR, PCLMULQDQ, AESKEYGENASSIST, @@ -1960,6 +1970,287 @@ pub enum Opcode { // TSXLDTRK XSUSLDTRK, XRESLDTRK, + + // AVX512F + VALIGND, + VALIGNQ, + VBLENDMPD, + VBLENDMPS, + VCOMPRESSPD, + VCOMPRESSPS, + VCVTPD2UDQ, + VCVTTPD2UDQ, + VCVTPS2UDQ, + VCVTTPS2UDQ, + VCVTQQ2PD, + VCVTQQ2PS, + VCVTSD2USI, + VCVTTSD2USI, + VCVTSS2USI, + VCVTTSS2USI, + VCVTUDQ2PD, + VCVTUDQ2PS, + VCVTUSI2USD, + VCVTUSI2USS, + VEXPANDPD, + VEXPANDPS, + VEXTRACTF32X4, + VEXTRACTF64X4, + VEXTRACTI32X4, + VEXTRACTI64X4, + VFIXUPIMMPD, + VFIXUPIMMPS, + VFIXUPIMMSD, + VFIXUPIMMSS, + VGETEXPPD, + VGETEXPPS, + VGETEXPSD, + VGETEXPSS, + VGETMANTPD, + VGETMANTPS, + VGETMANTSD, + VGETMANTSS, + VINSERTF32X4, + VINSERTF64X4, + VMOVDQA32, + VMOVDQA64, + VMOVDQU32, + VMOVDQU64, + VPBLENDMD, + VPBLENDMQ, + VPCMPD, + VPCMPUD, + VPCMPQ, + VPCMPUQ, + VPCOMPRESSQ, + VPCOMPRESSD, + VPERMI2D, + VPERMI2Q, + VPERMI2PD, + VPERMI2PS, + VPERMT2D, + VPERMT2Q, + VPERMT2PD, + VPERMT2PS, + VPMAXSQ, + VPMAXUQ, + VPMINSQ, + VPMINUQ, + VPMOVSQB, + VPMOVUSQB, + VPMOVSQW, + VPMOVUSQW, + VPMOVSQD, + VPMOVUSQD, + VPMOVSDB, + VPMOVUSDB, + VPMOVSDW, + VPMOVUSDW, + VPROLD, + VPROLQ, + VPROLVD, + VPROLVQ, + VPRORD, + VPRORQ, + VPRORRD, + VPRORRQ, + VPSCATTERDD, + VPSCATTERDQ, + VPSCATTERQD, + VPSCATTERQQ, + VPSRAQ, + VPSRAVQ, + VPTESTNMD, + VPTESTNMQ, + VPTERLOGD, + VPTERLOGQ, + VPTESTMD, + VPTESTMQ, + VRCP14PD, + VRCP14PS, + VRCP14SD, + VRCP14SS, + VRNDSCALEPD, + VRNDSCALEPS, + VRNDCSALESD, + VRNDSCALESS, + VRSQRT14PD, + VRSQRT14PS, + VRSQRT14SD, + VRSQRT14SS, + VSCALEDPD, + VSCALEDPS, + VSCALEDSD, + VSCALEDSS, + VSCATTERDD, + VSCATTERDQ, + VSCATTERQD, + VSCATTERQQ, + VSHUFF32X4, + VSHUFF64X2, + VSHUFI32X4, + VSHUFI64X2, + + // AVX512DQ + VCVTTPD2QQ, + VCVTPD2QQ, + VCVTTPD2UQQ, + VCVTPD2UQQ, + VCVTTPS2QQ, + VCVTPS2QQ, + VCVTTPS2UQQ, + VCVTPS2UQQ, + VCVTUQQ2PD, + VCVTUQQ2PS, + VEXTRACTF64X2, + VEXTRACTI64X2, + VFPCLASSPD, + VFPCLASSPS, + VFPCLASSSD, + VFPCLASSSS, + VINSERTF64X2, + VINSERTI64X2, + VPMOVM2D, + VPMOVM2Q, + VPMOVB2D, + VPMOVQ2M, + VPMULLLQ, + VRANGEPD, + VRANGEPS, + VRANGESD, + VRANGESS, + VREDUCEPD, + VREDUCEPS, + VREDUCESD, + VREDUCESS, + + // AVX512BW + VDBPSADBW, + VMOVDQU8, + VMOVDQU16, + VPBLENDMB, + VPBLENDMW, + VPCMPB, + VPCMPUB, + VPCMPW, + VPCMPUW, + VPERMW, + VPERMI2B, + VPERMI2W, + VPMOVM2B, + VPMOVM2W, + VPMOVB2M, + VPMOVW2M, + VPMOVSWB, + VPMOVUSWB, + VPSLLVW, + VPSRAVW, + VPSRLVW, + VPTESTNMB, + VPTESTNMW, + VPTESTMB, + VPTESTMW, + + // AVX512CD + VPBROADCASTM, + VPCONFLICTD, + VPCONFLICTQ, + VPLZCNTD, + VPLZCNTQ, + + KUNPCKBW, + KUNPCKWD, + KUNPCKDQ, + + KADDB, + KANDB, + KANDNB, + KMOVB, + KNOTB, + KORB, + KORTESTB, + KSHIFTLB, + KSHIFTRB, + KTESTB, + KXNORB, + KXORB, + KADDW, + KANDW, + KANDNW, + KMOVW, + KNOTW, + KORW, + KORTESTW, + KSHIFTLW, + KSHIFTRW, + KTESTW, + KXNORW, + KXORW, + KADDD, + KANDD, + KANDND, + KMOVD, + KNOTD, + KORD, + KORTESTD, + KSHIFTLD, + KSHIFTRD, + KTESTD, + KXNORD, + KXORD, + KADDQ, + KANDQ, + KANDNQ, + KMOVQ, + KNOTQ, + KORQ, + KORTESTQ, + KSHIFTLQ, + KSHIFTRQ, + KTESTQ, + KXNORQ, + KXORQ, + + // AVX512ER + VEXP2PD, + VEXP2PS, + VEXP2SD, + VEXP2SS, + VRCP28PD, + VRCP28PS, + VRCP28SD, + VRCP28SS, + VRSQRT28PD, + VRSQRT28PS, + VRSQRT28SD, + VRSQRT28SS, + + // AVX512PF + VGATHERPF0DPD, + VGATHERPF0DPS, + VGATHERPF0QPD, + VGATHERPF0QPS, + VGATHERPF1DPD, + VGATHERPF1DPS, + VGATHERPF1QPD, + VGATHERPF1QPS, + VSCATTERPF0DPD, + VSCATTERPF0DPS, + VSCATTERPF0QPD, + VSCATTERPF0QPS, + VSCATTERPF1DPD, + VSCATTERPF1DPS, + VSCATTERPF1QPD, + VSCATTERPF1QPS, + + // MPX + BNDMK, + BNDCL, + BNDCU, + BNDCN, + BNDMOV, + BNDLDX, + BNDSTX, } #[derive(Debug)] @@ -2936,6 +3227,7 @@ impl InstDecoder { // AVX... Opcode::VMOVDDUP | Opcode::VPSHUFLW | + Opcode::VPSHUFHW | Opcode::VHADDPS | Opcode::VHSUBPS | Opcode::VADDSUBPS | @@ -3099,6 +3391,7 @@ impl InstDecoder { Opcode::VPABSD | Opcode::VPABSW | Opcode::VPACKSSDW | + Opcode::VPACKUSDW | Opcode::VPACKSSWB | Opcode::VPACKUSWB | Opcode::VPADDB | @@ -3136,6 +3429,8 @@ impl InstDecoder { Opcode::VPCMPGTD | Opcode::VPCMPGTQ | Opcode::VPCMPGTW | + Opcode::VPCMPESTRI | + Opcode::VPCMPESTRM | Opcode::VPCMPISTRI | Opcode::VPCMPISTRM | Opcode::VPERM2F128 | @@ -3157,7 +3452,7 @@ impl InstDecoder { Opcode::VPHADDD | Opcode::VPHADDSW | Opcode::VPHADDW | - Opcode::VPHADDUBSW | + Opcode::VPMADDUBSW | Opcode::VPHMINPOSUW | Opcode::VPHSUBD | Opcode::VPHSUBSW | @@ -3175,8 +3470,11 @@ impl InstDecoder { Opcode::VPMAXUB | Opcode::VPMAXUW | Opcode::VPMAXUD | + Opcode::VPMINSB | Opcode::VPMINSW | Opcode::VPMINSD | + Opcode::VPMINUB | + Opcode::VPMINUW | Opcode::VPMINUD | Opcode::VPMOVMSKB | Opcode::VPMOVSXBD | @@ -3264,7 +3562,10 @@ impl InstDecoder { Opcode::VUNPCKLPS | Opcode::VXORPD | Opcode::VXORPS | - Opcode::VZEROUPPER => { + Opcode::VZEROUPPER | + Opcode::VZEROALL | + Opcode::VLDMXCSR | + Opcode::VSTMXCSR => { // TODO: check a table for these if !self.avx() { inst.opcode = Opcode::Invalid; diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs index 9d51ba4..401c61f 100644 --- a/src/long_mode/vex.rs +++ b/src/long_mode/vex.rs @@ -39,23 +39,33 @@ enum VEXOperandCode { VMOVSD_10, VMOVSD_11, VMOVSS_11, + VMOVLPS_12, + VMOVHPS_16, E_G_xmm, U_G_xmm, M_G_xmm, G_M_xmm, G_U_xmm, + Gd_U_xmm, E_G_xmm_imm8, - U_G_xmm_imm8, + Ud_G_xmm_imm8, + Ud_G_xmm, + Ud_G_ymm, E_G_ymm, U_G_ymm, M_G_ymm, G_E_ymm, G_M_ymm, G_U_ymm, + Gd_U_ymm, E_V_G_ymm, E_V_G_xmm, E_xmm_G_ymm_imm8, Ev_G_xmm_imm8, + Eb_G_xmm_imm8, + Ew_G_xmm_imm8, + Ed_G_xmm_imm8, + Eq_G_xmm_imm8, G_Ex_V_xmm, G_Ey_V_ymm, G_E_xmm, @@ -68,12 +78,17 @@ enum VEXOperandCode { G_V_ymm_E_xmm, M_V_G_xmm, M_V_G_ymm, + G_V_xmm_Ed, + G_V_xmm_Eq, G_V_E_xmm, G_V_E_xmm_imm8, G_V_E_xmm_xmm4, G_V_E_ymm, G_V_E_ymm_imm8, G_V_E_ymm_ymm4, + G_V_xmm_Eb_imm8, + G_V_xmm_Ed_imm8, + G_V_xmm_Eq_imm8, G_V_M_xmm, G_V_M_ymm, V_xmm_G_ymm_E_ymm_imm8, @@ -86,7 +101,12 @@ enum VEXOperandCode { G_E_V, G_V_E, G_E_Ib, + VCVT_Gd_Ed_xmm, + VCVT_Gd_Eq_xmm, + VCVT_Gq_Ed_xmm, + VCVT_Gq_Eq_xmm, BMI1_F3, + MXCSR, } #[inline(never)] @@ -103,7 +123,6 @@ pub(crate) fn three_byte_vex>(bytes: &mut T, instruction: & _ => { unreachable!("p is two bits"); } }; let m = vex_byte_one & 0b11111; -// println!("m: {:05b}", m); let m = match m { 0b00001 => VEXOpcodeMap::Map0F, 0b00010 => VEXOpcodeMap::Map0F38, @@ -151,6 +170,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst match operand_code { VEXOperandCode::VPS_71 => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLW; @@ -177,7 +200,14 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_71_L => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { + 0b001 => { + instruction.opcode = Opcode::VPSLLW; + } 0b010 => { instruction.opcode = Opcode::VPSRLW; } @@ -203,6 +233,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_72 => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLD; @@ -229,6 +263,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_72_L => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLD; @@ -255,6 +293,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_73 => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLQ; @@ -284,6 +326,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst } VEXOperandCode::VPS_73_L => { let modrm = read_modrm(bytes, length)?; + if modrm & 0xc0 != 0xc0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } match (modrm >> 3) & 0b111 { 0b000 | 0b001 | @@ -331,6 +377,10 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 3; }, other => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } instruction.operands[1] = other; instruction.operand_count = 2; } @@ -343,23 +393,171 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst 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[1] = OperandSpec::RegRRR; + instruction.operands[2] = OperandSpec::RegRRR; match mem_oper { OperandSpec::RegMMM => { - instruction.operands[0] = OperandSpec::RegVex; - instruction.operands[2] = OperandSpec::RegMMM; + instruction.operands[0] = OperandSpec::RegMMM; + instruction.operands[1] = OperandSpec::RegVex; instruction.operand_count = 3; }, other => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } instruction.operands[0] = other; + instruction.operands[1] = instruction.operands[2]; instruction.operand_count = 2; } } Ok(()) }, + VEXOperandCode::VMOVLPS_12 => { + let modrm = read_modrm(bytes, length)?; + instruction.opcode = if modrm & 0xc0 == 0xc0 { + Opcode::VMOVHLPS + } else { + Opcode::VMOVLPS + }; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operand_count = 3; + Ok(()) + } + VEXOperandCode::VMOVHPS_16 => { + let modrm = read_modrm(bytes, length)?; + instruction.opcode = if modrm & 0xc0 == 0xc0 { + Opcode::VMOVLHPS + } else { + Opcode::VMOVHPS + }; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operand_count = 3; + Ok(()) + } VEXOperandCode::Nothing => { Ok(()) }, + VEXOperandCode::Eb_G_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.mem_size = 1; + instruction.operand_count = 3; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + Ok(()) + }, + VEXOperandCode::Ew_G_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.mem_size = 2; + instruction.operand_count = 3; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + Ok(()) + }, + VEXOperandCode::Ed_G_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.mem_size = 4; + instruction.operand_count = 3; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + Ok(()) + }, + VEXOperandCode::Eq_G_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 8, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.mem_size = 8; + instruction.operand_count = 3; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + Ok(()) + }, + VEXOperandCode::G_V_xmm_Eb_imm8 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + instruction.vex_reg.bank = RegisterBank::X; + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[3] = OperandSpec::ImmU8; + instruction.mem_size = 1; + instruction.operand_count = 4; + Ok(()) + } + VEXOperandCode::G_V_xmm_Ed_imm8 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + instruction.vex_reg.bank = RegisterBank::X; + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[3] = OperandSpec::ImmU8; + instruction.mem_size = 4; + instruction.operand_count = 4; + Ok(()) + } + VEXOperandCode::G_V_xmm_Eq_imm8 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + instruction.vex_reg.bank = RegisterBank::X; + let mem_oper = read_E(bytes, instruction, modrm, 8, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[3] = OperandSpec::ImmU8; + instruction.mem_size = 8; + instruction.operand_count = 4; + Ok(()) + } VEXOperandCode::Ev_G_xmm_imm8 => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; @@ -432,11 +630,165 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 2; Ok(()) } - _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 => { + VEXOperandCode::VCVT_Gd_Ed_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 4; + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::VCVT_Gd_Eq_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 8; + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::VCVT_Gq_Ed_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Q); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 4; + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::VCVT_Gq_Eq_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Q); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + if let OperandSpec::RegMMM = mem_oper { + instruction.modrm_mmm.bank = RegisterBank::X; + } else { + instruction.mem_size = 8; + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + op @ VEXOperandCode::E_G_xmm | + op @ VEXOperandCode::U_G_xmm | + op @ VEXOperandCode::M_G_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, 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)?; + match (op, mem_oper) { + (VEXOperandCode::E_G_xmm, OperandSpec::RegMMM) => { + /* this is the only accepted operand */ + } + (VEXOperandCode::U_G_xmm, _) | + (VEXOperandCode::M_G_xmm, OperandSpec::RegMMM) => { + return Err(DecodeError::InvalidOperand); + } + (VEXOperandCode::M_G_xmm, _) | // otherwise it's memory-constrained and a memory operand + (_, _) => { // ... or unconstrained + /* and this is always accepted */ + } + } + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::Ud_G_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::Ud_G_ymm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + Ok(()) + } + VEXOperandCode::Ud_G_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + Ok(()) + } + VEXOperandCode::E_G_xmm_imm8 => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); @@ -447,35 +799,84 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + Ok(()) + } + _op @ VEXOperandCode::E_xmm_G_ymm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + Ok(()) + } + + VEXOperandCode::Gd_U_xmm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::E_xmm_G_ymm_imm8 => { + VEXOperandCode::Gd_U_ymm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); - let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - instruction.operands[0] = mem_oper; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.imm = read_imm_unsigned(bytes, 1, length)?; - instruction.operands[2] = OperandSpec::ImmU8; - instruction.operand_count = 3; + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; Ok(()) } - _op @ VEXOperandCode::G_M_xmm | - _op @ VEXOperandCode::G_U_xmm | - _op @ VEXOperandCode::G_E_xmm | - _op @ VEXOperandCode::G_E_xmm_imm8 => { + op @ VEXOperandCode::G_M_xmm | + op @ VEXOperandCode::G_U_xmm | + op @ VEXOperandCode::G_E_xmm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(bytes, length)?; + match (op, modrm & 0xc0) { + (VEXOperandCode::G_U_xmm, 0xc0) => { + /* this is the only accepted operand */ + } + (VEXOperandCode::G_U_xmm, _) | + (VEXOperandCode::G_M_xmm, 0xc0) => { + return Err(DecodeError::InvalidOperand); + } + (VEXOperandCode::G_M_xmm, _) | // otherwise it's memory-constrained and a memory operand + (_, _) => { // ... or unconstrained + /* and this is always accepted */ + } + } 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)?; @@ -541,14 +942,27 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst Ok(()) } - _op @ VEXOperandCode::E_G_ymm | - _op @ VEXOperandCode::U_G_ymm | - _op @ VEXOperandCode::M_G_ymm => { + op @ VEXOperandCode::E_G_ymm | + op @ VEXOperandCode::U_G_ymm | + op @ VEXOperandCode::M_G_ymm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(bytes, length)?; + match (op, modrm & 0xc0) { + (VEXOperandCode::U_G_ymm, 0xc0) => { + /* this is the only accepted operand */ + } + (VEXOperandCode::U_G_ymm, _) | + (VEXOperandCode::M_G_ymm, 0xc0) => { + return Err(DecodeError::InvalidOperand); + } + (VEXOperandCode::M_G_ymm, _) | // otherwise it's memory-constrained and a memory operand + (_, _) => { // ... or unconstrained + /* and this is always accepted */ + } + } 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)?; @@ -558,14 +972,27 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst Ok(()) } - _op @ VEXOperandCode::G_M_ymm | - _op @ VEXOperandCode::G_U_ymm | - _op @ VEXOperandCode::G_E_ymm => { + op @ VEXOperandCode::G_M_ymm | + op @ VEXOperandCode::G_U_ymm | + op @ VEXOperandCode::G_E_ymm => { if instruction.vex_reg.num != 0 { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(bytes, length)?; + match (op, modrm & 0xc0) { + (VEXOperandCode::G_U_ymm, 0xc0) => { + /* this is the only accepted operand */ + } + (VEXOperandCode::G_U_ymm, _) | + (VEXOperandCode::G_M_ymm, 0xc0) => { + return Err(DecodeError::InvalidOperand); + } + (VEXOperandCode::G_M_ymm, _) | // otherwise it's memory-constrained and a memory operand + (_, _) => { // ... or unconstrained + /* and this is always accepted */ + } + } 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)?; @@ -614,8 +1041,22 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 3; Ok(()) } - _op @ VEXOperandCode::G_V_M_xmm | - _op @ VEXOperandCode::G_V_E_xmm => { + VEXOperandCode::G_V_M_xmm => { + let modrm = read_modrm(bytes, 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)?; + if mem_oper == OperandSpec::RegMMM { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + Ok(()) + } + VEXOperandCode::G_V_E_xmm => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); @@ -626,6 +1067,28 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.operand_count = 3; Ok(()) } + VEXOperandCode::G_V_xmm_Ed => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + Ok(()) + } + VEXOperandCode::G_V_xmm_Eq => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 8, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.operand_count = 3; + Ok(()) + } _op @ VEXOperandCode::G_V_E_xmm_imm8 => { let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = @@ -786,7 +1249,47 @@ fn read_vex_operands>(bytes: &mut T, instruction: &mut Inst instruction.vex_reg.bank = bank; Ok(()) } + VEXOperandCode::MXCSR => { + let modrm = read_modrm(bytes, length)?; + instruction.opcode = match (modrm >> 3) & 7 { + 2 => { + Opcode::VLDMXCSR + } + 3 => { + Opcode::VSTMXCSR + } + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + }; + let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; + if let OperandSpec::RegMMM = mem_oper { + return Err(DecodeError::InvalidOperand); + } + instruction.operands[0] = mem_oper; + instruction.operand_count = 1; + Ok(()) + } + VEXOperandCode::G_E_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, 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; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + Ok(()) + } VEXOperandCode::G_E_ymm_imm8 => { + if instruction.vex_reg.num != 0 { + return Err(DecodeError::InvalidOperand); + } let modrm = read_modrm(bytes, length)?; instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); @@ -877,9 +1380,12 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 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, ..), + 0x12 => (Opcode::Invalid, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::VMOVLPS_12 + }), 0x13 => (Opcode::VMOVLPS, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -896,9 +1402,12 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm }), - // ugh -// 0x16 => (Opcode::VMOVHPS, ..), -// 0x16 => (Opcode::VMOVLHPS, ..), + 0x16 => (Opcode::Invalid, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::VMOVHPS_16 + }), 0x17 => (Opcode::VMOVHPS, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -923,9 +1432,9 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0x2e => (Opcode::VUCOMISS, VEXOperandCode::G_E_xmm), 0x2f => (Opcode::VCOMISS, VEXOperandCode::G_E_xmm), 0x50 => (Opcode::VMOVMSKPS, if L { - VEXOperandCode::U_G_ymm + VEXOperandCode::Ud_G_ymm } else { - VEXOperandCode::U_G_xmm + VEXOperandCode::Ud_G_xmm }), 0x51 => (Opcode::VSQRTPS, if L { VEXOperandCode::G_E_ymm @@ -973,7 +1482,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm }), 0x5A => (Opcode::VCVTPS2PD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), @@ -1003,6 +1512,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm }), 0x77 => (Opcode::VZEROUPPER, VEXOperandCode::Nothing), + 0xAE => (Opcode::Invalid, if L { + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::MXCSR + }), 0xC2 => (Opcode::VCMPPS, if L { VEXOperandCode::G_V_E_ymm_imm8 } else { @@ -1055,12 +1569,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm }), - 0x16 => (Opcode::VMOVHPD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_M_xmm - }), + 0x16 => (Opcode::VMOVHPD, VEXOperandCode::G_V_M_xmm), 0x17 => (Opcode::VMOVHPD, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -1085,9 +1594,9 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0x2e => (Opcode::VUCOMISD, VEXOperandCode::G_E_xmm), 0x2f => (Opcode::VCOMISD, VEXOperandCode::G_E_xmm), 0x50 => (Opcode::VMOVMSKPD, if L { - VEXOperandCode::G_U_ymm + VEXOperandCode::Gd_U_ymm } else { - VEXOperandCode::G_U_xmm + VEXOperandCode::Gd_U_xmm }), 0x51 => (Opcode::VSQRTPD, if L { VEXOperandCode::G_E_ymm @@ -1310,9 +1819,9 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::E_G_xmm }), 0xC2 => (Opcode::VCMPPD, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_E_ymm_imm8 } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_V_E_xmm_imm8 }), 0xC4 => (Opcode::VPINSRW, if L { instruction.opcode = Opcode::Invalid; @@ -1324,12 +1833,12 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::U_G_xmm_imm8 + VEXOperandCode::Ud_G_xmm_imm8 }), 0xC6 => (Opcode::VSHUFPD, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_E_ymm_imm8 } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_V_E_xmm_imm8 }), 0xD0 => (Opcode::VADDSUBPD, if L { VEXOperandCode::G_V_E_ymm @@ -1337,17 +1846,17 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm }), 0xD1 => (Opcode::VPSRLW, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), 0xD2 => (Opcode::VPSRLD, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), 0xD3 => (Opcode::VPSRLQ, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), @@ -1368,9 +1877,9 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0xD7 => (Opcode::VPMOVMSKB, if L { - VEXOperandCode::U_G_ymm + VEXOperandCode::Ud_G_ymm } else { - VEXOperandCode::U_G_xmm + VEXOperandCode::Ud_G_xmm }), 0xD8 => (Opcode::VPSUBUSB, if L { VEXOperandCode::G_V_E_ymm @@ -1382,6 +1891,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm }), + 0xDA => (Opcode::VPMINSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), 0xDB => (Opcode::VPAND, if L { VEXOperandCode::G_V_E_ymm } else { @@ -1521,7 +2035,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_xmm + VEXOperandCode::G_U_xmm }), 0xF8 => (Opcode::VPSUBB, if L { VEXOperandCode::G_V_E_ymm @@ -1574,24 +2088,24 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0x2a => (Opcode::VCVTSI2SD, if instruction.prefixes.vex().w() { - VEXOperandCode::G_V_E_xmm // 64-bit last operand + VEXOperandCode::G_V_xmm_Eq // 64-bit last operand } else { - VEXOperandCode::G_V_E_xmm // 32-bit last operand + VEXOperandCode::G_V_xmm_Ed // 32-bit last operand }), 0x2c => (Opcode::VCVTTSD2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit + VEXOperandCode::VCVT_Gq_Eq_xmm // 64-bit } else { - VEXOperandCode::G_E_xmm // 32-bit + VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit }), 0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit + VEXOperandCode::VCVT_Gq_Eq_xmm // 64-bit } else { - VEXOperandCode::G_E_xmm // 32-bit + VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit }), 0x51 => (Opcode::VSQRTSD, VEXOperandCode::G_V_E_xmm), 0x58 => (Opcode::VADDSD, VEXOperandCode::G_V_E_xmm), 0x59 => (Opcode::VMULSD, VEXOperandCode::G_V_E_xmm), - 0x5a => (Opcode::CVTSD2SS, VEXOperandCode::G_V_E_xmm), + 0x5a => (Opcode::VCVTSD2SS, VEXOperandCode::G_V_E_xmm), 0x5c => (Opcode::VSUBSD, VEXOperandCode::G_V_E_xmm), 0x5d => (Opcode::VMINSD, VEXOperandCode::G_V_E_xmm), 0x5e => (Opcode::VDIVSD, VEXOperandCode::G_V_E_xmm), @@ -1625,7 +2139,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0xf0 => (Opcode::VLDDQU, if L { VEXOperandCode::G_M_ymm } else { - VEXOperandCode::G_M_ymm + VEXOperandCode::G_M_xmm }), _ => { instruction.opcode = Opcode::Invalid; @@ -1640,19 +2154,19 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 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 }), 0x2a => (Opcode::VCVTSI2SS, if instruction.prefixes.vex().w() { - VEXOperandCode::G_V_E_xmm // 64-bit last operand + VEXOperandCode::G_V_xmm_Eq } else { - VEXOperandCode::G_V_E_xmm // 32-bit last operand + VEXOperandCode::G_V_xmm_Ed }), 0x2c => (Opcode::VCVTTSS2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit + VEXOperandCode::VCVT_Gq_Eq_xmm } else { - VEXOperandCode::G_E_xmm // 32-bit + VEXOperandCode::VCVT_Gd_Ed_xmm }), - 0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit + 0x2d => (Opcode::VCVTSS2SI, if instruction.prefixes.vex().w() { + VEXOperandCode::VCVT_Gq_Eq_xmm } else { - VEXOperandCode::G_E_xmm // 32-bit + VEXOperandCode::VCVT_Gd_Ed_xmm }), 0x51 => (Opcode::VSQRTSS, VEXOperandCode::G_V_E_xmm), 0x52 => (Opcode::VRSQRTSS, VEXOperandCode::G_V_E_xmm), @@ -1666,7 +2180,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & 0x5e => (Opcode::VDIVSS, VEXOperandCode::G_V_E_xmm), 0x5f => (Opcode::VMAXSS, VEXOperandCode::G_V_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 }), + 0x70 => (Opcode::VPSHUFHW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), 0x7e => (Opcode::VMOVQ, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), 0x7f => (Opcode::VMOVDQU, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), 0xc2 => (Opcode::VCMPSS, VEXOperandCode::G_V_E_xmm_imm8), @@ -1704,7 +2222,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm }), - 0x04 => (Opcode::VPHADDUBSW, if L { + 0x04 => (Opcode::VPMADDUBSW, if L { VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm @@ -1780,16 +2298,26 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_E_xmm }), - 0x18 => (Opcode::VBROADCASTSS, if L { - VEXOperandCode::G_E_ymm + 0x18 => if instruction.prefixes.vex().w() { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_xmm - }), - 0x19 => (Opcode::VBROADCASTSD, if L { - VEXOperandCode::G_E_ymm + (Opcode::VBROADCASTSS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }) + }, + 0x19 => if instruction.prefixes.vex().w() { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_xmm - }), + (Opcode::VBROADCASTSD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }) + } 0x1A => (Opcode::VBROADCASTF128, if L { VEXOperandCode::G_M_ymm } else { @@ -1812,32 +2340,32 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0x20 => (Opcode::VPMOVSXBW, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x21 => (Opcode::VPMOVSXBD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x22 => (Opcode::VPMOVSXBQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x23 => (Opcode::VPMOVSXWD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x24 => (Opcode::VPMOVSXWQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x25 => (Opcode::VPMOVSXDQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), @@ -1856,6 +2384,11 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_M_xmm }), + 0x2B => (Opcode::VPACKUSDW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), 0x2C => (Opcode::VMASKMOVPS, if L { VEXOperandCode::G_V_M_ymm } else { @@ -1877,35 +2410,34 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::M_V_G_xmm }), 0x30 => (Opcode::VPMOVZXBW, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x31 => (Opcode::VPMOVZXBD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x32 => (Opcode::VPMOVZXBQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x33 => (Opcode::VPMOVZXWD, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x34 => (Opcode::VPMOVZXWQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), 0x35 => (Opcode::VPMOVZXDQ, if L { - VEXOperandCode::G_E_ymm + VEXOperandCode::G_ymm_E_xmm } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_E_xmm }), 0x36 => (Opcode::VPERMD, if L { VEXOperandCode::G_V_E_ymm @@ -1918,11 +2450,21 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm }), + 0x38 => (Opcode::VPMINSB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), 0x39 => (Opcode::VPMINSD, if L { VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), + 0x3A => (Opcode::VPMINUW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), 0x3B => (Opcode::VPMINUD, if L { VEXOperandCode::G_V_E_ymm } else { @@ -2443,26 +2985,22 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_E_xmm }), 0xDC => (Opcode::VAESENC, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), 0xDD => (Opcode::VAESENCLAST, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), 0xDE => (Opcode::VAESDEC, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), 0xDF => (Opcode::VAESDECLAST, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + VEXOperandCode::G_V_E_ymm } else { VEXOperandCode::G_V_E_xmm }), @@ -2576,17 +3114,17 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & VEXOperandCode::G_V_E_xmm }), 0x04 => (Opcode::VPERMILPS, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_E_ymm_imm8 } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_E_xmm_imm8 }), 0x05 => (Opcode::VPERMILPD, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_E_ymm_imm8 } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_E_xmm_imm8 }), 0x06 => (Opcode::VPERM2F128, if L { - VEXOperandCode::G_V_E_ymm + VEXOperandCode::G_V_E_ymm_imm8 } else { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); @@ -2601,6 +3139,16 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_E_xmm_imm8 }), + 0x0A => (Opcode::VROUNDSS, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x0B => (Opcode::VROUNDSD, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), 0x0C => (Opcode::VBLENDPS, if L { VEXOperandCode::G_V_E_ymm_imm8 } else { @@ -2625,20 +3173,20 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::Ev_G_xmm_imm8 + VEXOperandCode::Eb_G_xmm_imm8 }), 0x15 => (Opcode::VPEXTRW, if L || instruction.prefixes.vex().w() { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::Ev_G_xmm_imm8 + VEXOperandCode::Ew_G_xmm_imm8 }), 0x16 => if instruction.prefixes.vex().w() { (Opcode::VPEXTRQ, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_ymm_imm8 + VEXOperandCode::Eq_G_xmm_imm8 }) } else { (Opcode::VPEXTRD, if L { @@ -2646,27 +3194,37 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & return Err(DecodeError::InvalidOpcode); } else { // varies on W - VEXOperandCode::Ev_G_xmm_imm8 + VEXOperandCode::Ed_G_xmm_imm8 }) }, 0x17 => (Opcode::VEXTRACTPS, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_ymm_imm8 + VEXOperandCode::Ed_G_xmm_imm8 }), - 0x18 => (Opcode::VINSERTF128, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { + 0x18 => if instruction.prefixes.vex().w() { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); - }), - 0x19 => (Opcode::VEXTRACTF128, if L { - VEXOperandCode::E_xmm_G_ymm_imm8 } else { + (Opcode::VINSERTF128, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }) + }, + 0x19 => if instruction.prefixes.vex().w() { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); - }), + } else { + (Opcode::VEXTRACTF128, if L { + VEXOperandCode::E_xmm_G_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }) + }, 0x1D => (Opcode::VCVTPS2PH, if L { VEXOperandCode::E_xmm_G_ymm_imm8 } else { @@ -2676,7 +3234,7 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm_imm8 + VEXOperandCode::G_V_xmm_Eb_imm8 }), 0x21 => (Opcode::VINSERTPS, if L { instruction.opcode = Opcode::Invalid; @@ -2689,14 +3247,14 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm_imm8 + VEXOperandCode::G_V_xmm_Eq_imm8 }) } else { (Opcode::VPINSRD, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm_imm8 + VEXOperandCode::G_V_xmm_Ed_imm8 }) }, 0x38 => (Opcode::VINSERTI128, if L { @@ -2749,10 +3307,27 @@ fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: & } else { VEXOperandCode::G_V_E_xmm_xmm4 }), - 0x4C => (Opcode::VPBLENDVB, if L { - VEXOperandCode::G_V_E_ymm_ymm4 + 0x4C => if instruction.prefixes.vex().w() { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm_xmm4 + (Opcode::VPBLENDVB, if L { + VEXOperandCode::G_V_E_ymm_ymm4 + } else { + VEXOperandCode::G_V_E_xmm_xmm4 + }) + }, + 0x60 => (Opcode::VPCMPESTRM, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x61 => (Opcode::VPCMPESTRI, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm_imm8 }), 0x62 => (Opcode::VPCMPISTRM, if L { instruction.opcode = Opcode::Invalid; -- cgit v1.1