aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/long_mode/display.rs581
-rw-r--r--src/long_mode/mod.rs307
-rw-r--r--src/long_mode/vex.rs815
-rw-r--r--test/long_mode/mod.rs998
4 files changed, 2561 insertions, 140 deletions
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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result {
match self {
@@ -1408,6 +1704,7 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::VMULPS |
Opcode::VMULSD |
Opcode::VMULSS |
+ Opcode::VPMULLLQ |
Opcode::VPABSB |
Opcode::VPABSD |
Opcode::VPABSW |
@@ -1451,6 +1748,34 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::SUB |
Opcode::POPCNT |
Opcode::LZCNT |
+ Opcode::VPLZCNTD |
+ Opcode::VPLZCNTQ |
Opcode::BT |
Opcode::BTS |
Opcode::BTR |
@@ -1702,6 +2043,42 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::VBROADCASTI128 |
Opcode::VBROADCASTSD |
Opcode::VBROADCASTSS |
+ Opcode::VPBROADCASTM |
Opcode::VEXTRACTF128 |
Opcode::VEXTRACTI128 |
Opcode::VEXTRACTPS |
@@ -1803,10 +2212,48 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::VPCMPGTD |
Opcode::VPCMPGTQ |
Opcode::VPCMPGTW |
+ Opcode::VPCMPESTRI |
+ Opcode::VPCMPESTRM |
Opcode::VPCMPISTRI |
Opcode::VPCMPISTRM |
Opcode::VPMAXSB |
@@ -2137,9 +2687,22 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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 <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for Opcode {
Opcode::FXRSTOR |
Opcode::LDMXCSR |
Opcode::STMXCSR |
+ Opcode::VLDMXCSR |
+ Opcode::VSTMXCSR |
Opcode::XSAVE |
Opcode::XSAVEC |
Opcode::XSAVES |
@@ -2327,6 +2892,12 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> 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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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,85 @@ fn read_vex_operands<T: Iterator<Item=u8>>(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);
@@ -445,11 +717,93 @@ fn read_vex_operands<T: Iterator<Item=u8>>(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)?;
+ 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);
+ }
+ 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] = 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;
@@ -467,16 +821,63 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst
Ok(())
}
- _op @ VEXOperandCode::G_M_xmm |
- _op @ VEXOperandCode::G_U_xmm |
- _op @ VEXOperandCode::G_E_xmm |
- _op @ VEXOperandCode::G_E_xmm_imm8 => {
+ 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(())
+ }
+ 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::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 => {
+ 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)?;
instruction.operands[0] = OperandSpec::RegRRR;
@@ -541,14 +942,27 @@ fn read_vex_operands<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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,12 +1041,48 @@ fn read_vex_operands<T: Iterator<Item=u8>>(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);
+ let mem_oper = read_E_xmm(bytes, instruction, modrm, 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_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;
@@ -786,7 +1249,47 @@ fn read_vex_operands<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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;
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 1895f6e..c6b895c 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1401,6 +1401,7 @@ fn test_misc() {
fn evex() {
test_display(&[0x62, 0xf2, 0x7d, 0x48, 0x2a, 0x44, 0x40, 0x01], "vmovntdqa zmm0, [rax + rax*2 + 0x40]");
test_display(&[0x62, 0xf2, 0x7d, 0x08, 0x2a, 0x44, 0x40, 0x01], "vmovntdqa xmm0, [rax + rax*2 + 0x10]");
+ test_display(&[0x62, 0xf2, 0x7d, 0x1d, 0x66, 0x50, 0x01, 0x11], "vfpclassps");
}
#[test]
@@ -1411,11 +1412,985 @@ fn test_vex() {
test_invalid_under(&InstDecoder::minimal(), bytes);
}
+ fn test_avx2(bytes: &[u8], text: &'static str) {
+ test_display_under(&InstDecoder::minimal().with_avx().with_avx2(), bytes, text);
+ test_display_under(&InstDecoder::default(), bytes, text);
+ test_invalid_under(&InstDecoder::minimal(), bytes);
+ }
+
+ fn test_instr_vex_aesni(bytes: &[u8], text: &'static str) {
+ test_display_under(&InstDecoder::minimal().with_avx().with_aesni(), bytes, text);
+ test_display_under(&InstDecoder::default(), bytes, text);
+ test_invalid_under(&InstDecoder::minimal(), bytes);
+ }
+
fn test_instr_invalid(bytes: &[u8]) {
test_invalid_under(&InstDecoder::minimal().with_avx(), bytes);
test_invalid_under(&InstDecoder::default(), bytes);
}
+ // prefix 03
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x04, 0b11_001_010, 0x77], "vpermilps xmm9, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x04, 0b11_001_010, 0x77], "vpermilps ymm9, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x05, 0b11_001_010, 0x77], "vpermilpd xmm9, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x05, 0b11_001_010, 0x77], "vpermilpd ymm9, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_001, 0x06, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x06, 0b11_001_010, 0x77], "vperm2f128 ymm9, ymm0, ymm10, 0x77");
+
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x0c, 0b11_001_010, 0x77], "vblendps xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0c, 0b11_001_010, 0x77], "vblendps ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x0d, 0b11_001_010, 0x77], "vblendpd xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0d, 0b11_001_010, 0x77], "vblendpd ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x0e, 0b11_001_010, 0x77], "vpblendw xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0e, 0b11_001_010, 0x77], "vpblendw ymm9, ymm8, ymm10, 0x77");
+
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x08, 0b11_001_010, 0x77], "vroundps xmm9, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x08, 0b11_001_010, 0x77], "vroundps ymm9, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x08, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x08, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x09, 0b11_001_010, 0x77], "vroundpd xmm9, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x09, 0b11_001_010, 0x77], "vroundpd ymm9, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x09, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x09, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x0a, 0b11_001_010, 0x77], "vroundss xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0a, 0b11_001_010, 0x77], "vroundss ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x0b, 0b11_001_010, 0x77], "vroundsd xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x0b, 0b11_001_010, 0x77], "vroundsd ymm9, ymm8, ymm10, 0x77");
+
+ test_instr(&[0xc4, 0b000_00011, 0b1_0111_001, 0x0f, 0b11_001_010, 0x77], "vpalignr xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b1_0111_101, 0x0f, 0b11_001_010, 0x77], "vpalignr ymm9, ymm8, ymm10, 0x77");
+
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x14, 0b11_001_010, 0x77], "vpextrb r10d, xmm9, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x14, 0b00_001_010, 0x77], "vpextrb [r10], xmm9, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x14, 0b00_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x14, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x15, 0b11_001_010, 0x77], "vpextrw r10d, xmm9, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x15, 0b00_001_010, 0x77], "vpextrw [r10], xmm9, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x15, 0b00_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x15, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x16, 0b11_001_010, 0x77], "vpextrd r10d, xmm9, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x16, 0b00_001_010, 0x77], "vpextrd [r10], xmm9, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x16, 0b00_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x16, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b1_1111_001, 0x16, 0b11_001_010, 0x77], "vpextrq r10, xmm9, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b1_0111_001, 0x16, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b1_1111_001, 0x16, 0b00_001_010, 0x77], "vpextrq [r10], xmm9, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x17, 0b11_001_010, 0x77], "vextractps r10d, xmm9, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x17, 0b00_001_010, 0x77], "vextractps [r10], xmm9, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x17, 0b00_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x17, 0b00_001_010, 0x77]);
+
+ test_invalid(&[0xc4, 0b000_00011, 0b1_0111_001, 0x18, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x18, 0b11_001_010, 0x77], "vinsertf128 ymm9, ymm8, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b1_0111_101, 0x18, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_101, 0x19, 0b11_001_010, 0x77], "vextractf128 xmm10, ymm9, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_001, 0x19, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b1_1111_101, 0x19, 0b11_001_010, 0x77]);
+
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x20, 0b11_001_010, 0x77], "vpinsrb xmm9, xmm8, r10d, 0x77");
+ // TODO: byte ptr
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x20, 0b00_001_010, 0x77], "vpinsrb xmm9, xmm8, [r10], 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x20, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x21, 0b11_001_010, 0x77], "vinsertps xmm9, xmm8, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x21, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x22, 0b11_001_010, 0x77], "vpinsrd xmm9, xmm8, r10d, 0x77");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x22, 0b00_001_010, 0x77], "vpinsrd xmm9, xmm8, [r10], 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x22, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b1_0111_001, 0x22, 0b11_001_010, 0x77], "vpinsrq xmm9, xmm8, r10, 0x77");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00011, 0b1_0111_001, 0x22, 0b00_001_010, 0x77], "vpinsrq xmm9, xmm8, [r10], 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b1_0111_101, 0x22, 0b00_001_010, 0x77]);
+
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x40, 0b11_001_010, 0x77], "vdpps xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_101, 0x40, 0b11_001_010, 0x77], "vdpps ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x41, 0b11_001_010, 0x77], "vdppd xmm9, xmm8, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x41, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x42, 0b11_001_010, 0x77], "vmpsadbw xmm9, xmm8, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00011, 0b0_0111_101, 0x42, 0b11_001_010, 0x77], "vmpsadbw ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00011, 0b0_0111_001, 0x4c, 0b11_001_010, 0x77], "vpblendvb xmm9, xmm8, xmm10, xmm7");
+ test_avx2(&[0xc4, 0b000_00011, 0b0_0111_101, 0x4c, 0b11_001_010, 0x77], "vpblendvb ymm9, ymm8, ymm10, ymm7");
+ test_invalid(&[0xc4, 0b000_00011, 0b1_0111_001, 0x4c, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b1_0111_101, 0x4c, 0b11_001_010, 0x77]);
+
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x60, 0b11_001_010, 0x77], "vpcmpestrm xmm9, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x60, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x60, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x60, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x61, 0b11_001_010, 0x77], "vpcmpestri xmm9, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x61, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x61, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x61, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x62, 0b11_001_010, 0x77], "vpcmpistrm xmm9, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x62, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x62, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x62, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00011, 0b0_1111_001, 0x63, 0b11_001_010, 0x77], "vpcmpistri xmm9, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b0_1111_101, 0x63, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_001, 0x63, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b0_0111_101, 0x63, 0b11_001_010, 0x77]);
+
+ test_instr_vex_aesni(&[0xc4, 0b000_00011, 0b1_1111_001, 0xdf, 0b11_001_010, 0x77], "vaeskeygenassist xmm9, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00011, 0b1_0111_001, 0xdf, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00011, 0b1_0111_101, 0xdf, 0b11_001_010, 0x77]);
+
+ // prefix 02
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x00, 0b11_001_010], "vpshufb xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x00, 0b11_001_010], "vpshufb ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x01, 0b11_001_010], "vphaddw xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x01, 0b11_001_010], "vphaddw ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x02, 0b11_001_010], "vphaddd xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x02, 0b11_001_010], "vphaddd ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x03, 0b11_001_010], "vphaddsw xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x03, 0b11_001_010], "vphaddsw ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x04, 0b11_001_010], "vpmaddubsw xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x04, 0b11_001_010], "vpmaddubsw ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x05, 0b11_001_010], "vphsubw xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x05, 0b11_001_010], "vphsubw ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x06, 0b11_001_010], "vphsubd xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x06, 0b11_001_010], "vphsubd ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x07, 0b11_001_010], "vphsubsw xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x07, 0b11_001_010], "vphsubsw ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x08, 0b11_001_010], "vpsignb xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x08, 0b11_001_010], "vpsignb ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x09, 0b11_001_010], "vpsignw xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x09, 0b11_001_010], "vpsignw ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x0a, 0b11_001_010], "vpsignd xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x0a, 0b11_001_010], "vpsignd ymm9, ymm0, ymm10");
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x0b, 0b11_001_010], "vpmulhrsw xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x0b, 0b11_001_010], "vpmulhrsw ymm9, ymm0, ymm10");
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x0c, 0b11_001_010], "vpermilps xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_101, 0x0c, 0b11_001_010], "vpermilps ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x0d, 0b11_001_010], "vpermilpd xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_101, 0x0d, 0b11_001_010], "vpermilpd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x0e, 0b11_001_010], "vtestps xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x0e, 0b11_001_010], "vtestps ymm9, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x0f, 0b11_001_010], "vtestpd xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x0f, 0b11_001_010], "vtestpd ymm9, ymm10");
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x17, 0b11_001_010], "vptest xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x17, 0b11_001_010], "vptest ymm9, ymm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x17, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x17, 0b11_001_010]);
+
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x18, 0b00_001_010], "vbroadcastss xmm9, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x18, 0b00_001_010], "vbroadcastss ymm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00010, 0b1_1111_001, 0x18, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x18, 0b00_001_010]);
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x19, 0b00_001_010], "vbroadcastsd ymm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x19, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x19, 0b00_001_010]);
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x1a, 0b00_001_010], "vbroadcastf128 ymm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x1a, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_001, 0x1a, 0b00_001_010]);
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_001, 0x18, 0b11_001_010], "vbroadcastss xmm9, xmm10");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x18, 0b00_001_010], "vbroadcastss ymm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_001, 0x18, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x18, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x19, 0b11_001_010], "vbroadcastsd ymm9, ymm10");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x19, 0b00_001_010], "vbroadcastsd ymm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00010, 0b1_1111_101, 0x19, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x19, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_001, 0x19, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_001, 0x1a, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x1a, 0b11_001_010]);
+
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x1c, 0b11_001_010], "vpabsb xmm9, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x1c, 0b11_001_010], "vpabsb ymm9, ymm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x1c, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x1d, 0b11_001_010], "vpabsw xmm9, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x1d, 0b11_001_010], "vpabsw ymm9, ymm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x1d, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x1e, 0b11_001_010], "vpabsd xmm9, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x1e, 0b11_001_010], "vpabsd ymm9, ymm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x1e, 0b11_001_010]);
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x20, 0b11_001_010], "vpmovsxbw xmm9, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x20, 0b11_001_010], "vpmovsxbw ymm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x20, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x21, 0b11_001_010], "vpmovsxbd xmm9, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x21, 0b11_001_010], "vpmovsxbd ymm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x21, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x22, 0b11_001_010], "vpmovsxbq xmm9, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x22, 0b11_001_010], "vpmovsxbq ymm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x22, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x23, 0b11_001_010], "vpmovsxwd xmm9, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x23, 0b11_001_010], "vpmovsxwd ymm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x23, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x24, 0b11_001_010], "vpmovsxwq xmm9, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x24, 0b11_001_010], "vpmovsxwq ymm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x24, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x25, 0b11_001_010], "vpmovsxdq xmm9, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x25, 0b11_001_010], "vpmovsxdq ymm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x25, 0b11_001_010]);
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x28, 0b11_001_010], "vpmuldq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x28, 0b11_001_010], "vpmuldq ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x29, 0b11_001_010], "vpcmpeqq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x29, 0b11_001_010], "vpcmpeqq ymm9, ymm8, ymm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x2a, 0b11_001_010]);
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x2a, 0b00_001_010], "vmovntdqa xmm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x2a, 0b00_001_010]);
+ // TODO: ymmword ptr
+ test_avx2(&[0xc4, 0b000_00010, 0b0_1111_101, 0x2a, 0b00_001_010], "vmovntdqa ymm9, [r10]");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x2b, 0b11_001_010], "vpackusdw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x2b, 0b11_001_010], "vpackusdw ymm9, ymm8, ymm10");
+ // TODO: ymmword ptr
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x2b, 0b00_001_010], "vpackusdw ymm9, ymm8, [r10]");
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x30, 0b11_001_010], "vpmovzxbw xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x30, 0b11_001_010], "vpmovzxbw ymm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x31, 0b11_001_010], "vpmovzxbd xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x31, 0b11_001_010], "vpmovzxbd ymm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x32, 0b11_001_010], "vpmovzxbq xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x32, 0b11_001_010], "vpmovzxbq ymm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x33, 0b11_001_010], "vpmovzxwd xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x33, 0b11_001_010], "vpmovzxwd ymm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x34, 0b11_001_010], "vpmovzxwq xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x34, 0b11_001_010], "vpmovzxwq ymm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x35, 0b11_001_010], "vpmovzxdq xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x35, 0b11_001_010], "vpmovzxdq ymm9, xmm10");
+
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x30, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x30, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x31, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x31, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x32, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x32, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x33, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x33, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x34, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x34, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x35, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x35, 0b11_001_010]);
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x37, 0b11_001_010], "vpcmpgtq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x37, 0b11_001_010], "vpcmpgtq ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x38, 0b11_001_010], "vpminsb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x38, 0b11_001_010], "vpminsb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x39, 0b11_001_010], "vpminsd xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x39, 0b11_001_010], "vpminsd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x3a, 0b11_001_010], "vpminuw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x3a, 0b11_001_010], "vpminuw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x3b, 0b11_001_010], "vpminud xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x3b, 0b11_001_010], "vpminud ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x3c, 0b11_001_010], "vpmaxsb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x3c, 0b11_001_010], "vpmaxsb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x3d, 0b11_001_010], "vpmaxsd xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x3d, 0b11_001_010], "vpmaxsd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x3e, 0b11_001_010], "vpmaxuw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x3e, 0b11_001_010], "vpmaxuw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x3f, 0b11_001_010], "vpmaxud xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x3f, 0b11_001_010], "vpmaxud ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x40, 0b11_001_010], "vpmulld xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00010, 0b0_0111_101, 0x40, 0b11_001_010], "vpmulld ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x41, 0b11_001_010], "vphminposuw xmm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_001, 0x41, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0x41, 0b11_001_010]);
+// TODO: should something be at opcode 42 here?
+// test_instr(&[0xc4, 0b000_00010, 0b1_0111_001, 0x42, 0b11_001_010], "vphminposuw xmm");
+// test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x41, 0b11_001_010]);
+
+ test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b0_1111_001, 0xdb, 0b11_001_010], "vaesimc xmm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b0_0111_101, 0xdb, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0xdb, 0b11_001_010]);
+ test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b1_0111_001, 0xdc, 0b11_001_010], "vaesenc xmm9, xmm8, xmm10");
+ test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b1_0111_101, 0xdc, 0b11_001_010], "vaesenc ymm9, ymm8, ymm10");
+ test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b1_0111_001, 0xdd, 0b11_001_010], "vaesenclast xmm9, xmm8, xmm10");
+ test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b1_0111_101, 0xdd, 0b11_001_010], "vaesenclast ymm9, ymm8, ymm10");
+ test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b1_0111_001, 0xde, 0b11_001_010], "vaesdec xmm9, xmm8, xmm10");
+ test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b1_0111_101, 0xde, 0b11_001_010], "vaesdec ymm9, ymm8, ymm10");
+ test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b1_0111_001, 0xdf, 0b11_001_010], "vaesdeclast xmm9, xmm8, xmm10");
+ test_instr_vex_aesni(&[0xc4, 0b000_00010, 0b1_0111_101, 0xdf, 0b11_001_010], "vaesdeclast ymm9, ymm8, ymm10");
+
+ // prefix 01
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x10, 0b00_001_010], "vmovsd xmm9, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x10, 0b00_001_010], "vmovsd xmm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_011, 0x10, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_111, 0x10, 0b00_001_010]);
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x10, 0b00_001_010], "vmovupd xmm9, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x10, 0b00_001_010], "vmovupd ymm9, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x11, 0b00_001_010], "vmovsd [r10], xmm9");
+ // TODO: ... also qword ptr?
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x11, 0b00_001_010], "vmovsd [r10], xmm9");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_011, 0x11, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_111, 0x11, 0b00_001_010]);
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x10, 0b00_001_010], "vmovupd xmm9, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x10, 0b00_001_010], "vmovupd ymm9, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x10, 0b00_001_010], "vmovss xmm9, [r10]");
+ // TODO: ... also dword ptr?
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x10, 0b00_001_010], "vmovss xmm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_010, 0x10, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_110, 0x10, 0b00_001_010]);
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x10, 0b00_001_010], "vmovups xmm9, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x10, 0b00_001_010], "vmovups ymm9, [r10]");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0x11, 0b11_001_010], "vmovsd xmm10, xmm8, xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0x11, 0b11_001_010], "vmovsd xmm10, xmm8, xmm9");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x11, 0b00_001_010], "vmovss [r10], xmm9");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x11, 0b00_001_010], "vmovss [r10], xmm9");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x11, 0b00_001_010], "vmovups [r10], xmm9");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x11, 0b00_001_010], "vmovups [r10], ymm9");
+
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x12, 0b00_001_010], "vmovddup xmm9, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x12, 0b00_001_010], "vmovddup ymm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_011, 0x12, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_111, 0x12, 0b00_001_010]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x12, 0b11_001_010], "vmovhlps xmm9, xmm8, xmm10");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x12, 0b00_001_010], "vmovlps xmm9, xmm8, [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_100, 0x12, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_111, 0x12, 0b11_001_010]);
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x12, 0b00_001_010], "vmovsldup xmm9, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x12, 0b00_001_010], "vmovsldup ymm9, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x12, 0b00_001_010], "vmovsldup xmm9, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x12, 0b00_001_010], "vmovsldup ymm9, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x12, 0b00_001_010], "vmovlpd xmm9, xmm8, [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_101, 0x12, 0b00_001_010]);
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x13, 0b00_001_010], "vmovlpd [r10], xmm9");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_001, 0x13, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_101, 0x13, 0b00_001_010]);
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_000, 0x14, 0b11_001_010], "vunpcklps xmm9, xmm8, xmm10");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_100, 0x14, 0b11_001_010], "vunpcklps ymm9, ymm8, ymm10");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x14, 0b11_001_010], "vunpcklpd xmm9, xmm8, xmm10");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_101, 0x14, 0b11_001_010], "vunpcklpd ymm9, ymm8, ymm10");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_000, 0x15, 0b11_001_010], "vunpckhps xmm9, xmm8, xmm10");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_100, 0x15, 0b11_001_010], "vunpckhps ymm9, ymm8, ymm10");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x15, 0b11_001_010], "vunpckhpd xmm9, xmm8, xmm10");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_101, 0x15, 0b11_001_010], "vunpckhpd ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x16, 0b11_001_010], "vmovshdup xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x16, 0b11_001_010], "vmovshdup ymm9, ymm10");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_010, 0x16, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_110, 0x16, 0b11_001_010]);
+
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x16, 0b00_001_010], "vmovhps xmm9, xmm8, [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_100, 0x16, 0b00_001_010]);
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x16, 0b00_001_010], "vmovhpd xmm9, xmm8, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x16, 0b00_001_010], "vmovhpd xmm9, xmm8, [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_001, 0x16, 0b11_001_010]);
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x17, 0b00_001_010], "vmovhps [r10], xmm9");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_100, 0x17, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_000, 0x17, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_100, 0x17, 0b00_001_010]);
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x17, 0b00_001_010], "vmovhpd [r10], xmm9");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_001, 0x17, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_101, 0x17, 0b00_001_010]);
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_000, 0x28, 0b11_001_010], "vmovaps xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x28, 0b11_001_010], "vmovaps ymm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_000, 0x29, 0b11_001_010], "vmovaps xmm10, xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x29, 0b11_001_010], "vmovaps ymm10, ymm9");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x28, 0b11_001_010], "vmovapd xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x28, 0b11_001_010], "vmovapd ymm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x29, 0b11_001_010], "vmovapd xmm10, xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x29, 0b11_001_010], "vmovapd ymm10, ymm9");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x2a, 0b11_001_010], "vcvtsi2ss xmm9, xmm0, r10d");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x2a, 0b00_001_010], "vcvtsi2ss xmm9, xmm0, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x2a, 0b11_001_010], "vcvtsi2ss xmm9, xmm0, r10");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x2a, 0b00_001_010], "vcvtsi2ss xmm9, xmm0, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x2a, 0b11_001_010], "vcvtsi2ss xmm9, xmm0, r10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x2a, 0b11_001_010], "vcvtsi2sd xmm9, xmm0, r10d");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2a, 0b11_001_010], "vcvtsi2sd xmm9, xmm0, r10d");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x2a, 0b11_001_010], "vcvtsi2sd xmm9, xmm0, r10");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x2a, 0b00_001_010], "vcvtsi2sd xmm9, xmm0, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x2a, 0b00_001_010], "vcvtsi2sd xmm9, xmm0, [r10]");
+ test_instr(&[0xc5, 0b0_1111_011, 0x2a, 0b11_001_010], "vcvtsi2sd xmm9, xmm0, edx");
+ test_instr(&[0xc5, 0b0_1111_111, 0x2a, 0b11_001_010], "vcvtsi2sd xmm9, xmm0, edx");
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_000, 0x2b, 0b00_001_010], "vmovntps [r10], xmm9");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x2b, 0b00_001_010], "vmovntps [r10], ymm9");
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_000, 0x2b, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_100, 0x2b, 0b11_001_010]);
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x2b, 0b00_001_010], "vmovntpd [r10], xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x2b, 0b00_001_010], "vmovntpd [r10], ymm9");
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_001, 0x2b, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_101, 0x2b, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x2c, 0b11_001_010], "vcvttss2si r9d, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x2c, 0b11_001_010], "vcvttss2si r9d, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x2c, 0b11_001_010], "vcvttss2si r9, xmm10");
+ test_instr(&[0xc5, 0b0_1111_010, 0x2c, 0b11_001_010], "vcvttss2si r9d, xmm2");
+ // TODO: dword ptr
+ test_instr(&[0xc5, 0b0_1111_010, 0x2c, 0b00_001_010], "vcvttss2si r9d, [rdx]");
+ test_instr(&[0xc5, 0b0_1111_110, 0x2c, 0b11_001_010], "vcvttss2si r9d, xmm2");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x2c, 0b11_001_010], "vcvttsd2si r9d, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2c, 0b11_001_010], "vcvttsd2si r9d, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x2c, 0b11_001_010], "vcvttsd2si r9, xmm10");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si r9, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si r9d, [r10]");
+ test_instr(&[0xc5, 0b0_1111_011, 0x2c, 0b11_001_010], "vcvttsd2si r9d, xmm2");
+ test_instr(&[0xc5, 0b0_1111_111, 0x2c, 0b11_001_010], "vcvttsd2si r9d, xmm2");
+ // TODO: qword ptr
+ test_instr(&[0xc5, 0b0_1111_111, 0x2c, 0b00_001_010], "vcvttsd2si r9d, [rdx]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x2d, 0b11_001_010], "vcvtss2si r9d, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x2d, 0b11_001_010], "vcvtss2si r9d, xmm10");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x2d, 0b00_001_010], "vcvtss2si r9d, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x2d, 0b00_001_010], "vcvtss2si r9, [r10]");
+ test_instr(&[0xc5, 0b0_1111_010, 0x2d, 0b11_001_010], "vcvtss2si r9d, xmm2");
+ test_instr(&[0xc5, 0b0_1111_110, 0x2d, 0b11_001_010], "vcvtss2si r9d, xmm2");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x2d, 0b11_001_010], "vcvtsd2si r9d, xmm10");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_011, 0x2d, 0b00_001_010], "vcvtsd2si r9d, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2d, 0b11_001_010], "vcvtsd2si r9d, xmm10");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_111, 0x2d, 0b00_001_010], "vcvtsd2si r9d, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x2d, 0b11_001_010], "vcvtsd2si r9, xmm10");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x2d, 0b00_001_010], "vcvtsd2si r9, [r10]");
+ test_instr(&[0xc5, 0b0_1111_011, 0x2d, 0b11_001_010], "vcvtsd2si r9d, xmm2");
+ test_instr(&[0xc5, 0b0_1111_111, 0x2d, 0b11_001_010], "vcvtsd2si r9d, xmm2");
+
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x2e, 0b00_001_010], "vucomisd xmm9, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_101, 0x2e, 0b00_001_010], "vucomisd xmm9, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x2e, 0b11_001_010], "vucomisd xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_101, 0x2e, 0b11_001_010], "vucomisd xmm9, xmm10");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x2f, 0b00_001_010], "vcomisd xmm9, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_101, 0x2f, 0b00_001_010], "vcomisd xmm9, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x2f, 0b11_001_010], "vcomisd xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_101, 0x2f, 0b11_001_010], "vcomisd xmm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_001, 0x2e, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_101, 0x2e, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_001, 0x2e, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_101, 0x2e, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_001, 0x2f, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_101, 0x2f, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_001, 0x2f, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_0111_101, 0x2f, 0b11_001_010]);
+
+ test_instr(&[0xc5, 0b0_1111_000, 0x2e, 0b11_001_010], "vucomiss xmm9, xmm2");
+ // TODO: dword ptr
+ test_instr(&[0xc5, 0b0_1111_100, 0x2e, 0b00_001_010], "vucomiss xmm9, [rdx]");
+ test_instr(&[0xc5, 0b0_1111_000, 0x2f, 0b11_001_010], "vcomiss xmm9, xmm2");
+ // TODO: dword ptr
+ test_instr(&[0xc5, 0b0_1111_100, 0x2f, 0b00_001_010], "vcomiss xmm9, [rdx]");
+ test_invalid(&[0xc5, 0b0_1111_111, 0x2f, 0b11_001_010]);
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x50, 0b11_001_010], "vmovmskps r9d, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x50, 0b11_001_010], "vmovmskps r9d, ymm10");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_000, 0x50, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_100, 0x50, 0b00_001_010]);
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x50, 0b11_001_010], "vmovmskpd r9d, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x50, 0b11_001_010], "vmovmskpd r9d, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x50, 0b11_001_010], "vmovmskpd r9d, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_101, 0x50, 0b11_001_010], "vmovmskpd r9d, ymm10");
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_001, 0x50, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_101, 0x50, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_001, 0x50, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_101, 0x50, 0b00_001_010]);
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x51, 0b00_001_010], "vsqrtpd xmm9, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_101, 0x51, 0b00_001_010], "vsqrtpd ymm9, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_011, 0x51, 0b00_001_010], "vsqrtsd xmm9, xmm8, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_111, 0x51, 0b00_001_010], "vsqrtsd xmm9, xmm8, [r10]");
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x51, 0b11_001_010], "vsqrtps xmm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_000, 0x51, 0b11_001_010]);
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x51, 0b11_001_010], "vsqrtps ymm9, ymm10");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x51, 0b00_001_010], "vsqrtss xmm9, xmm0, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x51, 0b00_001_010], "vsqrtss xmm9, xmm0, [r10]");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x52, 0b11_001_010], "vrsqrtps xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x52, 0b11_001_010], "vrsqrtps ymm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x52, 0b11_001_010], "vrsqrtss xmm9, xmm0, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x52, 0b11_001_010], "vrsqrtss xmm9, xmm0, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x53, 0b11_001_010], "vrcpps xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x53, 0b11_001_010], "vrcpps ymm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x53, 0b11_001_010], "vrcpss xmm9, xmm0, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x53, 0b11_001_010], "vrcpss xmm9, xmm0, xmm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x54, 0b11_001_010], "vandps xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0x54, 0b11_001_010], "vandps ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x55, 0b11_001_010], "vandnps xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0x55, 0b11_001_010], "vandnps ymm9, ymm8, ymm10");
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x54, 0b00_001_010], "vandpd xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x54, 0b00_001_010], "vandpd ymm9, ymm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x55, 0b00_001_010], "vandnpd xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x55, 0b00_001_010], "vandnpd ymm9, ymm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x56, 0b00_001_010], "vorpd xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x56, 0b00_001_010], "vorpd ymm9, ymm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x56, 0b00_001_010], "vorps xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0x56, 0b00_001_010], "vorps ymm9, ymm8, [r10]");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x57, 0b11_001_010], "vxorps xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0x57, 0b11_001_010], "vxorps ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x57, 0b11_001_010], "vxorpd xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x57, 0b11_001_010], "vxorpd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x58, 0b11_001_010], "vaddps xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0x58, 0b11_001_010], "vaddps ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_010, 0x58, 0b11_001_010], "vaddss xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_110, 0x58, 0b11_001_010], "vaddss xmm9, xmm8, xmm10");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_010, 0x58, 0b00_001_010], "vaddss xmm9, xmm8, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_110, 0x58, 0b00_001_010], "vaddss xmm9, xmm8, [r10]");
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x58, 0b00_001_010], "vaddpd xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x58, 0b00_001_010], "vaddpd ymm9, ymm8, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0x58, 0b00_001_010], "vaddsd xmm9, xmm8, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0x58, 0b00_001_010], "vaddsd xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x59, 0b00_001_010], "vmulps xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0x59, 0b00_001_010], "vmulps ymm9, ymm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x59, 0b00_001_010], "vmulpd xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x59, 0b00_001_010], "vmulpd ymm9, ymm8, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_010, 0x59, 0b00_001_010], "vmulss xmm9, xmm8, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_110, 0x59, 0b00_001_010], "vmulss xmm9, xmm8, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0x59, 0b00_001_010], "vmulsd xmm9, xmm8, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0x59, 0b00_001_010], "vmulsd xmm9, xmm8, [r10]");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x5a, 0b11_001_010], "vcvtps2pd xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x5a, 0b11_001_010], "vcvtps2pd ymm9, xmm10");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x5a, 0b00_001_010], "vcvtps2pd xmm9, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x5a, 0b00_001_010], "vcvtps2pd ymm9, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x5a, 0b11_001_010], "vcvtpd2ps xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x5a, 0b11_001_010], "vcvtpd2ps xmm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x5a, 0b11_001_010], "vcvtsd2ss xmm9, xmm0, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x5a, 0b11_001_010], "vcvtsd2ss xmm9, xmm0, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x5a, 0b11_001_010], "vcvtss2sd xmm9, xmm0, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x5a, 0b11_001_010], "vcvtss2sd xmm9, xmm0, xmm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x5b, 0b11_001_010], "vcvtps2dq xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x5b, 0b11_001_010], "vcvtps2dq ymm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x5b, 0b11_001_010], "vcvttps2dq xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x5b, 0b11_001_010], "vcvttps2dq ymm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x5b, 0b11_001_010], "vcvtdq2ps xmm9, xmm10");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x5b, 0b00_001_010], "vcvtdq2ps xmm9, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x5b, 0b11_001_010], "vcvtdq2ps ymm9, ymm10");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x5b, 0b00_001_010], "vcvtdq2ps ymm9, [r10]");
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_000, 0x5c, 0b00_001_010], "vsubps xmm9, xmm0, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_100, 0x5c, 0b00_001_010], "vsubps ymm9, ymm0, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_010, 0x5c, 0b00_001_010], "vsubss xmm9, xmm8, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_110, 0x5c, 0b00_001_010], "vsubss xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x5c, 0b00_001_010], "vsubpd xmm9, xmm0, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_101, 0x5c, 0b00_001_010], "vsubpd ymm9, ymm0, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_011, 0x5c, 0b00_001_010], "vsubsd xmm9, xmm8, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_111, 0x5c, 0b00_001_010], "vsubsd xmm9, xmm8, [r10]");
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x5d, 0b00_001_010], "vminps xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0x5d, 0b00_001_010], "vminps ymm9, ymm8, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_010, 0x5d, 0b00_001_010], "vminss xmm9, xmm8, [r10]");
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_110, 0x5d, 0b00_001_010], "vminss xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x5d, 0b00_001_010], "vminpd xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x5d, 0b00_001_010], "vminpd ymm9, ymm8, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0x5d, 0b00_001_010], "vminsd xmm9, xmm8, [r10]");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0x5d, 0b00_001_010], "vminsd xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x5e, 0b00_001_010], "vdivps xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x5e, 0b00_001_010], "vdivps xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x5e, 0b00_001_010], "vdivpd xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_010, 0x5e, 0b00_001_010], "vdivss xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0x5e, 0b00_001_010], "vdivsd xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0x5e, 0b00_001_010], "vdivps ymm9, ymm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x5e, 0b00_001_010], "vdivpd ymm9, ymm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_110, 0x5e, 0b00_001_010], "vdivss xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0x5e, 0b00_001_010], "vdivsd xmm9, xmm8, [r10]");
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0x5f, 0b00_001_010], "vmaxps xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x5f, 0b00_001_010], "vmaxpd xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_010, 0x5f, 0b00_001_010], "vmaxss xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0x5f, 0b00_001_010], "vmaxsd xmm9, xmm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0x5f, 0b00_001_010], "vmaxps ymm9, ymm8, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x5f, 0b00_001_010], "vmaxpd ymm9, ymm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_110, 0x5f, 0b00_001_010], "vmaxss xmm9, xmm8, [r10]");
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0x5f, 0b00_001_010], "vmaxsd xmm9, xmm8, [r10]");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x60, 0b11_001_010], "vpunpcklbw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x60, 0b11_001_010], "vpunpcklbw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x61, 0b11_001_010], "vpunpcklwd xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x61, 0b11_001_010], "vpunpcklwd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x62, 0b11_001_010], "vpunpckldq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x62, 0b11_001_010], "vpunpckldq ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x63, 0b11_001_010], "vpacksswb xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_101, 0x63, 0b11_001_010], "vpacksswb ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x64, 0b11_001_010], "vpcmpgtb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x64, 0b11_001_010], "vpcmpgtb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x65, 0b11_001_010], "vpcmpgtw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x65, 0b11_001_010], "vpcmpgtw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x66, 0b11_001_010], "vpcmpgtd xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x66, 0b11_001_010], "vpcmpgtd ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x67, 0b11_001_010], "vpackuswb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x67, 0b11_001_010], "vpackuswb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x68, 0b11_001_010], "vpunpckhbw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x68, 0b11_001_010], "vpunpckhbw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x69, 0b11_001_010], "vpunpckhwd xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x69, 0b11_001_010], "vpunpckhwd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x6a, 0b11_001_010], "vpunpckhdq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x6a, 0b11_001_010], "vpunpckhdq ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0x6b, 0b11_001_010], "vpackssdw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0x6b, 0b11_001_010], "vpackssdw ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x6c, 0b11_001_010], "vpunpcklqdq xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x6c, 0b11_001_010], "vpunpcklqdq ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x6d, 0b11_001_010], "vpunpckhqdq xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x6d, 0b11_001_010], "vpunpckhqdq ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x6e, 0b11_001_010], "vmovq xmm9, r10");
+ // TODO: qword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x6e, 0b00_001_010], "vmovq xmm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_101, 0x6e, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x6f, 0b11_001_010], "vmovdqa xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_101, 0x6f, 0b11_001_010], "vmovdqa ymm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x6f, 0b11_001_010], "vmovdqu xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x6f, 0b11_001_010], "vmovdqu ymm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x70, 0b11_001_010, 0x77], "vpshufd xmm9, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x70, 0b11_001_010, 0x77], "vpshufd ymm9, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x70, 0b11_001_010, 0x77], "vpshufhw xmm9, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_110, 0x70, 0b11_001_010, 0x77], "vpshufhw ymm9, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x70, 0b11_001_010, 0x77], "vpshuflw xmm9, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_111, 0x70, 0b11_001_010, 0x77], "vpshuflw ymm9, ymm10, 0x77");
+
+
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x71, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x71, 0b11_010_010, 0x77], "vpsrlw xmm0, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x71, 0b11_010_010, 0x77], "vpsrlw xmm8, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x71, 0b11_010_010, 0x77], "vpsrlw ymm0, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x71, 0b00_011_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x71, 0b11_100_010, 0x77], "vpsraw xmm0, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x71, 0b11_100_010, 0x77], "vpsraw ymm0, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x71, 0b11_101_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x71, 0b11_110_010, 0x77], "vpsllw xmm0, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x71, 0b11_110_010, 0x77], "vpsllw ymm0, ymm10, 0x77");
+
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x72, 0b00_000_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x72, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x72, 0b11_010_010, 0x77], "vpsrld xmm0, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x72, 0b11_010_010, 0x77], "vpsrld ymm0, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_101, 0x72, 0b11_011_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x72, 0b11_100_010, 0x77], "vpsrad xmm0, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x72, 0b00_100_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x72, 0b11_100_010, 0x77], "vpsrad ymm0, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x72, 0b00_101_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x72, 0b11_110_010, 0x77], "vpslld xmm0, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x72, 0b00_110_010, 0x77]);
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x72, 0b11_110_010, 0x77], "vpslld ymm0, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x72, 0b00_111_010, 0x77]);
+
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x73, 0b11_000_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x73, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x73, 0b11_010_010, 0x77], "vpsrlq xmm0, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x73, 0b11_011_010, 0x77], "vpsrldq xmm0, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x73, 0b11_010_010, 0x77], "vpsrlq ymm0, ymm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x73, 0b11_011_010, 0x77], "vpsrldq ymm0, ymm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x73, 0b11_100_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0x73, 0b11_101_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x73, 0b11_110_010, 0x77], "vpsllq xmm0, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x73, 0b11_111_010, 0x77], "vpslldq xmm0, xmm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x73, 0b11_110_010, 0x77], "vpsllq ymm0, ymm10, 0x77");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0x73, 0b11_111_010, 0x77], "vpslldq ymm0, ymm10, 0x77");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x74, 0b11_001_010], "vpcmpeqb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0x74, 0b11_001_010], "vpcmpeqb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x75, 0b11_001_010], "vpcmpeqw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0x75, 0b11_001_010], "vpcmpeqw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x76, 0b11_001_010], "vpcmpeqd xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0x76, 0b11_001_010], "vpcmpeqd ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x7c, 0b11_001_010], "vhaddpd xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x7c, 0b11_001_010], "vhaddpd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0x7c, 0b11_001_010], "vhaddps xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0x7c, 0b11_001_010], "vhaddps ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0x7d, 0b11_001_010], "vhsubpd xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0x7d, 0b11_001_010], "vhsubpd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0x7d, 0b11_001_010], "vhsubps xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0x7d, 0b11_001_010], "vhsubps ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x7e, 0b11_001_010], "vmovd r10d, xmm9");
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_101, 0x7e, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x7e, 0b11_001_010], "vmovq r10, xmm9");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_101, 0x7e, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0x7f, 0b11_001_010], "vmovdqa xmm10, xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_101, 0x7f, 0b11_001_010], "vmovdqa ymm10, ymm9");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_010, 0x7f, 0b11_001_010], "vmovdqu xmm10, xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_110, 0x7f, 0b11_001_010], "vmovdqu ymm10, ymm9");
+
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_000, 0xae, 0b00_010_001], "vldmxcsr [r9]");
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_100, 0xae, 0b00_010_001]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_000, 0xae, 0b11_010_001]);
+ // TODO: dword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_000, 0xae, 0b00_011_001], "vstmxcsr [r9]");
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_100, 0xae, 0b00_011_001]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_000, 0xae, 0b11_011_001]);
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_000, 0xc2, 0b11_001_010, 0x77], "vcmpps xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_100, 0xc2, 0b11_001_010, 0x77], "vcmpps ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xc2, 0b11_001_010, 0x77], "vcmppd xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0xc2, 0b11_001_010, 0x77], "vcmppd ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0xc2, 0b11_001_010, 0x77], "vcmpsd xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0xc2, 0b11_001_010, 0x77], "vcmpsd xmm9, xmm8, xmm10, 0x77");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xc4, 0b11_001_010, 0x77], "vpinsrw xmm9, xmm8, r10d, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_101, 0xc4, 0b11_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_001, 0xc5, 0b00_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0xc5, 0b11_001_010, 0x77], "vpextrw r9d, xmm10, 0x77");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0xc5, 0b00_001_010, 0x77]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_101, 0xc5, 0b11_001_010, 0x77]);
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xc6, 0b11_001_010, 0x77], "vshufpd xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_101, 0xc6, 0b11_001_010, 0x77], "vshufpd ymm9, ymm8, ymm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_000, 0xc6, 0b11_001_010, 0x77], "vshufps xmm9, xmm8, xmm10, 0x77");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_100, 0xc6, 0b11_001_010, 0x77], "vshufps ymm9, ymm8, ymm10, 0x77");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xd0, 0b11_001_010], "vaddsubpd xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd0, 0b11_001_010], "vaddsubpd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0xd0, 0b11_001_010], "vaddsubps xmm9, xmm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0xd0, 0b11_001_010], "vaddsubps ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xd1, 0b11_001_010], "vpsrlw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd1, 0b11_001_010], "vpsrlw ymm9, ymm8, xmm10");
+ // TODO: xmmword ptr
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd1, 0b00_001_010], "vpsrlw ymm9, ymm8, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xd2, 0b11_001_010], "vpsrld xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd2, 0b11_001_010], "vpsrld ymm9, ymm8, xmm10");
+ // TODO: xmmword ptr
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd2, 0b00_001_010], "vpsrld ymm9, ymm8, [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xd3, 0b11_001_010], "vpsrlq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd3, 0b11_001_010], "vpsrlq ymm9, ymm8, xmm10");
+ // TODO: xmmword ptr
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd3, 0b00_001_010], "vpsrlq ymm9, ymm8, [r10]");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xd4, 0b11_001_010], "vpaddq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd4, 0b11_001_010], "vpaddq ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xd5, 0b11_001_010], "vpmullw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xd5, 0b11_001_010], "vpmullw ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_1111_001, 0xd7, 0b11_001_010], "vpmovmskb r9d, xmm10");
+ test_invalid(&[0xc4, 0b000_00001, 0b0_1111_001, 0xd7, 0b00_001_010]);
+ test_avx2(&[0xc4, 0b000_00001, 0b0_1111_101, 0xd7, 0b11_001_010], "vpmovmskb r9d, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xd8, 0b11_001_010], "vpsubusb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd8, 0b11_001_010], "vpsubusb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xd9, 0b11_001_010], "vpsubusw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xd9, 0b11_001_010], "vpsubusw ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xda, 0b11_001_010], "vpminsw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xda, 0b11_001_010], "vpminsw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xdb, 0b11_001_010], "vpand xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xdb, 0b11_001_010], "vpand ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xdc, 0b11_001_010], "vpaddusb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xdc, 0b11_001_010], "vpaddusb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xdd, 0b11_001_010], "vpaddusw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xdd, 0b11_001_010], "vpaddusw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xde, 0b11_001_010], "vpmaxub xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xde, 0b11_001_010], "vpmaxub ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xdf, 0b11_001_010], "vpandn xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xdf, 0b11_001_010], "vpandn ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xe0, 0b11_001_010], "vpavgb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xe0, 0b11_001_010], "vpavgb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xe1, 0b11_001_010], "vpsraw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xe1, 0b11_001_010], "vpsraw ymm9, ymm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xe2, 0b11_001_010], "vpsrad xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xe2, 0b11_001_010], "vpsrad ymm9, ymm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xe3, 0b11_001_010], "vpavgw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xe3, 0b11_001_010], "vpavgw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xe4, 0b11_001_010], "vpmulhuw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xe4, 0b11_001_010], "vpmulhuw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xe5, 0b11_001_010], "vpmulhw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xe5, 0b11_001_010], "vpmulhw ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0xe6, 0b11_001_010], "vcvttpd2dq xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0xe6, 0b11_001_010], "vcvttpd2dq xmm9, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0xe6, 0b11_001_010], "vcvtdq2pd xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0xe6, 0b11_001_010], "vcvtdq2pd ymm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0xe6, 0b11_001_010], "vcvtpd2dq xmm9, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0xe6, 0b11_001_010], "vcvtpd2dq xmm9, ymm10");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0xe7, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_101, 0xe7, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0xe7, 0b00_001_010], "vmovntdq [r10], xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0xe7, 0b00_001_010], "vmovntdq [r10], ymm9");
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xe8, 0b11_001_010], "vpsubsb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xe8, 0b11_001_010], "vpsubsb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xe9, 0b11_001_010], "vpsubsw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xe9, 0b11_001_010], "vpsubsw ymm9, ymm8, ymm10");
+
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xea, 0b11_001_010], "vpminsw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xea, 0b11_001_010], "vpminsw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xeb, 0b11_001_010], "vpor xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xeb, 0b11_001_010], "vpor ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xec, 0b11_001_010], "vpaddsb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xec, 0b11_001_010], "vpaddsb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xed, 0b11_001_010], "vpaddsw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xed, 0b11_001_010], "vpaddsw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xee, 0b11_001_010], "vpmaxsw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xee, 0b11_001_010], "vpmaxsw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b0_0111_001, 0xef, 0b11_001_010], "vpxor xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b0_0111_101, 0xef, 0b11_001_010], "vpxor ymm9, ymm8, ymm10");
+
+ // TODO: xmmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0xf0, 0b00_001_010], "vlddqu xmm9, [r10]");
+ // TODO: ymmword ptr
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0xf0, 0b00_001_010], "vlddqu ymm9, [r10]");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_011, 0xf0, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_011, 0xf0, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_0111_111, 0xf0, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_111, 0xf0, 0b11_001_010]);
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xf1, 0b11_001_010], "vpsllw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xf1, 0b11_001_010], "vpsllw ymm9, ymm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xf2, 0b11_001_010], "vpslld xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xf2, 0b11_001_010], "vpslld ymm9, ymm8, xmm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xf3, 0b11_001_010], "vpsllq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xf3, 0b11_001_010], "vpsllq ymm9, ymm8, xmm10");
+
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xf4, 0b11_001_010], "vpmuludq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xf4, 0b11_001_010], "vpmuludq ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0xf5, 0b11_001_010], "vpmaddwd xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0xf5, 0b11_001_010], "vpmaddwd ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0xf6, 0b11_001_010], "vpsadbw xmm9, xmm0, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_1111_101, 0xf6, 0b11_001_010], "vpsadbw ymm9, ymm0, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0xf7, 0b11_001_010], "vmaskmovdqu xmm9, xmm10");
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_001, 0xf7, 0b00_001_010]);
+ test_invalid(&[0xc4, 0b000_00001, 0b1_1111_101, 0xf7, 0b11_001_010]);
+
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xf8, 0b11_001_010], "vpsubb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xf8, 0b11_001_010], "vpsubb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xf9, 0b11_001_010], "vpsubw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xf9, 0b11_001_010], "vpsubw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xfa, 0b11_001_010], "vpsubd xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xfa, 0b11_001_010], "vpsubd ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xfb, 0b11_001_010], "vpsubq xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xfb, 0b11_001_010], "vpsubq ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xfc, 0b11_001_010], "vpaddb xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xfc, 0b11_001_010], "vpaddb ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xfd, 0b11_001_010], "vpaddw xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xfd, 0b11_001_010], "vpaddw ymm9, ymm8, ymm10");
+ test_instr(&[0xc4, 0b000_00001, 0b1_0111_001, 0xfe, 0b11_001_010], "vpaddd xmm9, xmm8, xmm10");
+ test_avx2(&[0xc4, 0b000_00001, 0b1_0111_101, 0xfe, 0b11_001_010], "vpaddd ymm9, ymm8, ymm10");
+
test_instr(&[0xc5, 0xf8, 0x10, 0x00], "vmovups xmm0, [rax]");
test_instr(&[0xc5, 0xf8, 0x10, 0x01], "vmovups xmm0, [rcx]");
test_instr(&[0xc5, 0x78, 0x10, 0x0f], "vmovups xmm9, [rdi]");
@@ -1449,10 +2424,10 @@ fn test_vex() {
test_instr(&[0xc4, 0x02, 0x75, 0x03, 0x0f], "vphaddsw ymm9, ymm1, [r15]");
test_instr(&[0xc4, 0x02, 0x71, 0x03, 0xcd], "vphaddsw xmm9, xmm1, xmm13");
test_instr(&[0xc4, 0x02, 0x75, 0x03, 0xcd], "vphaddsw ymm9, ymm1, ymm13");
- test_instr(&[0xc4, 0x02, 0x71, 0x04, 0x0f], "vphaddubsw xmm9, xmm1, [r15]");
- test_instr(&[0xc4, 0x02, 0x75, 0x04, 0x0f], "vphaddubsw ymm9, ymm1, [r15]");
- test_instr(&[0xc4, 0x02, 0x71, 0x04, 0xcd], "vphaddubsw xmm9, xmm1, xmm13");
- test_instr(&[0xc4, 0x02, 0x75, 0x04, 0xcd], "vphaddubsw ymm9, ymm1, ymm13");
+ test_instr(&[0xc4, 0x02, 0x71, 0x04, 0x0f], "vpmaddubsw xmm9, xmm1, [r15]");
+ test_instr(&[0xc4, 0x02, 0x75, 0x04, 0x0f], "vpmaddubsw ymm9, ymm1, [r15]");
+ test_instr(&[0xc4, 0x02, 0x71, 0x04, 0xcd], "vpmaddubsw xmm9, xmm1, xmm13");
+ test_instr(&[0xc4, 0x02, 0x75, 0x04, 0xcd], "vpmaddubsw ymm9, ymm1, ymm13");
test_instr(&[0xc4, 0x02, 0x71, 0x05, 0x0f], "vphsubw xmm9, xmm1, [r15]");
test_instr(&[0xc4, 0x02, 0x75, 0x05, 0x0f], "vphsubw ymm9, ymm1, [r15]");
test_instr(&[0xc4, 0x02, 0x71, 0x05, 0xcd], "vphsubw xmm9, xmm1, xmm13");
@@ -1506,7 +2481,7 @@ fn test_vex() {
test_instr(&[0xc4, 0x02, 0x09, 0x9d, 0xcd], "vfnmadd132ss xmm9, xmm14, xmm13");
test_instr(&[0xc4, 0x02, 0x89, 0x9d, 0xcd], "vfnmadd132sd xmm9, xmm14, xmm13");
// ...
- test_instr(&[0xc4, 0xe3, 0x79, 0x14, 0xd0, 0x0a], "vpextrb rax, xmm2, 0xa");
+ test_instr(&[0xc4, 0xe3, 0x79, 0x14, 0xd0, 0x0a], "vpextrb eax, xmm2, 0xa");
test_instr(&[0xc4, 0xe3, 0x79, 0x14, 0x10, 0x0a], "vpextrb [rax], xmm2, 0xa");
test_instr_invalid(&[0xc4, 0xe3, 0xf9, 0x14, 0x00, 0xd0]);
test_instr_invalid(&[0xc4, 0xe3, 0xf9, 0x14, 0x00, 0x0a]);
@@ -1543,13 +2518,12 @@ fn test_vex() {
test_instr(&[0xc5, 0xf1, 0xc4, 0xd8, 0x78], "vpinsrw xmm3, xmm1, eax, 0x78");
test_instr(&[0xc5, 0xf1, 0xc4, 0x18, 0x78], "vpinsrw xmm3, xmm1, [rax], 0x78");
- // uh oh, i think these sizes are backwards...
- test_instr(&[0xc5, 0xe0, 0x54, 0x03], "vandpd xmm0, xmm3, [rbx]");
- test_instr(&[0xc5, 0xe1, 0x54, 0x03], "vandps xmm0, xmm3, [rbx]");
- test_instr(&[0xc5, 0xe0, 0x55, 0x03], "vandnpd xmm0, xmm3, [rbx]");
- test_instr(&[0xc5, 0xe1, 0x55, 0x03], "vandnps xmm0, xmm3, [rbx]");
- test_instr(&[0xc5, 0xe0, 0x56, 0x03], "vorpd xmm0, xmm3, [rbx]");
- test_instr(&[0xc5, 0xe1, 0x56, 0x03], "vorps xmm0, xmm3, [rbx]");
+ test_instr(&[0xc5, 0xe0, 0x54, 0x03], "vandps xmm0, xmm3, [rbx]");
+ test_instr(&[0xc5, 0xe1, 0x54, 0x03], "vandpd xmm0, xmm3, [rbx]");
+ test_instr(&[0xc5, 0xe0, 0x55, 0x03], "vandnps xmm0, xmm3, [rbx]");
+ test_instr(&[0xc5, 0xe1, 0x55, 0x03], "vandnpd xmm0, xmm3, [rbx]");
+ test_instr(&[0xc5, 0xe0, 0x56, 0x03], "vorps xmm0, xmm3, [rbx]");
+ test_instr(&[0xc5, 0xe1, 0x56, 0x03], "vorpd xmm0, xmm3, [rbx]");
test_instr(&[0xc4, 0xa2, 0x15, 0x3e, 0x14, 0xb9], "vpmaxuw ymm2, ymm13, [rcx + r15 * 4]");
}