From 8d8cb8d594217a630dea605348211539afe3f940 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 15 Dec 2019 21:19:44 -0800 Subject: test fence instructions against different quirks modes add enclv instruction add sse3, ssse3, sse4.1, and sse4.2 feature flags, plus a host of missing opcodes --- src/display.rs | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 103 +++++++++++++++++++++++++++++++++----- test/test.rs | 11 +++-- 3 files changed, 251 insertions(+), 15 deletions(-) diff --git a/src/display.rs b/src/display.rs index 35cd210..9315e19 100644 --- a/src/display.rs +++ b/src/display.rs @@ -553,6 +553,7 @@ impl fmt::Display for Opcode { &Opcode::CLAC => write!(f, "{}", "clac"), &Opcode::STAC => write!(f, "{}", "stac"), &Opcode::ENCLS => write!(f, "{}", "encls"), + &Opcode::ENCLV => write!(f, "{}", "enclv"), &Opcode::XGETBV => write!(f, "{}", "xgetbv"), &Opcode::XSETBV => write!(f, "{}", "xsetbv"), &Opcode::VMFUNC => write!(f, "{}", "vmfunc"), @@ -892,6 +893,81 @@ impl fmt::Display for Opcode { &Opcode::VSUBSS => write!(f, "{}", "vsubss"), &Opcode::VUCOMISD => write!(f, "{}", "vucomisd"), &Opcode::VUCOMISS => write!(f, "{}", "vucomiss"), + &Opcode::PCLMULQDQ => write!(f, "{}", "pclmulqdq"), + &Opcode::AESKEYGENASSIST => write!(f, "{}", "aeskeygenassist"), + &Opcode::AESIMC => write!(f, "{}", "aesimc"), + &Opcode::AESENC => write!(f, "{}", "aesenc"), + &Opcode::AESENCLAST => write!(f, "{}", "aesenclast"), + &Opcode::AESDEC => write!(f, "{}", "aesdec"), + &Opcode::AESDECLAST => write!(f, "{}", "aesdeclast"), + &Opcode::PCMPGTQ => write!(f, "{}", "pcmpgtq"), + &Opcode::PCMPISTRM => write!(f, "{}", "pcmpistrm"), + &Opcode::PCMPISTRI => write!(f, "{}", "pcmpistri"), + &Opcode::PCMPESTRI => write!(f, "{}", "pcmpestri"), + &Opcode::PACKUSDW => write!(f, "{}", "packusdw"), + &Opcode::PCMPESTRM => write!(f, "{}", "pcmpestrm"), + &Opcode::PCMPEQQ => write!(f, "{}", "pcmpeqq"), + &Opcode::PTEST => write!(f, "{}", "ptest"), + &Opcode::PHMINPOSUW => write!(f, "{}", "phminposuw"), + &Opcode::MPSADBW => write!(f, "{}", "mpsadbw"), + &Opcode::PMOVZXDQ => write!(f, "{}", "pmovzxdq"), + &Opcode::PMOVSXDQ => write!(f, "{}", "pmovsxdq"), + &Opcode::PMOVZXBD => write!(f, "{}", "pmovzxbd"), + &Opcode::PMOVSXBD => write!(f, "{}", "pmovsxbd"), + &Opcode::PMOVZXWQ => write!(f, "{}", "pmovzxwq"), + &Opcode::PMOVSXWQ => write!(f, "{}", "pmovsxwq"), + &Opcode::PMOVZXBQ => write!(f, "{}", "pmovzxbq"), + &Opcode::PMOVSXBQ => write!(f, "{}", "pmovsxbq"), + &Opcode::PMOVSXWD => write!(f, "{}", "pmovsxwd"), + &Opcode::PMOVZXWD => write!(f, "{}", "pmovzxwd"), + &Opcode::PEXTRQ => write!(f, "{}", "pextrq"), + &Opcode::PEXTRB => write!(f, "{}", "pextrb"), + &Opcode::PMOVSXBW => write!(f, "{}", "pmovsxbw"), + &Opcode::PMOVZXBW => write!(f, "{}", "pmovzxbw"), + &Opcode::PINSRQ => write!(f, "{}", "pinsrq"), + &Opcode::PINSRD => write!(f, "{}", "pinsrd"), + &Opcode::PINSRB => write!(f, "{}", "pinsrb"), + &Opcode::EXTRACTPS => write!(f, "{}", "extractps"), + &Opcode::INSERTPS => write!(f, "{}", "insertps"), + &Opcode::ROUNDSS => write!(f, "{}", "roundss"), + &Opcode::ROUNDSD => write!(f, "{}", "roundsd"), + &Opcode::ROUNDPS => write!(f, "{}", "roundps"), + &Opcode::ROUNDPD => write!(f, "{}", "roundpd"), + &Opcode::PMAXSB => write!(f, "{}", "pmaxsb"), + &Opcode::PMAXUW => write!(f, "{}", "pmaxuw"), + &Opcode::PMAXUD => write!(f, "{}", "pmaxud"), + &Opcode::PMINSD => write!(f, "{}", "pminsd"), + &Opcode::PMINSB => write!(f, "{}", "pminsb"), + &Opcode::PMINUD => write!(f, "{}", "pminud"), + &Opcode::PMINUW => write!(f, "{}", "pminuw"), + &Opcode::BLENDW => write!(f, "{}", "blendw"), + &Opcode::BLENDDVB => write!(f, "{}", "blenddvb"), + &Opcode::BLENDVPS => write!(f, "{}", "blendvps"), + &Opcode::BLENDVPD => write!(f, "{}", "blendvpd"), + &Opcode::BLENDPS => write!(f, "{}", "blendps"), + &Opcode::BLENDPD => write!(f, "{}", "blendpd"), + &Opcode::PMULDQ => write!(f, "{}", "pmuldq"), + &Opcode::MOVNTDQA => write!(f, "{}", "movntdqa"), + &Opcode::PMULLD => write!(f, "{}", "pmulld"), + &Opcode::PALIGNR => write!(f, "{}", "palignr"), + &Opcode::PSIGNW => write!(f, "{}", "psignw"), + &Opcode::PSIGND => write!(f, "{}", "psignd"), + &Opcode::PSIGNB => write!(f, "{}", "psignb"), + &Opcode::PSHUFB => write!(f, "{}", "pshufb"), + &Opcode::PMULHRSU => write!(f, "{}", "pmulhrsu"), + &Opcode::PMADDUBSW => write!(f, "{}", "pmaddubsw"), + &Opcode::PABSD => write!(f, "{}", "pabsd"), + &Opcode::PABSW => write!(f, "{}", "pabsw"), + &Opcode::PABSB => write!(f, "{}", "pabsb"), + &Opcode::PHSUBSW => write!(f, "{}", "phsubsw"), + &Opcode::PHSUBW => write!(f, "{}", "phsubw"), + &Opcode::PHSUBD => write!(f, "{}", "phsubd"), + &Opcode::PHADDD => write!(f, "{}", "phaddd"), + &Opcode::PHADDSW => write!(f, "{}", "phaddsw"), + &Opcode::PHADDW => write!(f, "{}", "phaddw"), + &Opcode::HSUBPD => write!(f, "{}", "hsubpd"), + &Opcode::HADDPD => write!(f, "{}", "haddpd"), + &Opcode::ADDSUBPD => write!(f, "{}", "addsubpd"), &Opcode::Invalid => write!(f, "{}", "invalid"), } } @@ -974,6 +1050,8 @@ impl Colorize for Opcode { Opcode::VDIVSS | Opcode::VHADDPD | Opcode::VHSUBPD | + Opcode::HADDPD | + Opcode::HSUBPD | Opcode::VMULPD | Opcode::VMULPS | Opcode::VMULSD | @@ -981,9 +1059,15 @@ impl Colorize for Opcode { Opcode::VPABSB | Opcode::VPABSD | Opcode::VPABSW | + Opcode::PABSB | + Opcode::PABSD | + Opcode::PABSW | Opcode::VPSIGNB | Opcode::VPSIGND | Opcode::VPSIGNW | + Opcode::PSIGNB | + Opcode::PSIGND | + Opcode::PSIGNW | Opcode::VPADDB | Opcode::VPADDD | Opcode::VPADDQ | @@ -1001,6 +1085,10 @@ impl Colorize for Opcode { Opcode::VPMULLD | Opcode::VPMULLW | Opcode::VPMULUDQ | + Opcode::PCLMULQDQ | + Opcode::PMULDQ | + Opcode::PMULHRSU | + Opcode::PMULLD | Opcode::VPSUBB | Opcode::VPSUBD | Opcode::VPSUBQ | @@ -1021,6 +1109,10 @@ impl Colorize for Opcode { Opcode::VRCPSS | Opcode::VROUNDSD | Opcode::VROUNDSS | + Opcode::ROUNDPD | + Opcode::ROUNDPS | + Opcode::ROUNDSD | + Opcode::ROUNDSS | Opcode::VRSQRTSS | Opcode::VSQRTSD | Opcode::VSQRTSS | @@ -1058,6 +1150,15 @@ impl Colorize for Opcode { Opcode::VPSRLVD | Opcode::VPSRLVQ | Opcode::VPSRLW | + Opcode::PHADDD | + Opcode::PHADDSW | + Opcode::PHADDW | + Opcode::PHSUBD | + Opcode::PHSUBSW | + Opcode::PHSUBW | + Opcode::PMADDUBSW | + Opcode::ADDSUBPD | + Opcode::MPSADBW | Opcode::RCPSS | Opcode::RSQRTSS | Opcode::SQRTSD | @@ -1138,6 +1239,7 @@ impl Colorize for Opcode { Opcode::POR | Opcode::PSADBW | Opcode::PSHUFW | + Opcode::PSHUFB | Opcode::PSLLD | Opcode::PSLLQ | Opcode::PSLLW | @@ -1230,6 +1332,12 @@ impl Colorize for Opcode { Opcode::VBLENDPS | Opcode::VBLENDVPD | Opcode::VBLENDVPS | + Opcode::BLENDDVB | + Opcode::BLENDPD | + Opcode::BLENDPS | + Opcode::BLENDVPD | + Opcode::BLENDVPS | + Opcode::BLENDW | Opcode::VBROADCASTF128 | Opcode::VBROADCASTI128 | Opcode::VBROADCASTSD | @@ -1237,6 +1345,7 @@ impl Colorize for Opcode { Opcode::VEXTRACTF128 | Opcode::VEXTRACTI128 | Opcode::VEXTRACTPS | + Opcode::EXTRACTPS | Opcode::VGATHERDPD | Opcode::VGATHERDPS | Opcode::VGATHERQPD | @@ -1244,6 +1353,7 @@ impl Colorize for Opcode { Opcode::VINSERTF128 | Opcode::VINSERTI128 | Opcode::VINSERTPS | + Opcode::INSERTPS | Opcode::VMASKMOVDQU | Opcode::VMASKMOVPD | Opcode::VMASKMOVPS | @@ -1264,6 +1374,7 @@ impl Colorize for Opcode { Opcode::VMOVNTDQA | Opcode::VMOVNTPD | Opcode::VMOVNTPS | + Opcode::MOVNTDQA | Opcode::VMOVQ | Opcode::VMOVSHDUP | Opcode::VMOVSLDUP | @@ -1297,6 +1408,18 @@ impl Colorize for Opcode { Opcode::VPMOVZXDQ | Opcode::VPMOVZXWD | Opcode::VPMOVZXWQ | + Opcode::PMOVSXBD | + Opcode::PMOVSXBQ | + Opcode::PMOVSXBW | + Opcode::PMOVSXDQ | + Opcode::PMOVSXWD | + Opcode::PMOVSXWQ | + Opcode::PMOVZXBD | + Opcode::PMOVZXBQ | + Opcode::PMOVZXBW | + Opcode::PMOVZXDQ | + Opcode::PMOVZXWD | + Opcode::PMOVZXWQ | Opcode::VUNPCKHPD | Opcode::VUNPCKHPS | Opcode::VUNPCKLPD | @@ -1312,9 +1435,11 @@ impl Colorize for Opcode { Opcode::VSHUFPD | Opcode::VSHUFPS | Opcode::VPACKSSDW | + Opcode::PACKUSDW | Opcode::VPACKSSWB | Opcode::VPACKUSWB | Opcode::VPALIGNR | + Opcode::PALIGNR | Opcode::VPERM2F128 | Opcode::VPERM2I128 | Opcode::VPERMD | @@ -1327,6 +1452,11 @@ impl Colorize for Opcode { Opcode::VPEXTRD | Opcode::VPEXTRQ | Opcode::VPEXTRW | + Opcode::PEXTRB | + Opcode::PEXTRQ | + Opcode::PINSRB | + Opcode::PINSRD | + Opcode::PINSRQ | Opcode::VPINSRB | Opcode::VPINSRD | Opcode::VPINSRQ | @@ -1336,6 +1466,7 @@ impl Colorize for Opcode { Opcode::VPSHUFB | Opcode::VPSHUFD | Opcode::VPHMINPOSUW | + Opcode::PHMINPOSUW | Opcode::VZEROUPPER | Opcode::VLDDQU | Opcode::BSWAP | @@ -1495,20 +1626,34 @@ impl Colorize for Opcode { Opcode::VTESTPS | Opcode::PCMPEQB | Opcode::PCMPEQD | + Opcode::PCMPEQQ | Opcode::PCMPEQW | + Opcode::PCMPESTRI | + Opcode::PCMPESTRM | Opcode::PCMPGTB | Opcode::PCMPGTD | + Opcode::PCMPGTQ | Opcode::PCMPGTW | + Opcode::PCMPISTRI | + Opcode::PCMPISTRM | + Opcode::PTEST | Opcode::MAXPS | Opcode::MAXSD | Opcode::MAXSS | Opcode::MINPS | Opcode::MINSD | Opcode::MINSS | + Opcode::PMAXSB | Opcode::PMAXSW | Opcode::PMAXUB | + Opcode::PMAXUD | + Opcode::PMAXUW | + Opcode::PMINSB | + Opcode::PMINSD | Opcode::PMINSW | Opcode::PMINUB | + Opcode::PMINUD | + Opcode::PMINUW | Opcode::CMPS | Opcode::SCAS | Opcode::TEST | @@ -1576,6 +1721,7 @@ impl Colorize for Opcode { Opcode::CLAC | Opcode::STAC | Opcode::ENCLS | + Opcode::ENCLV | Opcode::XGETBV | Opcode::XSETBV | Opcode::VMFUNC | @@ -1586,6 +1732,12 @@ impl Colorize for Opcode { Opcode::WRPKRU | Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } + Opcode::AESDEC | + Opcode::AESDECLAST | + Opcode::AESENC | + Opcode::AESENCLAST | + Opcode::AESIMC | + Opcode::AESKEYGENASSIST | Opcode::VAESDEC | Opcode::VAESDECLAST | Opcode::VAESENC | diff --git a/src/lib.rs b/src/lib.rs index 1fbe622..272db75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -659,6 +659,7 @@ pub enum Opcode { CLAC, STAC, ENCLS, + ENCLV, XGETBV, XSETBV, VMFUNC, @@ -1109,6 +1110,82 @@ pub enum Opcode { VXORPD, VXORPS, VZEROUPPER, + + PCLMULQDQ, + AESKEYGENASSIST, + AESIMC, + AESENC, + AESENCLAST, + AESDEC, + AESDECLAST, + PCMPGTQ, + PCMPISTRM, + PCMPISTRI, + PCMPESTRI, + PACKUSDW, + PCMPESTRM, + PCMPEQQ, + PTEST, + PHMINPOSUW, + MPSADBW, + PMOVZXDQ, + PMOVSXDQ, + PMOVZXBD, + PMOVSXBD, + PMOVZXWQ, + PMOVSXWQ, + PMOVZXBQ, + PMOVSXBQ, + PMOVSXWD, + PMOVZXWD, + PEXTRQ, + PEXTRB, + PMOVSXBW, + PMOVZXBW, + PINSRQ, + PINSRD, + PINSRB, + EXTRACTPS, + INSERTPS, + ROUNDSS, + ROUNDSD, + ROUNDPS, + ROUNDPD, + PMAXSB, + PMAXUW, + PMAXUD, + PMINSD, + PMINSB, + PMINUD, + PMINUW, + BLENDW, + BLENDDVB, + BLENDVPS, + BLENDVPD, + BLENDPS, + BLENDPD, + PMULDQ, + MOVNTDQA, + PMULLD, + PALIGNR, + PSIGNW, + PSIGND, + PSIGNB, + PSHUFB, + PMULHRSU, + PMADDUBSW, + PABSD, + PABSW, + PABSB, + PHSUBSW, + PHSUBW, + PHSUBD, + PHADDD, + PHADDSW, + PHADDW, + HSUBPD, + HADDPD, + ADDSUBPD, } #[derive(Debug)] @@ -1921,6 +1998,7 @@ impl InstDecoder { return Err(()); } }*/ + Opcode::ENCLV | Opcode::ENCLS | Opcode::ENCLU => { if !self.sgx() { @@ -5194,6 +5272,9 @@ fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter if mod_bits == 0b11 { instruction.operand_count = 0; match m { + 0b000 => { + instruction.opcode = Opcode::ENCLV; + }, 0b001 => { instruction.opcode = Opcode::VMCALL; }, @@ -5324,10 +5405,10 @@ fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter let mod_bits = modrm >> 6; let m = modrm & 7; if mod_bits == 0b11 { - if m == 1 { + if m == 0 { instruction.opcode = Opcode::SWAPGS; instruction.operand_count = 0; - } else if m == 2 { + } else if m == 1 { instruction.opcode = Opcode::RDTSCP; instruction.operand_count = 0; } else { @@ -5359,9 +5440,9 @@ fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter }, 5 => { instruction.opcode = Opcode::LFENCE; - // TODO: verify on real hardware - // AMD's manual suggests their chips reject *FENCE with non-zero r/m - if decoder.amd_quirks() && !decoder.intel_quirks() { + // Intel's manual accepts m != 0, AMD supports m != 0 though the manual + // doesn't say (tested on threadripper) + if !decoder.amd_quirks() && !decoder.intel_quirks() { if m != 0 { instruction.opcode = Opcode::Invalid; return Err(()); @@ -5370,9 +5451,9 @@ fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter }, 6 => { instruction.opcode = Opcode::MFENCE; - // TODO: verify on real hardware - // AMD's manual suggests their chips reject *FENCE with non-zero r/m - if decoder.amd_quirks() && !decoder.intel_quirks() { + // Intel's manual accepts m != 0, AMD supports m != 0 though the manual + // doesn't say (tested on threadripper) + if !decoder.amd_quirks() && !decoder.intel_quirks() { if m != 0 { instruction.opcode = Opcode::Invalid; return Err(()); @@ -5381,9 +5462,9 @@ fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter }, 7 => { instruction.opcode = Opcode::SFENCE; - // TODO: verify on real hardware - // AMD's manual suggests their chips reject *FENCE with non-zero r/m - if decoder.amd_quirks() && !decoder.intel_quirks() { + // Intel's manual accepts m != 0, AMD supports m != 0 though the manual + // doesn't say (tested on threadripper) + if !decoder.amd_quirks() && !decoder.intel_quirks() { if m != 0 { instruction.opcode = Opcode::Invalid; return Err(()); diff --git a/test/test.rs b/test/test.rs index 5c78c7c..b8c14a7 100644 --- a/test/test.rs +++ b/test/test.rs @@ -148,6 +148,7 @@ fn test_0fae() { let intel = InstDecoder::minimal().with_intel_quirks(); let amd = InstDecoder::minimal().with_amd_quirks(); let default = InstDecoder::default(); + let minimal = InstDecoder::minimal(); // drawn heavily from "Table A-6. Opcode Extensions for One- and Two-byte Opcodes by Group // Number" test_display(&[0x0f, 0xae, 0x04, 0x4f], "fxsave [rdi + rcx * 2]"); @@ -163,19 +164,21 @@ fn test_0fae() { test_display_under(&intel, &[0x0f, 0xae, *modrm], text); test_display_under(&amd, &[0x0f, 0xae, *modrm], text); test_display_under(&default, &[0x0f, 0xae, *modrm], text); - // it turns out intel accepts m != 0 for {l,m,s}fence, but amd does not: + test_display_under(&minimal, &[0x0f, 0xae, *modrm], text); + // it turns out intel and amd accept m != 0 for {l,m,s}fence: // from intel: // ``` // Specification of the instruction's opcode above indicates a ModR/M byte of F0. For this // instruction, the processor ignores the r/m field of the ModR/M byte. Thus, MFENCE is encoded // by any opcode of the form 0F AE Fx, where x is in the range 0-7. // ``` - // whereas amd does not discuss the r/m field at all. it is TBD if amd also ignores the r/m - // field, but for now assumed to be rejected. + // whereas amd does not discuss the r/m field at all. at least as of zen, amd also accepts + // these encodings. for m in 1u8..8u8 { test_display_under(&intel, &[0x0f, 0xae, modrm | m], text); - test_invalid_under(&amd, &[0x0f, 0xae, modrm | m]); + test_display_under(&amd, &[0x0f, 0xae, modrm | m], text); test_display_under(&default, &[0x0f, 0xae, modrm | m], text); + test_invalid_under(&minimal, &[0x0f, 0xae, modrm | m]); } } } -- cgit v1.1