aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2025-06-01 09:11:30 +0000
committeriximeow <me@iximeow.net>2025-06-01 09:21:57 +0000
commit54538a07bf4e0b8b2335e146198cda02a49589c8 (patch)
tree6033f4b63cb1426fcce9d1240e7f8deb10461d7b /src
parent72968a35438e5284a0ba63c947e70f8880b3abb5 (diff)
revise_instruction is the same on all bitnesses, so macro it too
Diffstat (limited to 'src')
-rw-r--r--src/isa_settings.rs712
-rw-r--r--src/long_mode/isa_settings.rs705
-rw-r--r--src/long_mode/mod.rs7
-rw-r--r--src/protected_mode/isa_settings.rs705
-rw-r--r--src/protected_mode/mod.rs11
-rw-r--r--src/real_mode/isa_settings.rs706
-rw-r--r--src/real_mode/mod.rs11
7 files changed, 727 insertions, 2130 deletions
diff --git a/src/isa_settings.rs b/src/isa_settings.rs
index 63f7454..0e52274 100644
--- a/src/isa_settings.rs
+++ b/src/isa_settings.rs
@@ -9,7 +9,7 @@
macro_rules! gen_isa_settings {
(
- ($inst_ty:ty, $decode_err:ty, $featureful_decoder:ty),
+ ($inst_ty:ty, $opcode:ty, $decode_err:ty, $featureful_decoder:ty),
$(
$(#[$doc:meta])*
$feature:ident,
@@ -39,9 +39,6 @@ macro_rules! gen_isa_settings {
) => {
/// specific decode settings controlling how an x86 byte sequence is interpreted.
///
- /// notably, `InstDecoder::default()` and `DecodeEverything` are functionally equivalent in that
- /// they accept all extensions supported by the decoder.
- ///
/// TODO: many additional extension support flags.
/// * extended MMX (see `sha256:daee4e23dac983f1744126352d40cc71d47b4a9283a2a1e473837728ca9c51ac`)
/// * lots of others... tile extensions...
@@ -79,13 +76,716 @@ macro_rules! gen_isa_settings {
}
)*
}
+
+ /// optionally reject or reinterpret instruction according to settings for this decode
+ /// operation.
+ pub(crate) fn revise_instruction(settings: &$featureful_decoder, inst: &mut $inst_ty) -> Result<(), $decode_err> {
+ if inst.prefixes.evex().is_some() {
+ if !settings.avx512() {
+ return Err(<$decode_err>::InvalidOpcode);
+ } else {
+ return Ok(());
+ }
+ }
+ match inst.opcode {
+ // original 3dnow instructions. see also
+ // `3DNow-Technology-Manual.pdf`
+ // * sha256: daee4e23dac983f1744126352d40cc71d47b4a9283a2a1e473837728ca9c51ac
+ // * ref: https://www.amd.com/content/dam/amd/en/documents/archived-tech-docs/programmer-references/21928.pdf
+ // * order# 21928
+ <$opcode>::FEMMS |
+ <$opcode>::PAVGUSB |
+ <$opcode>::PFADD |
+ <$opcode>::PFSUB |
+ <$opcode>::PFSUBR |
+ <$opcode>::PFACC |
+ <$opcode>::PFCMPGE |
+ <$opcode>::PFCMPGT |
+ <$opcode>::PFCMPEQ |
+ <$opcode>::PFMAX |
+ <$opcode>::PFMIN |
+ <$opcode>::PI2FD |
+ <$opcode>::PF2ID |
+ <$opcode>::PFRCP |
+ <$opcode>::PFRSQRT |
+ <$opcode>::PFMUL |
+ <$opcode>::PFRCPIT1 |
+ <$opcode>::PFRCPIT2 |
+ <$opcode>::PFRSQIT1 |
+ <$opcode>::PMULHRW => {
+ if !settings._3dnow() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ // later extension to 3dnow. see also
+ // `AMD-Extensions-to-the-3DNow-and-MMX-Instruction-Sets.pdf`
+ // * sha256: ad847bd6877a682296fc584b4bbee354bf84c57bb97ba57e9c9adfc63cc5f465
+ // * ref: https://refspecs.linuxfoundation.org/AMD-extensions.pdf
+ // * order# 22466
+ <$opcode>::PF2IW |
+ <$opcode>::PFNACC |
+ <$opcode>::PFPNACC |
+ <$opcode>::PI2FW |
+ <$opcode>::PSWAPD => {
+ if !settings._3dnow() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::TZCNT => {
+ if !settings.bmi1() {
+ // tzcnt is only supported if bmi1 is enabled. without bmi1, this decodes as
+ // bsf.
+ inst.opcode = <$opcode>::BSF;
+ }
+ }
+ <$opcode>::LDDQU |
+ <$opcode>::ADDSUBPS |
+ <$opcode>::ADDSUBPD |
+ <$opcode>::HADDPS |
+ <$opcode>::HSUBPS |
+ <$opcode>::HADDPD |
+ <$opcode>::HSUBPD |
+ <$opcode>::MOVSHDUP |
+ <$opcode>::MOVSLDUP |
+ <$opcode>::MOVDDUP |
+ <$opcode>::MONITOR |
+ <$opcode>::MWAIT => {
+ // via Intel section 5.7, SSE3 Instructions
+ if !settings.sse3() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::PHADDW |
+ <$opcode>::PHADDSW |
+ <$opcode>::PHADDD |
+ <$opcode>::PHSUBW |
+ <$opcode>::PHSUBSW |
+ <$opcode>::PHSUBD |
+ <$opcode>::PABSB |
+ <$opcode>::PABSW |
+ <$opcode>::PABSD |
+ <$opcode>::PMADDUBSW |
+ <$opcode>::PMULHRSW |
+ <$opcode>::PSHUFB |
+ <$opcode>::PSIGNB |
+ <$opcode>::PSIGNW |
+ <$opcode>::PSIGND |
+ <$opcode>::PALIGNR => {
+ // via Intel section 5.8, SSSE3 Instructions
+ if !settings.ssse3() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::PMULLD |
+ <$opcode>::PMULDQ |
+ <$opcode>::MOVNTDQA |
+ <$opcode>::BLENDPD |
+ <$opcode>::BLENDPS |
+ <$opcode>::BLENDVPD |
+ <$opcode>::BLENDVPS |
+ <$opcode>::PBLENDVB |
+ <$opcode>::BLENDW |
+ <$opcode>::PMINUW |
+ <$opcode>::PMINUD |
+ <$opcode>::PMINSB |
+ <$opcode>::PMINSD |
+ <$opcode>::PMAXUW |
+ <$opcode>::PMAXUD |
+ <$opcode>::PMAXSB |
+ <$opcode>::PMAXSD |
+ <$opcode>::ROUNDPS |
+ <$opcode>::ROUNDPD |
+ <$opcode>::ROUNDSS |
+ <$opcode>::ROUNDSD |
+ <$opcode>::PBLENDW |
+ <$opcode>::EXTRACTPS |
+ <$opcode>::INSERTPS |
+ <$opcode>::PINSRB |
+ <$opcode>::PINSRD |
+ <$opcode>::PINSRQ |
+ <$opcode>::PMOVSXBW |
+ <$opcode>::PMOVZXBW |
+ <$opcode>::PMOVSXBD |
+ <$opcode>::PMOVZXBD |
+ <$opcode>::PMOVSXWD |
+ <$opcode>::PMOVZXWD |
+ <$opcode>::PMOVSXBQ |
+ <$opcode>::PMOVZXBQ |
+ <$opcode>::PMOVSXWQ |
+ <$opcode>::PMOVZXWQ |
+ <$opcode>::PMOVSXDQ |
+ <$opcode>::PMOVZXDQ |
+ <$opcode>::DPPS |
+ <$opcode>::DPPD |
+ <$opcode>::MPSADBW |
+ <$opcode>::PHMINPOSUW |
+ <$opcode>::PTEST |
+ <$opcode>::PCMPEQQ |
+ <$opcode>::PEXTRB |
+ <$opcode>::PEXTRW |
+ <$opcode>::PEXTRD |
+ <$opcode>::PEXTRQ |
+ <$opcode>::PACKUSDW => {
+ // via Intel section 5.10, SSE4.1 Instructions
+ if !settings.sse4_1() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::EXTRQ |
+ <$opcode>::INSERTQ |
+ <$opcode>::MOVNTSS |
+ <$opcode>::MOVNTSD => {
+ if !settings.sse4a() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::CRC32 |
+ <$opcode>::PCMPESTRI |
+ <$opcode>::PCMPESTRM |
+ <$opcode>::PCMPISTRI |
+ <$opcode>::PCMPISTRM |
+ <$opcode>::PCMPGTQ => {
+ // via Intel section 5.11, SSE4.2 Instructions
+ if !settings.sse4_2() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::AESDEC |
+ <$opcode>::AESDECLAST |
+ <$opcode>::AESENC |
+ <$opcode>::AESENCLAST |
+ <$opcode>::AESIMC |
+ <$opcode>::AESKEYGENASSIST => {
+ // via Intel section 5.12. AESNI AND PCLMULQDQ
+ if !settings.aesni() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::PCLMULQDQ => {
+ // via Intel section 5.12. AESNI AND PCLMULQDQ
+ if !settings.pclmulqdq() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::XABORT |
+ <$opcode>::XBEGIN |
+ <$opcode>::XEND |
+ <$opcode>::XTEST => {
+ if !settings.tsx() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::SHA1MSG1 |
+ <$opcode>::SHA1MSG2 |
+ <$opcode>::SHA1NEXTE |
+ <$opcode>::SHA1RNDS4 |
+ <$opcode>::SHA256MSG1 |
+ <$opcode>::SHA256MSG2 |
+ <$opcode>::SHA256RNDS2 => {
+ if !settings.sha() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::ENCLV |
+ <$opcode>::ENCLS |
+ <$opcode>::ENCLU => {
+ if !settings.sgx() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ // AVX...
+ <$opcode>::VMOVDDUP |
+ <$opcode>::VPSHUFLW |
+ <$opcode>::VPSHUFHW |
+ <$opcode>::VHADDPS |
+ <$opcode>::VHSUBPS |
+ <$opcode>::VADDSUBPS |
+ <$opcode>::VCVTPD2DQ |
+ <$opcode>::VLDDQU |
+ <$opcode>::VCOMISD |
+ <$opcode>::VCOMISS |
+ <$opcode>::VUCOMISD |
+ <$opcode>::VUCOMISS |
+ <$opcode>::VADDPD |
+ <$opcode>::VADDPS |
+ <$opcode>::VADDSD |
+ <$opcode>::VADDSS |
+ <$opcode>::VADDSUBPD |
+ <$opcode>::VBLENDPD |
+ <$opcode>::VBLENDPS |
+ <$opcode>::VBLENDVPD |
+ <$opcode>::VBLENDVPS |
+ <$opcode>::VBROADCASTF128 |
+ <$opcode>::VBROADCASTI128 |
+ <$opcode>::VBROADCASTSD |
+ <$opcode>::VBROADCASTSS |
+ <$opcode>::VCMPSD |
+ <$opcode>::VCMPSS |
+ <$opcode>::VCMPPD |
+ <$opcode>::VCMPPS |
+ <$opcode>::VCVTDQ2PD |
+ <$opcode>::VCVTDQ2PS |
+ <$opcode>::VCVTPD2PS |
+ <$opcode>::VCVTPS2DQ |
+ <$opcode>::VCVTPS2PD |
+ <$opcode>::VCVTSS2SD |
+ <$opcode>::VCVTSI2SS |
+ <$opcode>::VCVTSI2SD |
+ <$opcode>::VCVTSD2SI |
+ <$opcode>::VCVTSD2SS |
+ <$opcode>::VCVTSS2SI |
+ <$opcode>::VCVTTPD2DQ |
+ <$opcode>::VCVTTPS2DQ |
+ <$opcode>::VCVTTSS2SI |
+ <$opcode>::VCVTTSD2SI |
+ <$opcode>::VDIVPD |
+ <$opcode>::VDIVPS |
+ <$opcode>::VDIVSD |
+ <$opcode>::VDIVSS |
+ <$opcode>::VDPPD |
+ <$opcode>::VDPPS |
+ <$opcode>::VEXTRACTF128 |
+ <$opcode>::VEXTRACTI128 |
+ <$opcode>::VEXTRACTPS |
+ <$opcode>::VFMADD132PD |
+ <$opcode>::VFMADD132PS |
+ <$opcode>::VFMADD132SD |
+ <$opcode>::VFMADD132SS |
+ <$opcode>::VFMADD213PD |
+ <$opcode>::VFMADD213PS |
+ <$opcode>::VFMADD213SD |
+ <$opcode>::VFMADD213SS |
+ <$opcode>::VFMADD231PD |
+ <$opcode>::VFMADD231PS |
+ <$opcode>::VFMADD231SD |
+ <$opcode>::VFMADD231SS |
+ <$opcode>::VFMADDSUB132PD |
+ <$opcode>::VFMADDSUB132PS |
+ <$opcode>::VFMADDSUB213PD |
+ <$opcode>::VFMADDSUB213PS |
+ <$opcode>::VFMADDSUB231PD |
+ <$opcode>::VFMADDSUB231PS |
+ <$opcode>::VFMSUB132PD |
+ <$opcode>::VFMSUB132PS |
+ <$opcode>::VFMSUB132SD |
+ <$opcode>::VFMSUB132SS |
+ <$opcode>::VFMSUB213PD |
+ <$opcode>::VFMSUB213PS |
+ <$opcode>::VFMSUB213SD |
+ <$opcode>::VFMSUB213SS |
+ <$opcode>::VFMSUB231PD |
+ <$opcode>::VFMSUB231PS |
+ <$opcode>::VFMSUB231SD |
+ <$opcode>::VFMSUB231SS |
+ <$opcode>::VFMSUBADD132PD |
+ <$opcode>::VFMSUBADD132PS |
+ <$opcode>::VFMSUBADD213PD |
+ <$opcode>::VFMSUBADD213PS |
+ <$opcode>::VFMSUBADD231PD |
+ <$opcode>::VFMSUBADD231PS |
+ <$opcode>::VFNMADD132PD |
+ <$opcode>::VFNMADD132PS |
+ <$opcode>::VFNMADD132SD |
+ <$opcode>::VFNMADD132SS |
+ <$opcode>::VFNMADD213PD |
+ <$opcode>::VFNMADD213PS |
+ <$opcode>::VFNMADD213SD |
+ <$opcode>::VFNMADD213SS |
+ <$opcode>::VFNMADD231PD |
+ <$opcode>::VFNMADD231PS |
+ <$opcode>::VFNMADD231SD |
+ <$opcode>::VFNMADD231SS |
+ <$opcode>::VFNMSUB132PD |
+ <$opcode>::VFNMSUB132PS |
+ <$opcode>::VFNMSUB132SD |
+ <$opcode>::VFNMSUB132SS |
+ <$opcode>::VFNMSUB213PD |
+ <$opcode>::VFNMSUB213PS |
+ <$opcode>::VFNMSUB213SD |
+ <$opcode>::VFNMSUB213SS |
+ <$opcode>::VFNMSUB231PD |
+ <$opcode>::VFNMSUB231PS |
+ <$opcode>::VFNMSUB231SD |
+ <$opcode>::VFNMSUB231SS |
+ <$opcode>::VGATHERDPD |
+ <$opcode>::VGATHERDPS |
+ <$opcode>::VGATHERQPD |
+ <$opcode>::VGATHERQPS |
+ <$opcode>::VHADDPD |
+ <$opcode>::VHSUBPD |
+ <$opcode>::VINSERTF128 |
+ <$opcode>::VINSERTI128 |
+ <$opcode>::VINSERTPS |
+ <$opcode>::VMASKMOVDQU |
+ <$opcode>::VMASKMOVPD |
+ <$opcode>::VMASKMOVPS |
+ <$opcode>::VMAXPD |
+ <$opcode>::VMAXPS |
+ <$opcode>::VMAXSD |
+ <$opcode>::VMAXSS |
+ <$opcode>::VMINPD |
+ <$opcode>::VMINPS |
+ <$opcode>::VMINSD |
+ <$opcode>::VMINSS |
+ <$opcode>::VMOVAPD |
+ <$opcode>::VMOVAPS |
+ <$opcode>::VMOVD |
+ <$opcode>::VMOVDQA |
+ <$opcode>::VMOVDQU |
+ <$opcode>::VMOVHLPS |
+ <$opcode>::VMOVHPD |
+ <$opcode>::VMOVHPS |
+ <$opcode>::VMOVLHPS |
+ <$opcode>::VMOVLPD |
+ <$opcode>::VMOVLPS |
+ <$opcode>::VMOVMSKPD |
+ <$opcode>::VMOVMSKPS |
+ <$opcode>::VMOVNTDQ |
+ <$opcode>::VMOVNTDQA |
+ <$opcode>::VMOVNTPD |
+ <$opcode>::VMOVNTPS |
+ <$opcode>::VMOVQ |
+ <$opcode>::VMOVSS |
+ <$opcode>::VMOVSD |
+ <$opcode>::VMOVSHDUP |
+ <$opcode>::VMOVSLDUP |
+ <$opcode>::VMOVUPD |
+ <$opcode>::VMOVUPS |
+ <$opcode>::VMPSADBW |
+ <$opcode>::VMULPD |
+ <$opcode>::VMULPS |
+ <$opcode>::VMULSD |
+ <$opcode>::VMULSS |
+ <$opcode>::VPABSB |
+ <$opcode>::VPABSD |
+ <$opcode>::VPABSW |
+ <$opcode>::VPACKSSDW |
+ <$opcode>::VPACKUSDW |
+ <$opcode>::VPACKSSWB |
+ <$opcode>::VPACKUSWB |
+ <$opcode>::VPADDB |
+ <$opcode>::VPADDD |
+ <$opcode>::VPADDQ |
+ <$opcode>::VPADDSB |
+ <$opcode>::VPADDSW |
+ <$opcode>::VPADDUSB |
+ <$opcode>::VPADDUSW |
+ <$opcode>::VPADDW |
+ <$opcode>::VPALIGNR |
+ <$opcode>::VPAND |
+ <$opcode>::VANDPD |
+ <$opcode>::VANDPS |
+ <$opcode>::VANDNPD |
+ <$opcode>::VANDNPS |
+ <$opcode>::VORPD |
+ <$opcode>::VORPS |
+ <$opcode>::VPANDN |
+ <$opcode>::VPAVGB |
+ <$opcode>::VPAVGW |
+ <$opcode>::VPBLENDD |
+ <$opcode>::VPBLENDVB |
+ <$opcode>::VPBLENDW |
+ <$opcode>::VPBROADCASTB |
+ <$opcode>::VPBROADCASTD |
+ <$opcode>::VPBROADCASTQ |
+ <$opcode>::VPBROADCASTW |
+ <$opcode>::VPCLMULQDQ |
+ <$opcode>::VPCMPEQB |
+ <$opcode>::VPCMPEQD |
+ <$opcode>::VPCMPEQQ |
+ <$opcode>::VPCMPEQW |
+ <$opcode>::VPCMPGTB |
+ <$opcode>::VPCMPGTD |
+ <$opcode>::VPCMPGTQ |
+ <$opcode>::VPCMPGTW |
+ <$opcode>::VPCMPESTRI |
+ <$opcode>::VPCMPESTRM |
+ <$opcode>::VPCMPISTRI |
+ <$opcode>::VPCMPISTRM |
+ <$opcode>::VPERM2F128 |
+ <$opcode>::VPERM2I128 |
+ <$opcode>::VPERMD |
+ <$opcode>::VPERMILPD |
+ <$opcode>::VPERMILPS |
+ <$opcode>::VPERMPD |
+ <$opcode>::VPERMPS |
+ <$opcode>::VPERMQ |
+ <$opcode>::VPEXTRB |
+ <$opcode>::VPEXTRD |
+ <$opcode>::VPEXTRQ |
+ <$opcode>::VPEXTRW |
+ <$opcode>::VPGATHERDD |
+ <$opcode>::VPGATHERDQ |
+ <$opcode>::VPGATHERQD |
+ <$opcode>::VPGATHERQQ |
+ <$opcode>::VPHADDD |
+ <$opcode>::VPHADDSW |
+ <$opcode>::VPHADDW |
+ <$opcode>::VPMADDUBSW |
+ <$opcode>::VPHMINPOSUW |
+ <$opcode>::VPHSUBD |
+ <$opcode>::VPHSUBSW |
+ <$opcode>::VPHSUBW |
+ <$opcode>::VPINSRB |
+ <$opcode>::VPINSRD |
+ <$opcode>::VPINSRQ |
+ <$opcode>::VPINSRW |
+ <$opcode>::VPMADDWD |
+ <$opcode>::VPMASKMOVD |
+ <$opcode>::VPMASKMOVQ |
+ <$opcode>::VPMAXSB |
+ <$opcode>::VPMAXSD |
+ <$opcode>::VPMAXSW |
+ <$opcode>::VPMAXUB |
+ <$opcode>::VPMAXUW |
+ <$opcode>::VPMAXUD |
+ <$opcode>::VPMINSB |
+ <$opcode>::VPMINSW |
+ <$opcode>::VPMINSD |
+ <$opcode>::VPMINUB |
+ <$opcode>::VPMINUW |
+ <$opcode>::VPMINUD |
+ <$opcode>::VPMOVMSKB |
+ <$opcode>::VPMOVSXBD |
+ <$opcode>::VPMOVSXBQ |
+ <$opcode>::VPMOVSXBW |
+ <$opcode>::VPMOVSXDQ |
+ <$opcode>::VPMOVSXWD |
+ <$opcode>::VPMOVSXWQ |
+ <$opcode>::VPMOVZXBD |
+ <$opcode>::VPMOVZXBQ |
+ <$opcode>::VPMOVZXBW |
+ <$opcode>::VPMOVZXDQ |
+ <$opcode>::VPMOVZXWD |
+ <$opcode>::VPMOVZXWQ |
+ <$opcode>::VPMULDQ |
+ <$opcode>::VPMULHRSW |
+ <$opcode>::VPMULHUW |
+ <$opcode>::VPMULHW |
+ <$opcode>::VPMULLQ |
+ <$opcode>::VPMULLD |
+ <$opcode>::VPMULLW |
+ <$opcode>::VPMULUDQ |
+ <$opcode>::VPOR |
+ <$opcode>::VPSADBW |
+ <$opcode>::VPSHUFB |
+ <$opcode>::VPSHUFD |
+ <$opcode>::VPSIGNB |
+ <$opcode>::VPSIGND |
+ <$opcode>::VPSIGNW |
+ <$opcode>::VPSLLD |
+ <$opcode>::VPSLLDQ |
+ <$opcode>::VPSLLQ |
+ <$opcode>::VPSLLVD |
+ <$opcode>::VPSLLVQ |
+ <$opcode>::VPSLLW |
+ <$opcode>::VPSRAD |
+ <$opcode>::VPSRAVD |
+ <$opcode>::VPSRAW |
+ <$opcode>::VPSRLD |
+ <$opcode>::VPSRLDQ |
+ <$opcode>::VPSRLQ |
+ <$opcode>::VPSRLVD |
+ <$opcode>::VPSRLVQ |
+ <$opcode>::VPSRLW |
+ <$opcode>::VPSUBB |
+ <$opcode>::VPSUBD |
+ <$opcode>::VPSUBQ |
+ <$opcode>::VPSUBSB |
+ <$opcode>::VPSUBSW |
+ <$opcode>::VPSUBUSB |
+ <$opcode>::VPSUBUSW |
+ <$opcode>::VPSUBW |
+ <$opcode>::VPTEST |
+ <$opcode>::VPUNPCKHBW |
+ <$opcode>::VPUNPCKHDQ |
+ <$opcode>::VPUNPCKHQDQ |
+ <$opcode>::VPUNPCKHWD |
+ <$opcode>::VPUNPCKLBW |
+ <$opcode>::VPUNPCKLDQ |
+ <$opcode>::VPUNPCKLQDQ |
+ <$opcode>::VPUNPCKLWD |
+ <$opcode>::VPXOR |
+ <$opcode>::VRCPPS |
+ <$opcode>::VROUNDPD |
+ <$opcode>::VROUNDPS |
+ <$opcode>::VROUNDSD |
+ <$opcode>::VROUNDSS |
+ <$opcode>::VRSQRTPS |
+ <$opcode>::VRSQRTSS |
+ <$opcode>::VRCPSS |
+ <$opcode>::VSHUFPD |
+ <$opcode>::VSHUFPS |
+ <$opcode>::VSQRTPD |
+ <$opcode>::VSQRTPS |
+ <$opcode>::VSQRTSS |
+ <$opcode>::VSQRTSD |
+ <$opcode>::VSUBPD |
+ <$opcode>::VSUBPS |
+ <$opcode>::VSUBSD |
+ <$opcode>::VSUBSS |
+ <$opcode>::VTESTPD |
+ <$opcode>::VTESTPS |
+ <$opcode>::VUNPCKHPD |
+ <$opcode>::VUNPCKHPS |
+ <$opcode>::VUNPCKLPD |
+ <$opcode>::VUNPCKLPS |
+ <$opcode>::VXORPD |
+ <$opcode>::VXORPS |
+ <$opcode>::VZEROUPPER |
+ <$opcode>::VZEROALL |
+ <$opcode>::VLDMXCSR |
+ <$opcode>::VSTMXCSR => {
+ // TODO: check a table for these
+ if !settings.avx() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::VAESDEC |
+ <$opcode>::VAESDECLAST |
+ <$opcode>::VAESENC |
+ <$opcode>::VAESENCLAST |
+ <$opcode>::VAESIMC |
+ <$opcode>::VAESKEYGENASSIST => {
+ // TODO: check a table for these
+ if !settings.avx() || !settings.aesni() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::MOVBE => {
+ if !settings.movbe() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::POPCNT => {
+ /*
+ * from the intel SDM:
+ * ```
+ * Before an application attempts to use the POPCNT instruction, it must check that
+ * the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1) and POPCNT
+ * (if CPUID.01H:ECX.POPCNT[bit 23] = 1).
+ * ```
+ */
+ if settings.intel_quirks() && (settings.sse4_2() || settings.popcnt()) {
+ return Ok(());
+ } else if !settings.popcnt() {
+ /*
+ * elsewhere from the amd APM:
+ * `Instruction Subsets and CPUID Feature Flags` on page 507 indicates that
+ * popcnt is present when the popcnt bit is reported by cpuid. this seems to be
+ * the less quirky default, so `intel_quirks` is considered the outlier, and
+ * before this default.
+ * */
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::LZCNT => {
+ /*
+ * amd APM, `LZCNT` page 212:
+ * LZCNT is an Advanced Bit Manipulation (ABM) instruction. Support for the LZCNT
+ * instruction is indicated by CPUID Fn8000_0001_ECX[ABM] = 1.
+ *
+ * meanwhile the intel SDM simply states:
+ * ```
+ * CPUID.EAX=80000001H:ECX.LZCNT[bit 5]: if 1 indicates the processor supports the
+ * LZCNT instruction.
+ * ```
+ *
+ * so that's considered the less-quirky (default) case here.
+ * */
+ if settings.amd_quirks() && !settings.abm() {
+ return Err(<$decode_err>::InvalidOpcode);
+ } else if !settings.lzcnt() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::ADCX |
+ <$opcode>::ADOX => {
+ if !settings.adx() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::VMRUN |
+ <$opcode>::VMLOAD |
+ <$opcode>::VMSAVE |
+ <$opcode>::CLGI |
+ <$opcode>::VMMCALL |
+ <$opcode>::INVLPGA => {
+ if !settings.svm() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::STGI |
+ <$opcode>::SKINIT => {
+ if !settings.svm() || !settings.skinit() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::LAHF |
+ <$opcode>::SAHF => {
+ if !settings.lahfsahf() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::VCVTPS2PH |
+ <$opcode>::VCVTPH2PS => {
+ /*
+ * from intel SDM:
+ * ```
+ * 14.4.1 Detection of F16C Instructions Application using float 16 instruction
+ * must follow a detection sequence similar to AVX to ensure: • The OS has
+ * enabled YMM state management support, • The processor support AVX as
+ * indicated by the CPUID feature flag, i.e. CPUID.01H:ECX.AVX[bit 28] = 1. •
+ * The processor support 16-bit floating-point conversion instructions via a
+ * CPUID feature flag (CPUID.01H:ECX.F16C[bit 29] = 1).
+ * ```
+ *
+ * TODO: only the VEX-coded variant of this instruction should be gated on `f16c`.
+ * the EVEX-coded variant should be gated on `avx512f` or `avx512vl` if not
+ * EVEX.512-coded.
+ */
+ if !settings.avx() || !settings.f16c() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::RDRAND => {
+ if !settings.rdrand() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::RDSEED => {
+ if !settings.rdseed() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ <$opcode>::MONITORX | <$opcode>::MWAITX | // these are gated on the `monitorx` and `mwaitx` cpuid bits, but are AMD-only.
+ <$opcode>::CLZERO | <$opcode>::RDPRU => { // again, gated on specific cpuid bits, but AMD-only.
+ if !settings.amd_quirks() {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ other => {
+ if !settings.bmi1() {
+ if BMI1.contains(&other) {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ if !settings.bmi2() {
+ if BMI2.contains(&other) {
+ return Err(<$decode_err>::InvalidOpcode);
+ }
+ }
+ }
+ }
+ Ok(())
+ }
}
}
macro_rules! gen_arch_isa_settings {
- ($inst_ty:ty, $decode_err:ty, $featureful_decoder:ty) => {
+ ($inst_ty:ty, $opcode:ty, $decode_err:ty, $featureful_decoder:ty) => {
gen_isa_settings!(
- ($inst_ty, $decode_err, $featureful_decoder),
+ ($inst_ty, $opcode, $decode_err, $featureful_decoder),
_3dnow, with_3dnow = 1;
_3dnowprefetch, with_3dnowprefetch = 2;
abm, with_abm = 3;
diff --git a/src/long_mode/isa_settings.rs b/src/long_mode/isa_settings.rs
index 10088d2..4fca174 100644
--- a/src/long_mode/isa_settings.rs
+++ b/src/long_mode/isa_settings.rs
@@ -1,706 +1,3 @@
use super::{BMI1, BMI2, DecodeError, InstDecoder, Instruction, Opcode};
-crate::isa_settings::gen_arch_isa_settings!(Instruction, DecodeError, InstDecoder);
-
-/// optionally reject or reinterpret instruction according to settings for this decode
-/// operation.
-pub(crate) fn revise_instruction(settings: &InstDecoder, inst: &mut Instruction) -> Result<(), DecodeError> {
- if inst.prefixes.evex().is_some() {
- if !settings.avx512() {
- return Err(DecodeError::InvalidOpcode);
- } else {
- return Ok(());
- }
- }
- match inst.opcode {
- // original 3dnow instructions. see also
- // `3DNow-Technology-Manual.pdf`
- // * sha256: daee4e23dac983f1744126352d40cc71d47b4a9283a2a1e473837728ca9c51ac
- // * ref: https://www.amd.com/content/dam/amd/en/documents/archived-tech-docs/programmer-references/21928.pdf
- // * order# 21928
- Opcode::FEMMS |
- Opcode::PAVGUSB |
- Opcode::PFADD |
- Opcode::PFSUB |
- Opcode::PFSUBR |
- Opcode::PFACC |
- Opcode::PFCMPGE |
- Opcode::PFCMPGT |
- Opcode::PFCMPEQ |
- Opcode::PFMAX |
- Opcode::PFMIN |
- Opcode::PI2FD |
- Opcode::PF2ID |
- Opcode::PFRCP |
- Opcode::PFRSQRT |
- Opcode::PFMUL |
- Opcode::PFRCPIT1 |
- Opcode::PFRCPIT2 |
- Opcode::PFRSQIT1 |
- Opcode::PMULHRW => {
- if !settings._3dnow() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- // later extension to 3dnow. see also
- // `AMD-Extensions-to-the-3DNow-and-MMX-Instruction-Sets.pdf`
- // * sha256: ad847bd6877a682296fc584b4bbee354bf84c57bb97ba57e9c9adfc63cc5f465
- // * ref: https://refspecs.linuxfoundation.org/AMD-extensions.pdf
- // * order# 22466
- Opcode::PF2IW |
- Opcode::PFNACC |
- Opcode::PFPNACC |
- Opcode::PI2FW |
- Opcode::PSWAPD => {
- if !settings._3dnow() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::TZCNT => {
- if !settings.bmi1() {
- // tzcnt is only supported if bmi1 is enabled. without bmi1, this decodes as
- // bsf.
- inst.opcode = Opcode::BSF;
- }
- }
- Opcode::LDDQU |
- Opcode::ADDSUBPS |
- Opcode::ADDSUBPD |
- Opcode::HADDPS |
- Opcode::HSUBPS |
- Opcode::HADDPD |
- Opcode::HSUBPD |
- Opcode::MOVSHDUP |
- Opcode::MOVSLDUP |
- Opcode::MOVDDUP |
- Opcode::MONITOR |
- Opcode::MWAIT => {
- // via Intel section 5.7, SSE3 Instructions
- if !settings.sse3() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::PHADDW |
- Opcode::PHADDSW |
- Opcode::PHADDD |
- Opcode::PHSUBW |
- Opcode::PHSUBSW |
- Opcode::PHSUBD |
- Opcode::PABSB |
- Opcode::PABSW |
- Opcode::PABSD |
- Opcode::PMADDUBSW |
- Opcode::PMULHRSW |
- Opcode::PSHUFB |
- Opcode::PSIGNB |
- Opcode::PSIGNW |
- Opcode::PSIGND |
- Opcode::PALIGNR => {
- // via Intel section 5.8, SSSE3 Instructions
- if !settings.ssse3() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::PMULLD |
- Opcode::PMULDQ |
- Opcode::MOVNTDQA |
- Opcode::BLENDPD |
- Opcode::BLENDPS |
- Opcode::BLENDVPD |
- Opcode::BLENDVPS |
- Opcode::PBLENDVB |
- Opcode::BLENDW |
- Opcode::PMINUW |
- Opcode::PMINUD |
- Opcode::PMINSB |
- Opcode::PMINSD |
- Opcode::PMAXUW |
- Opcode::PMAXUD |
- Opcode::PMAXSB |
- Opcode::PMAXSD |
- Opcode::ROUNDPS |
- Opcode::ROUNDPD |
- Opcode::ROUNDSS |
- Opcode::ROUNDSD |
- Opcode::PBLENDW |
- Opcode::EXTRACTPS |
- Opcode::INSERTPS |
- Opcode::PINSRB |
- Opcode::PINSRD |
- Opcode::PINSRQ |
- Opcode::PMOVSXBW |
- Opcode::PMOVZXBW |
- Opcode::PMOVSXBD |
- Opcode::PMOVZXBD |
- Opcode::PMOVSXWD |
- Opcode::PMOVZXWD |
- Opcode::PMOVSXBQ |
- Opcode::PMOVZXBQ |
- Opcode::PMOVSXWQ |
- Opcode::PMOVZXWQ |
- Opcode::PMOVSXDQ |
- Opcode::PMOVZXDQ |
- Opcode::DPPS |
- Opcode::DPPD |
- Opcode::MPSADBW |
- Opcode::PHMINPOSUW |
- Opcode::PTEST |
- Opcode::PCMPEQQ |
- Opcode::PEXTRB |
- Opcode::PEXTRW |
- Opcode::PEXTRD |
- Opcode::PEXTRQ |
- Opcode::PACKUSDW => {
- // via Intel section 5.10, SSE4.1 Instructions
- if !settings.sse4_1() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::EXTRQ |
- Opcode::INSERTQ |
- Opcode::MOVNTSS |
- Opcode::MOVNTSD => {
- if !settings.sse4a() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::CRC32 |
- Opcode::PCMPESTRI |
- Opcode::PCMPESTRM |
- Opcode::PCMPISTRI |
- Opcode::PCMPISTRM |
- Opcode::PCMPGTQ => {
- // via Intel section 5.11, SSE4.2 Instructions
- if !settings.sse4_2() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::AESDEC |
- Opcode::AESDECLAST |
- Opcode::AESENC |
- Opcode::AESENCLAST |
- Opcode::AESIMC |
- Opcode::AESKEYGENASSIST => {
- // via Intel section 5.12. AESNI AND PCLMULQDQ
- if !settings.aesni() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::PCLMULQDQ => {
- // via Intel section 5.12. AESNI AND PCLMULQDQ
- if !settings.pclmulqdq() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::XABORT |
- Opcode::XBEGIN |
- Opcode::XEND |
- Opcode::XTEST => {
- if !settings.tsx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::SHA1MSG1 |
- Opcode::SHA1MSG2 |
- Opcode::SHA1NEXTE |
- Opcode::SHA1RNDS4 |
- Opcode::SHA256MSG1 |
- Opcode::SHA256MSG2 |
- Opcode::SHA256RNDS2 => {
- if !settings.sha() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::ENCLV |
- Opcode::ENCLS |
- Opcode::ENCLU => {
- if !settings.sgx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- // AVX...
- Opcode::VMOVDDUP |
- Opcode::VPSHUFLW |
- Opcode::VPSHUFHW |
- Opcode::VHADDPS |
- Opcode::VHSUBPS |
- Opcode::VADDSUBPS |
- Opcode::VCVTPD2DQ |
- Opcode::VLDDQU |
- Opcode::VCOMISD |
- Opcode::VCOMISS |
- Opcode::VUCOMISD |
- Opcode::VUCOMISS |
- Opcode::VADDPD |
- Opcode::VADDPS |
- Opcode::VADDSD |
- Opcode::VADDSS |
- Opcode::VADDSUBPD |
- Opcode::VBLENDPD |
- Opcode::VBLENDPS |
- Opcode::VBLENDVPD |
- Opcode::VBLENDVPS |
- Opcode::VBROADCASTF128 |
- Opcode::VBROADCASTI128 |
- Opcode::VBROADCASTSD |
- Opcode::VBROADCASTSS |
- Opcode::VCMPSD |
- Opcode::VCMPSS |
- Opcode::VCMPPD |
- Opcode::VCMPPS |
- Opcode::VCVTDQ2PD |
- Opcode::VCVTDQ2PS |
- Opcode::VCVTPD2PS |
- Opcode::VCVTPS2DQ |
- Opcode::VCVTPS2PD |
- Opcode::VCVTSS2SD |
- Opcode::VCVTSI2SS |
- Opcode::VCVTSI2SD |
- Opcode::VCVTSD2SI |
- Opcode::VCVTSD2SS |
- Opcode::VCVTSS2SI |
- Opcode::VCVTTPD2DQ |
- Opcode::VCVTTPS2DQ |
- Opcode::VCVTTSS2SI |
- Opcode::VCVTTSD2SI |
- Opcode::VDIVPD |
- Opcode::VDIVPS |
- Opcode::VDIVSD |
- Opcode::VDIVSS |
- Opcode::VDPPD |
- Opcode::VDPPS |
- Opcode::VEXTRACTF128 |
- Opcode::VEXTRACTI128 |
- Opcode::VEXTRACTPS |
- Opcode::VFMADD132PD |
- Opcode::VFMADD132PS |
- Opcode::VFMADD132SD |
- Opcode::VFMADD132SS |
- Opcode::VFMADD213PD |
- Opcode::VFMADD213PS |
- Opcode::VFMADD213SD |
- Opcode::VFMADD213SS |
- Opcode::VFMADD231PD |
- Opcode::VFMADD231PS |
- Opcode::VFMADD231SD |
- Opcode::VFMADD231SS |
- Opcode::VFMADDSUB132PD |
- Opcode::VFMADDSUB132PS |
- Opcode::VFMADDSUB213PD |
- Opcode::VFMADDSUB213PS |
- Opcode::VFMADDSUB231PD |
- Opcode::VFMADDSUB231PS |
- Opcode::VFMSUB132PD |
- Opcode::VFMSUB132PS |
- Opcode::VFMSUB132SD |
- Opcode::VFMSUB132SS |
- Opcode::VFMSUB213PD |
- Opcode::VFMSUB213PS |
- Opcode::VFMSUB213SD |
- Opcode::VFMSUB213SS |
- Opcode::VFMSUB231PD |
- Opcode::VFMSUB231PS |
- Opcode::VFMSUB231SD |
- Opcode::VFMSUB231SS |
- Opcode::VFMSUBADD132PD |
- Opcode::VFMSUBADD132PS |
- Opcode::VFMSUBADD213PD |
- Opcode::VFMSUBADD213PS |
- Opcode::VFMSUBADD231PD |
- Opcode::VFMSUBADD231PS |
- Opcode::VFNMADD132PD |
- Opcode::VFNMADD132PS |
- Opcode::VFNMADD132SD |
- Opcode::VFNMADD132SS |
- Opcode::VFNMADD213PD |
- Opcode::VFNMADD213PS |
- Opcode::VFNMADD213SD |
- Opcode::VFNMADD213SS |
- Opcode::VFNMADD231PD |
- Opcode::VFNMADD231PS |
- Opcode::VFNMADD231SD |
- Opcode::VFNMADD231SS |
- Opcode::VFNMSUB132PD |
- Opcode::VFNMSUB132PS |
- Opcode::VFNMSUB132SD |
- Opcode::VFNMSUB132SS |
- Opcode::VFNMSUB213PD |
- Opcode::VFNMSUB213PS |
- Opcode::VFNMSUB213SD |
- Opcode::VFNMSUB213SS |
- Opcode::VFNMSUB231PD |
- Opcode::VFNMSUB231PS |
- Opcode::VFNMSUB231SD |
- Opcode::VFNMSUB231SS |
- Opcode::VGATHERDPD |
- Opcode::VGATHERDPS |
- Opcode::VGATHERQPD |
- Opcode::VGATHERQPS |
- Opcode::VHADDPD |
- Opcode::VHSUBPD |
- Opcode::VINSERTF128 |
- Opcode::VINSERTI128 |
- Opcode::VINSERTPS |
- Opcode::VMASKMOVDQU |
- Opcode::VMASKMOVPD |
- Opcode::VMASKMOVPS |
- Opcode::VMAXPD |
- Opcode::VMAXPS |
- Opcode::VMAXSD |
- Opcode::VMAXSS |
- Opcode::VMINPD |
- Opcode::VMINPS |
- Opcode::VMINSD |
- Opcode::VMINSS |
- Opcode::VMOVAPD |
- Opcode::VMOVAPS |
- Opcode::VMOVD |
- Opcode::VMOVDQA |
- Opcode::VMOVDQU |
- Opcode::VMOVHLPS |
- Opcode::VMOVHPD |
- Opcode::VMOVHPS |
- Opcode::VMOVLHPS |
- Opcode::VMOVLPD |
- Opcode::VMOVLPS |
- Opcode::VMOVMSKPD |
- Opcode::VMOVMSKPS |
- Opcode::VMOVNTDQ |
- Opcode::VMOVNTDQA |
- Opcode::VMOVNTPD |
- Opcode::VMOVNTPS |
- Opcode::VMOVQ |
- Opcode::VMOVSS |
- Opcode::VMOVSD |
- Opcode::VMOVSHDUP |
- Opcode::VMOVSLDUP |
- Opcode::VMOVUPD |
- Opcode::VMOVUPS |
- Opcode::VMPSADBW |
- Opcode::VMULPD |
- Opcode::VMULPS |
- Opcode::VMULSD |
- Opcode::VMULSS |
- Opcode::VPABSB |
- Opcode::VPABSD |
- Opcode::VPABSW |
- Opcode::VPACKSSDW |
- Opcode::VPACKUSDW |
- Opcode::VPACKSSWB |
- Opcode::VPACKUSWB |
- Opcode::VPADDB |
- Opcode::VPADDD |
- Opcode::VPADDQ |
- Opcode::VPADDSB |
- Opcode::VPADDSW |
- Opcode::VPADDUSB |
- Opcode::VPADDUSW |
- Opcode::VPADDW |
- Opcode::VPALIGNR |
- Opcode::VPAND |
- Opcode::VANDPD |
- Opcode::VANDPS |
- Opcode::VANDNPD |
- Opcode::VANDNPS |
- Opcode::VORPD |
- Opcode::VORPS |
- Opcode::VPANDN |
- Opcode::VPAVGB |
- Opcode::VPAVGW |
- Opcode::VPBLENDD |
- Opcode::VPBLENDVB |
- Opcode::VPBLENDW |
- Opcode::VPBROADCASTB |
- Opcode::VPBROADCASTD |
- Opcode::VPBROADCASTQ |
- Opcode::VPBROADCASTW |
- Opcode::VPCLMULQDQ |
- Opcode::VPCMPEQB |
- Opcode::VPCMPEQD |
- Opcode::VPCMPEQQ |
- Opcode::VPCMPEQW |
- Opcode::VPCMPGTB |
- Opcode::VPCMPGTD |
- Opcode::VPCMPGTQ |
- Opcode::VPCMPGTW |
- Opcode::VPCMPESTRI |
- Opcode::VPCMPESTRM |
- Opcode::VPCMPISTRI |
- Opcode::VPCMPISTRM |
- Opcode::VPERM2F128 |
- Opcode::VPERM2I128 |
- Opcode::VPERMD |
- Opcode::VPERMILPD |
- Opcode::VPERMILPS |
- Opcode::VPERMPD |
- Opcode::VPERMPS |
- Opcode::VPERMQ |
- Opcode::VPEXTRB |
- Opcode::VPEXTRD |
- Opcode::VPEXTRQ |
- Opcode::VPEXTRW |
- Opcode::VPGATHERDD |
- Opcode::VPGATHERDQ |
- Opcode::VPGATHERQD |
- Opcode::VPGATHERQQ |
- Opcode::VPHADDD |
- Opcode::VPHADDSW |
- Opcode::VPHADDW |
- Opcode::VPMADDUBSW |
- Opcode::VPHMINPOSUW |
- Opcode::VPHSUBD |
- Opcode::VPHSUBSW |
- Opcode::VPHSUBW |
- Opcode::VPINSRB |
- Opcode::VPINSRD |
- Opcode::VPINSRQ |
- Opcode::VPINSRW |
- Opcode::VPMADDWD |
- Opcode::VPMASKMOVD |
- Opcode::VPMASKMOVQ |
- Opcode::VPMAXSB |
- Opcode::VPMAXSD |
- Opcode::VPMAXSW |
- Opcode::VPMAXUB |
- Opcode::VPMAXUW |
- Opcode::VPMAXUD |
- Opcode::VPMINSB |
- Opcode::VPMINSW |
- Opcode::VPMINSD |
- Opcode::VPMINUB |
- Opcode::VPMINUW |
- Opcode::VPMINUD |
- Opcode::VPMOVMSKB |
- Opcode::VPMOVSXBD |
- Opcode::VPMOVSXBQ |
- Opcode::VPMOVSXBW |
- Opcode::VPMOVSXDQ |
- Opcode::VPMOVSXWD |
- Opcode::VPMOVSXWQ |
- Opcode::VPMOVZXBD |
- Opcode::VPMOVZXBQ |
- Opcode::VPMOVZXBW |
- Opcode::VPMOVZXDQ |
- Opcode::VPMOVZXWD |
- Opcode::VPMOVZXWQ |
- Opcode::VPMULDQ |
- Opcode::VPMULHRSW |
- Opcode::VPMULHUW |
- Opcode::VPMULHW |
- Opcode::VPMULLQ |
- Opcode::VPMULLD |
- Opcode::VPMULLW |
- Opcode::VPMULUDQ |
- Opcode::VPOR |
- Opcode::VPSADBW |
- Opcode::VPSHUFB |
- Opcode::VPSHUFD |
- Opcode::VPSIGNB |
- Opcode::VPSIGND |
- Opcode::VPSIGNW |
- Opcode::VPSLLD |
- Opcode::VPSLLDQ |
- Opcode::VPSLLQ |
- Opcode::VPSLLVD |
- Opcode::VPSLLVQ |
- Opcode::VPSLLW |
- Opcode::VPSRAD |
- Opcode::VPSRAVD |
- Opcode::VPSRAW |
- Opcode::VPSRLD |
- Opcode::VPSRLDQ |
- Opcode::VPSRLQ |
- Opcode::VPSRLVD |
- Opcode::VPSRLVQ |
- Opcode::VPSRLW |
- Opcode::VPSUBB |
- Opcode::VPSUBD |
- Opcode::VPSUBQ |
- Opcode::VPSUBSB |
- Opcode::VPSUBSW |
- Opcode::VPSUBUSB |
- Opcode::VPSUBUSW |
- Opcode::VPSUBW |
- Opcode::VPTEST |
- Opcode::VPUNPCKHBW |
- Opcode::VPUNPCKHDQ |
- Opcode::VPUNPCKHQDQ |
- Opcode::VPUNPCKHWD |
- Opcode::VPUNPCKLBW |
- Opcode::VPUNPCKLDQ |
- Opcode::VPUNPCKLQDQ |
- Opcode::VPUNPCKLWD |
- Opcode::VPXOR |
- Opcode::VRCPPS |
- Opcode::VROUNDPD |
- Opcode::VROUNDPS |
- Opcode::VROUNDSD |
- Opcode::VROUNDSS |
- Opcode::VRSQRTPS |
- Opcode::VRSQRTSS |
- Opcode::VRCPSS |
- Opcode::VSHUFPD |
- Opcode::VSHUFPS |
- Opcode::VSQRTPD |
- Opcode::VSQRTPS |
- Opcode::VSQRTSS |
- Opcode::VSQRTSD |
- Opcode::VSUBPD |
- Opcode::VSUBPS |
- Opcode::VSUBSD |
- Opcode::VSUBSS |
- Opcode::VTESTPD |
- Opcode::VTESTPS |
- Opcode::VUNPCKHPD |
- Opcode::VUNPCKHPS |
- Opcode::VUNPCKLPD |
- Opcode::VUNPCKLPS |
- Opcode::VXORPD |
- Opcode::VXORPS |
- Opcode::VZEROUPPER |
- Opcode::VZEROALL |
- Opcode::VLDMXCSR |
- Opcode::VSTMXCSR => {
- // TODO: check a table for these
- if !settings.avx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::VAESDEC |
- Opcode::VAESDECLAST |
- Opcode::VAESENC |
- Opcode::VAESENCLAST |
- Opcode::VAESIMC |
- Opcode::VAESKEYGENASSIST => {
- // TODO: check a table for these
- if !settings.avx() || !settings.aesni() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::MOVBE => {
- if !settings.movbe() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::POPCNT => {
- /*
- * from the intel SDM:
- * ```
- * Before an application attempts to use the POPCNT instruction, it must check that
- * the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1) and POPCNT
- * (if CPUID.01H:ECX.POPCNT[bit 23] = 1).
- * ```
- */
- if settings.intel_quirks() && (settings.sse4_2() || settings.popcnt()) {
- return Ok(());
- } else if !settings.popcnt() {
- /*
- * elsewhere from the amd APM:
- * `Instruction Subsets and CPUID Feature Flags` on page 507 indicates that
- * popcnt is present when the popcnt bit is reported by cpuid. this seems to be
- * the less quirky default, so `intel_quirks` is considered the outlier, and
- * before this default.
- * */
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::LZCNT => {
- /*
- * amd APM, `LZCNT` page 212:
- * LZCNT is an Advanced Bit Manipulation (ABM) instruction. Support for the LZCNT
- * instruction is indicated by CPUID Fn8000_0001_ECX[ABM] = 1.
- *
- * meanwhile the intel SDM simply states:
- * ```
- * CPUID.EAX=80000001H:ECX.LZCNT[bit 5]: if 1 indicates the processor supports the
- * LZCNT instruction.
- * ```
- *
- * so that's considered the less-quirky (default) case here.
- * */
- if settings.amd_quirks() && !settings.abm() {
- return Err(DecodeError::InvalidOpcode);
- } else if !settings.lzcnt() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::ADCX |
- Opcode::ADOX => {
- if !settings.adx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::VMRUN |
- Opcode::VMLOAD |
- Opcode::VMSAVE |
- Opcode::CLGI |
- Opcode::VMMCALL |
- Opcode::INVLPGA => {
- if !settings.svm() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::STGI |
- Opcode::SKINIT => {
- if !settings.svm() || !settings.skinit() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::LAHF |
- Opcode::SAHF => {
- if !settings.lahfsahf() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::VCVTPS2PH |
- Opcode::VCVTPH2PS => {
- /*
- * from intel SDM:
- * ```
- * 14.4.1 Detection of F16C Instructions Application using float 16 instruction
- * must follow a detection sequence similar to AVX to ensure: • The OS has
- * enabled YMM state management support, • The processor support AVX as
- * indicated by the CPUID feature flag, i.e. CPUID.01H:ECX.AVX[bit 28] = 1. •
- * The processor support 16-bit floating-point conversion instructions via a
- * CPUID feature flag (CPUID.01H:ECX.F16C[bit 29] = 1).
- * ```
- *
- * TODO: only the VEX-coded variant of this instruction should be gated on `f16c`.
- * the EVEX-coded variant should be gated on `avx512f` or `avx512vl` if not
- * EVEX.512-coded.
- */
- if !settings.avx() || !settings.f16c() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::RDRAND => {
- if !settings.rdrand() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::RDSEED => {
- if !settings.rdseed() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::MONITORX | Opcode::MWAITX | // these are gated on the `monitorx` and `mwaitx` cpuid bits, but are AMD-only.
- Opcode::CLZERO | Opcode::RDPRU => { // again, gated on specific cpuid bits, but AMD-only.
- if !settings.amd_quirks() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- other => {
- if !settings.bmi1() {
- if BMI1.contains(&other) {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- if !settings.bmi2() {
- if BMI2.contains(&other) {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- }
- }
- Ok(())
-}
+crate::isa_settings::gen_arch_isa_settings!(Instruction, Opcode, DecodeError, InstDecoder);
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index e471391..1ec924a 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -3,7 +3,6 @@ mod evex;
#[cfg(feature = "fmt")]
mod display;
pub mod uarch;
-mod isa_settings;
pub use crate::MemoryAccessSize;
@@ -19,6 +18,10 @@ use yaxpeax_arch::annotation::{AnnotatingDecoder, DescriptionSink, NullSink};
use yaxpeax_arch::{DecodeError as ArchDecodeError};
use yaxpeax_arch::safer_unchecked::unreachable_kinda_unchecked as unreachable_unchecked;
+// generate InstDecoder settings and `revise_instruction` here. a bit early, but
+// gets it out of the way..
+crate::isa_settings::gen_arch_isa_settings!(Instruction, Opcode, DecodeError, InstDecoder);
+
use core::fmt;
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -2865,7 +2868,7 @@ fn decode_with_annotation<
return Err(DecodeError::TooLong);
}
- isa_settings::revise_instruction(decoder, instr)?;
+ revise_instruction(decoder, instr)?;
Ok(())
}
diff --git a/src/protected_mode/isa_settings.rs b/src/protected_mode/isa_settings.rs
index 10088d2..4fca174 100644
--- a/src/protected_mode/isa_settings.rs
+++ b/src/protected_mode/isa_settings.rs
@@ -1,706 +1,3 @@
use super::{BMI1, BMI2, DecodeError, InstDecoder, Instruction, Opcode};
-crate::isa_settings::gen_arch_isa_settings!(Instruction, DecodeError, InstDecoder);
-
-/// optionally reject or reinterpret instruction according to settings for this decode
-/// operation.
-pub(crate) fn revise_instruction(settings: &InstDecoder, inst: &mut Instruction) -> Result<(), DecodeError> {
- if inst.prefixes.evex().is_some() {
- if !settings.avx512() {
- return Err(DecodeError::InvalidOpcode);
- } else {
- return Ok(());
- }
- }
- match inst.opcode {
- // original 3dnow instructions. see also
- // `3DNow-Technology-Manual.pdf`
- // * sha256: daee4e23dac983f1744126352d40cc71d47b4a9283a2a1e473837728ca9c51ac
- // * ref: https://www.amd.com/content/dam/amd/en/documents/archived-tech-docs/programmer-references/21928.pdf
- // * order# 21928
- Opcode::FEMMS |
- Opcode::PAVGUSB |
- Opcode::PFADD |
- Opcode::PFSUB |
- Opcode::PFSUBR |
- Opcode::PFACC |
- Opcode::PFCMPGE |
- Opcode::PFCMPGT |
- Opcode::PFCMPEQ |
- Opcode::PFMAX |
- Opcode::PFMIN |
- Opcode::PI2FD |
- Opcode::PF2ID |
- Opcode::PFRCP |
- Opcode::PFRSQRT |
- Opcode::PFMUL |
- Opcode::PFRCPIT1 |
- Opcode::PFRCPIT2 |
- Opcode::PFRSQIT1 |
- Opcode::PMULHRW => {
- if !settings._3dnow() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- // later extension to 3dnow. see also
- // `AMD-Extensions-to-the-3DNow-and-MMX-Instruction-Sets.pdf`
- // * sha256: ad847bd6877a682296fc584b4bbee354bf84c57bb97ba57e9c9adfc63cc5f465
- // * ref: https://refspecs.linuxfoundation.org/AMD-extensions.pdf
- // * order# 22466
- Opcode::PF2IW |
- Opcode::PFNACC |
- Opcode::PFPNACC |
- Opcode::PI2FW |
- Opcode::PSWAPD => {
- if !settings._3dnow() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::TZCNT => {
- if !settings.bmi1() {
- // tzcnt is only supported if bmi1 is enabled. without bmi1, this decodes as
- // bsf.
- inst.opcode = Opcode::BSF;
- }
- }
- Opcode::LDDQU |
- Opcode::ADDSUBPS |
- Opcode::ADDSUBPD |
- Opcode::HADDPS |
- Opcode::HSUBPS |
- Opcode::HADDPD |
- Opcode::HSUBPD |
- Opcode::MOVSHDUP |
- Opcode::MOVSLDUP |
- Opcode::MOVDDUP |
- Opcode::MONITOR |
- Opcode::MWAIT => {
- // via Intel section 5.7, SSE3 Instructions
- if !settings.sse3() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::PHADDW |
- Opcode::PHADDSW |
- Opcode::PHADDD |
- Opcode::PHSUBW |
- Opcode::PHSUBSW |
- Opcode::PHSUBD |
- Opcode::PABSB |
- Opcode::PABSW |
- Opcode::PABSD |
- Opcode::PMADDUBSW |
- Opcode::PMULHRSW |
- Opcode::PSHUFB |
- Opcode::PSIGNB |
- Opcode::PSIGNW |
- Opcode::PSIGND |
- Opcode::PALIGNR => {
- // via Intel section 5.8, SSSE3 Instructions
- if !settings.ssse3() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::PMULLD |
- Opcode::PMULDQ |
- Opcode::MOVNTDQA |
- Opcode::BLENDPD |
- Opcode::BLENDPS |
- Opcode::BLENDVPD |
- Opcode::BLENDVPS |
- Opcode::PBLENDVB |
- Opcode::BLENDW |
- Opcode::PMINUW |
- Opcode::PMINUD |
- Opcode::PMINSB |
- Opcode::PMINSD |
- Opcode::PMAXUW |
- Opcode::PMAXUD |
- Opcode::PMAXSB |
- Opcode::PMAXSD |
- Opcode::ROUNDPS |
- Opcode::ROUNDPD |
- Opcode::ROUNDSS |
- Opcode::ROUNDSD |
- Opcode::PBLENDW |
- Opcode::EXTRACTPS |
- Opcode::INSERTPS |
- Opcode::PINSRB |
- Opcode::PINSRD |
- Opcode::PINSRQ |
- Opcode::PMOVSXBW |
- Opcode::PMOVZXBW |
- Opcode::PMOVSXBD |
- Opcode::PMOVZXBD |
- Opcode::PMOVSXWD |
- Opcode::PMOVZXWD |
- Opcode::PMOVSXBQ |
- Opcode::PMOVZXBQ |
- Opcode::PMOVSXWQ |
- Opcode::PMOVZXWQ |
- Opcode::PMOVSXDQ |
- Opcode::PMOVZXDQ |
- Opcode::DPPS |
- Opcode::DPPD |
- Opcode::MPSADBW |
- Opcode::PHMINPOSUW |
- Opcode::PTEST |
- Opcode::PCMPEQQ |
- Opcode::PEXTRB |
- Opcode::PEXTRW |
- Opcode::PEXTRD |
- Opcode::PEXTRQ |
- Opcode::PACKUSDW => {
- // via Intel section 5.10, SSE4.1 Instructions
- if !settings.sse4_1() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::EXTRQ |
- Opcode::INSERTQ |
- Opcode::MOVNTSS |
- Opcode::MOVNTSD => {
- if !settings.sse4a() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::CRC32 |
- Opcode::PCMPESTRI |
- Opcode::PCMPESTRM |
- Opcode::PCMPISTRI |
- Opcode::PCMPISTRM |
- Opcode::PCMPGTQ => {
- // via Intel section 5.11, SSE4.2 Instructions
- if !settings.sse4_2() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::AESDEC |
- Opcode::AESDECLAST |
- Opcode::AESENC |
- Opcode::AESENCLAST |
- Opcode::AESIMC |
- Opcode::AESKEYGENASSIST => {
- // via Intel section 5.12. AESNI AND PCLMULQDQ
- if !settings.aesni() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::PCLMULQDQ => {
- // via Intel section 5.12. AESNI AND PCLMULQDQ
- if !settings.pclmulqdq() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::XABORT |
- Opcode::XBEGIN |
- Opcode::XEND |
- Opcode::XTEST => {
- if !settings.tsx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::SHA1MSG1 |
- Opcode::SHA1MSG2 |
- Opcode::SHA1NEXTE |
- Opcode::SHA1RNDS4 |
- Opcode::SHA256MSG1 |
- Opcode::SHA256MSG2 |
- Opcode::SHA256RNDS2 => {
- if !settings.sha() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::ENCLV |
- Opcode::ENCLS |
- Opcode::ENCLU => {
- if !settings.sgx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- // AVX...
- Opcode::VMOVDDUP |
- Opcode::VPSHUFLW |
- Opcode::VPSHUFHW |
- Opcode::VHADDPS |
- Opcode::VHSUBPS |
- Opcode::VADDSUBPS |
- Opcode::VCVTPD2DQ |
- Opcode::VLDDQU |
- Opcode::VCOMISD |
- Opcode::VCOMISS |
- Opcode::VUCOMISD |
- Opcode::VUCOMISS |
- Opcode::VADDPD |
- Opcode::VADDPS |
- Opcode::VADDSD |
- Opcode::VADDSS |
- Opcode::VADDSUBPD |
- Opcode::VBLENDPD |
- Opcode::VBLENDPS |
- Opcode::VBLENDVPD |
- Opcode::VBLENDVPS |
- Opcode::VBROADCASTF128 |
- Opcode::VBROADCASTI128 |
- Opcode::VBROADCASTSD |
- Opcode::VBROADCASTSS |
- Opcode::VCMPSD |
- Opcode::VCMPSS |
- Opcode::VCMPPD |
- Opcode::VCMPPS |
- Opcode::VCVTDQ2PD |
- Opcode::VCVTDQ2PS |
- Opcode::VCVTPD2PS |
- Opcode::VCVTPS2DQ |
- Opcode::VCVTPS2PD |
- Opcode::VCVTSS2SD |
- Opcode::VCVTSI2SS |
- Opcode::VCVTSI2SD |
- Opcode::VCVTSD2SI |
- Opcode::VCVTSD2SS |
- Opcode::VCVTSS2SI |
- Opcode::VCVTTPD2DQ |
- Opcode::VCVTTPS2DQ |
- Opcode::VCVTTSS2SI |
- Opcode::VCVTTSD2SI |
- Opcode::VDIVPD |
- Opcode::VDIVPS |
- Opcode::VDIVSD |
- Opcode::VDIVSS |
- Opcode::VDPPD |
- Opcode::VDPPS |
- Opcode::VEXTRACTF128 |
- Opcode::VEXTRACTI128 |
- Opcode::VEXTRACTPS |
- Opcode::VFMADD132PD |
- Opcode::VFMADD132PS |
- Opcode::VFMADD132SD |
- Opcode::VFMADD132SS |
- Opcode::VFMADD213PD |
- Opcode::VFMADD213PS |
- Opcode::VFMADD213SD |
- Opcode::VFMADD213SS |
- Opcode::VFMADD231PD |
- Opcode::VFMADD231PS |
- Opcode::VFMADD231SD |
- Opcode::VFMADD231SS |
- Opcode::VFMADDSUB132PD |
- Opcode::VFMADDSUB132PS |
- Opcode::VFMADDSUB213PD |
- Opcode::VFMADDSUB213PS |
- Opcode::VFMADDSUB231PD |
- Opcode::VFMADDSUB231PS |
- Opcode::VFMSUB132PD |
- Opcode::VFMSUB132PS |
- Opcode::VFMSUB132SD |
- Opcode::VFMSUB132SS |
- Opcode::VFMSUB213PD |
- Opcode::VFMSUB213PS |
- Opcode::VFMSUB213SD |
- Opcode::VFMSUB213SS |
- Opcode::VFMSUB231PD |
- Opcode::VFMSUB231PS |
- Opcode::VFMSUB231SD |
- Opcode::VFMSUB231SS |
- Opcode::VFMSUBADD132PD |
- Opcode::VFMSUBADD132PS |
- Opcode::VFMSUBADD213PD |
- Opcode::VFMSUBADD213PS |
- Opcode::VFMSUBADD231PD |
- Opcode::VFMSUBADD231PS |
- Opcode::VFNMADD132PD |
- Opcode::VFNMADD132PS |
- Opcode::VFNMADD132SD |
- Opcode::VFNMADD132SS |
- Opcode::VFNMADD213PD |
- Opcode::VFNMADD213PS |
- Opcode::VFNMADD213SD |
- Opcode::VFNMADD213SS |
- Opcode::VFNMADD231PD |
- Opcode::VFNMADD231PS |
- Opcode::VFNMADD231SD |
- Opcode::VFNMADD231SS |
- Opcode::VFNMSUB132PD |
- Opcode::VFNMSUB132PS |
- Opcode::VFNMSUB132SD |
- Opcode::VFNMSUB132SS |
- Opcode::VFNMSUB213PD |
- Opcode::VFNMSUB213PS |
- Opcode::VFNMSUB213SD |
- Opcode::VFNMSUB213SS |
- Opcode::VFNMSUB231PD |
- Opcode::VFNMSUB231PS |
- Opcode::VFNMSUB231SD |
- Opcode::VFNMSUB231SS |
- Opcode::VGATHERDPD |
- Opcode::VGATHERDPS |
- Opcode::VGATHERQPD |
- Opcode::VGATHERQPS |
- Opcode::VHADDPD |
- Opcode::VHSUBPD |
- Opcode::VINSERTF128 |
- Opcode::VINSERTI128 |
- Opcode::VINSERTPS |
- Opcode::VMASKMOVDQU |
- Opcode::VMASKMOVPD |
- Opcode::VMASKMOVPS |
- Opcode::VMAXPD |
- Opcode::VMAXPS |
- Opcode::VMAXSD |
- Opcode::VMAXSS |
- Opcode::VMINPD |
- Opcode::VMINPS |
- Opcode::VMINSD |
- Opcode::VMINSS |
- Opcode::VMOVAPD |
- Opcode::VMOVAPS |
- Opcode::VMOVD |
- Opcode::VMOVDQA |
- Opcode::VMOVDQU |
- Opcode::VMOVHLPS |
- Opcode::VMOVHPD |
- Opcode::VMOVHPS |
- Opcode::VMOVLHPS |
- Opcode::VMOVLPD |
- Opcode::VMOVLPS |
- Opcode::VMOVMSKPD |
- Opcode::VMOVMSKPS |
- Opcode::VMOVNTDQ |
- Opcode::VMOVNTDQA |
- Opcode::VMOVNTPD |
- Opcode::VMOVNTPS |
- Opcode::VMOVQ |
- Opcode::VMOVSS |
- Opcode::VMOVSD |
- Opcode::VMOVSHDUP |
- Opcode::VMOVSLDUP |
- Opcode::VMOVUPD |
- Opcode::VMOVUPS |
- Opcode::VMPSADBW |
- Opcode::VMULPD |
- Opcode::VMULPS |
- Opcode::VMULSD |
- Opcode::VMULSS |
- Opcode::VPABSB |
- Opcode::VPABSD |
- Opcode::VPABSW |
- Opcode::VPACKSSDW |
- Opcode::VPACKUSDW |
- Opcode::VPACKSSWB |
- Opcode::VPACKUSWB |
- Opcode::VPADDB |
- Opcode::VPADDD |
- Opcode::VPADDQ |
- Opcode::VPADDSB |
- Opcode::VPADDSW |
- Opcode::VPADDUSB |
- Opcode::VPADDUSW |
- Opcode::VPADDW |
- Opcode::VPALIGNR |
- Opcode::VPAND |
- Opcode::VANDPD |
- Opcode::VANDPS |
- Opcode::VANDNPD |
- Opcode::VANDNPS |
- Opcode::VORPD |
- Opcode::VORPS |
- Opcode::VPANDN |
- Opcode::VPAVGB |
- Opcode::VPAVGW |
- Opcode::VPBLENDD |
- Opcode::VPBLENDVB |
- Opcode::VPBLENDW |
- Opcode::VPBROADCASTB |
- Opcode::VPBROADCASTD |
- Opcode::VPBROADCASTQ |
- Opcode::VPBROADCASTW |
- Opcode::VPCLMULQDQ |
- Opcode::VPCMPEQB |
- Opcode::VPCMPEQD |
- Opcode::VPCMPEQQ |
- Opcode::VPCMPEQW |
- Opcode::VPCMPGTB |
- Opcode::VPCMPGTD |
- Opcode::VPCMPGTQ |
- Opcode::VPCMPGTW |
- Opcode::VPCMPESTRI |
- Opcode::VPCMPESTRM |
- Opcode::VPCMPISTRI |
- Opcode::VPCMPISTRM |
- Opcode::VPERM2F128 |
- Opcode::VPERM2I128 |
- Opcode::VPERMD |
- Opcode::VPERMILPD |
- Opcode::VPERMILPS |
- Opcode::VPERMPD |
- Opcode::VPERMPS |
- Opcode::VPERMQ |
- Opcode::VPEXTRB |
- Opcode::VPEXTRD |
- Opcode::VPEXTRQ |
- Opcode::VPEXTRW |
- Opcode::VPGATHERDD |
- Opcode::VPGATHERDQ |
- Opcode::VPGATHERQD |
- Opcode::VPGATHERQQ |
- Opcode::VPHADDD |
- Opcode::VPHADDSW |
- Opcode::VPHADDW |
- Opcode::VPMADDUBSW |
- Opcode::VPHMINPOSUW |
- Opcode::VPHSUBD |
- Opcode::VPHSUBSW |
- Opcode::VPHSUBW |
- Opcode::VPINSRB |
- Opcode::VPINSRD |
- Opcode::VPINSRQ |
- Opcode::VPINSRW |
- Opcode::VPMADDWD |
- Opcode::VPMASKMOVD |
- Opcode::VPMASKMOVQ |
- Opcode::VPMAXSB |
- Opcode::VPMAXSD |
- Opcode::VPMAXSW |
- Opcode::VPMAXUB |
- Opcode::VPMAXUW |
- Opcode::VPMAXUD |
- Opcode::VPMINSB |
- Opcode::VPMINSW |
- Opcode::VPMINSD |
- Opcode::VPMINUB |
- Opcode::VPMINUW |
- Opcode::VPMINUD |
- Opcode::VPMOVMSKB |
- Opcode::VPMOVSXBD |
- Opcode::VPMOVSXBQ |
- Opcode::VPMOVSXBW |
- Opcode::VPMOVSXDQ |
- Opcode::VPMOVSXWD |
- Opcode::VPMOVSXWQ |
- Opcode::VPMOVZXBD |
- Opcode::VPMOVZXBQ |
- Opcode::VPMOVZXBW |
- Opcode::VPMOVZXDQ |
- Opcode::VPMOVZXWD |
- Opcode::VPMOVZXWQ |
- Opcode::VPMULDQ |
- Opcode::VPMULHRSW |
- Opcode::VPMULHUW |
- Opcode::VPMULHW |
- Opcode::VPMULLQ |
- Opcode::VPMULLD |
- Opcode::VPMULLW |
- Opcode::VPMULUDQ |
- Opcode::VPOR |
- Opcode::VPSADBW |
- Opcode::VPSHUFB |
- Opcode::VPSHUFD |
- Opcode::VPSIGNB |
- Opcode::VPSIGND |
- Opcode::VPSIGNW |
- Opcode::VPSLLD |
- Opcode::VPSLLDQ |
- Opcode::VPSLLQ |
- Opcode::VPSLLVD |
- Opcode::VPSLLVQ |
- Opcode::VPSLLW |
- Opcode::VPSRAD |
- Opcode::VPSRAVD |
- Opcode::VPSRAW |
- Opcode::VPSRLD |
- Opcode::VPSRLDQ |
- Opcode::VPSRLQ |
- Opcode::VPSRLVD |
- Opcode::VPSRLVQ |
- Opcode::VPSRLW |
- Opcode::VPSUBB |
- Opcode::VPSUBD |
- Opcode::VPSUBQ |
- Opcode::VPSUBSB |
- Opcode::VPSUBSW |
- Opcode::VPSUBUSB |
- Opcode::VPSUBUSW |
- Opcode::VPSUBW |
- Opcode::VPTEST |
- Opcode::VPUNPCKHBW |
- Opcode::VPUNPCKHDQ |
- Opcode::VPUNPCKHQDQ |
- Opcode::VPUNPCKHWD |
- Opcode::VPUNPCKLBW |
- Opcode::VPUNPCKLDQ |
- Opcode::VPUNPCKLQDQ |
- Opcode::VPUNPCKLWD |
- Opcode::VPXOR |
- Opcode::VRCPPS |
- Opcode::VROUNDPD |
- Opcode::VROUNDPS |
- Opcode::VROUNDSD |
- Opcode::VROUNDSS |
- Opcode::VRSQRTPS |
- Opcode::VRSQRTSS |
- Opcode::VRCPSS |
- Opcode::VSHUFPD |
- Opcode::VSHUFPS |
- Opcode::VSQRTPD |
- Opcode::VSQRTPS |
- Opcode::VSQRTSS |
- Opcode::VSQRTSD |
- Opcode::VSUBPD |
- Opcode::VSUBPS |
- Opcode::VSUBSD |
- Opcode::VSUBSS |
- Opcode::VTESTPD |
- Opcode::VTESTPS |
- Opcode::VUNPCKHPD |
- Opcode::VUNPCKHPS |
- Opcode::VUNPCKLPD |
- Opcode::VUNPCKLPS |
- Opcode::VXORPD |
- Opcode::VXORPS |
- Opcode::VZEROUPPER |
- Opcode::VZEROALL |
- Opcode::VLDMXCSR |
- Opcode::VSTMXCSR => {
- // TODO: check a table for these
- if !settings.avx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::VAESDEC |
- Opcode::VAESDECLAST |
- Opcode::VAESENC |
- Opcode::VAESENCLAST |
- Opcode::VAESIMC |
- Opcode::VAESKEYGENASSIST => {
- // TODO: check a table for these
- if !settings.avx() || !settings.aesni() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::MOVBE => {
- if !settings.movbe() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::POPCNT => {
- /*
- * from the intel SDM:
- * ```
- * Before an application attempts to use the POPCNT instruction, it must check that
- * the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1) and POPCNT
- * (if CPUID.01H:ECX.POPCNT[bit 23] = 1).
- * ```
- */
- if settings.intel_quirks() && (settings.sse4_2() || settings.popcnt()) {
- return Ok(());
- } else if !settings.popcnt() {
- /*
- * elsewhere from the amd APM:
- * `Instruction Subsets and CPUID Feature Flags` on page 507 indicates that
- * popcnt is present when the popcnt bit is reported by cpuid. this seems to be
- * the less quirky default, so `intel_quirks` is considered the outlier, and
- * before this default.
- * */
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::LZCNT => {
- /*
- * amd APM, `LZCNT` page 212:
- * LZCNT is an Advanced Bit Manipulation (ABM) instruction. Support for the LZCNT
- * instruction is indicated by CPUID Fn8000_0001_ECX[ABM] = 1.
- *
- * meanwhile the intel SDM simply states:
- * ```
- * CPUID.EAX=80000001H:ECX.LZCNT[bit 5]: if 1 indicates the processor supports the
- * LZCNT instruction.
- * ```
- *
- * so that's considered the less-quirky (default) case here.
- * */
- if settings.amd_quirks() && !settings.abm() {
- return Err(DecodeError::InvalidOpcode);
- } else if !settings.lzcnt() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::ADCX |
- Opcode::ADOX => {
- if !settings.adx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::VMRUN |
- Opcode::VMLOAD |
- Opcode::VMSAVE |
- Opcode::CLGI |
- Opcode::VMMCALL |
- Opcode::INVLPGA => {
- if !settings.svm() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::STGI |
- Opcode::SKINIT => {
- if !settings.svm() || !settings.skinit() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::LAHF |
- Opcode::SAHF => {
- if !settings.lahfsahf() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::VCVTPS2PH |
- Opcode::VCVTPH2PS => {
- /*
- * from intel SDM:
- * ```
- * 14.4.1 Detection of F16C Instructions Application using float 16 instruction
- * must follow a detection sequence similar to AVX to ensure: • The OS has
- * enabled YMM state management support, • The processor support AVX as
- * indicated by the CPUID feature flag, i.e. CPUID.01H:ECX.AVX[bit 28] = 1. •
- * The processor support 16-bit floating-point conversion instructions via a
- * CPUID feature flag (CPUID.01H:ECX.F16C[bit 29] = 1).
- * ```
- *
- * TODO: only the VEX-coded variant of this instruction should be gated on `f16c`.
- * the EVEX-coded variant should be gated on `avx512f` or `avx512vl` if not
- * EVEX.512-coded.
- */
- if !settings.avx() || !settings.f16c() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::RDRAND => {
- if !settings.rdrand() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::RDSEED => {
- if !settings.rdseed() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::MONITORX | Opcode::MWAITX | // these are gated on the `monitorx` and `mwaitx` cpuid bits, but are AMD-only.
- Opcode::CLZERO | Opcode::RDPRU => { // again, gated on specific cpuid bits, but AMD-only.
- if !settings.amd_quirks() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- other => {
- if !settings.bmi1() {
- if BMI1.contains(&other) {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- if !settings.bmi2() {
- if BMI2.contains(&other) {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- }
- }
- Ok(())
-}
+crate::isa_settings::gen_arch_isa_settings!(Instruction, Opcode, DecodeError, InstDecoder);
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index 170a830..835c934 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -3,7 +3,6 @@ mod evex;
#[cfg(feature = "fmt")]
mod display;
pub mod uarch;
-mod isa_settings;
pub use crate::MemoryAccessSize;
@@ -19,6 +18,10 @@ use yaxpeax_arch::annotation::{AnnotatingDecoder, DescriptionSink, NullSink};
use yaxpeax_arch::{DecodeError as ArchDecodeError};
use yaxpeax_arch::safer_unchecked::unreachable_kinda_unchecked as unreachable_unchecked;
+// generate InstDecoder settings and `revise_instruction` here. a bit early, but
+// gets it out of the way..
+crate::isa_settings::gen_arch_isa_settings!(Instruction, Opcode, DecodeError, InstDecoder);
+
use core::fmt;
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -2779,7 +2782,7 @@ fn decode_with_annotation<
return Err(DecodeError::TooLong);
}
- isa_settings::revise_instruction(decoder, instr)?;
+ revise_instruction(decoder, instr)?;
Ok(())
}
@@ -6546,7 +6549,7 @@ fn read_operands<
);
vex::three_byte_vex(words, modrm, instruction, sink)?;
- isa_settings::revise_instruction(decoder, instruction)?;
+ revise_instruction(decoder, instruction)?;
return Ok(());
}
@@ -6578,7 +6581,7 @@ fn read_operands<
);
vex::two_byte_vex(words, modrm, instruction, sink)?;
- isa_settings::revise_instruction(decoder, instruction)?;
+ revise_instruction(decoder, instruction)?;
return Ok(());
}
diff --git a/src/real_mode/isa_settings.rs b/src/real_mode/isa_settings.rs
index 10088d2..e69de29 100644
--- a/src/real_mode/isa_settings.rs
+++ b/src/real_mode/isa_settings.rs
@@ -1,706 +0,0 @@
-use super::{BMI1, BMI2, DecodeError, InstDecoder, Instruction, Opcode};
-
-crate::isa_settings::gen_arch_isa_settings!(Instruction, DecodeError, InstDecoder);
-
-/// optionally reject or reinterpret instruction according to settings for this decode
-/// operation.
-pub(crate) fn revise_instruction(settings: &InstDecoder, inst: &mut Instruction) -> Result<(), DecodeError> {
- if inst.prefixes.evex().is_some() {
- if !settings.avx512() {
- return Err(DecodeError::InvalidOpcode);
- } else {
- return Ok(());
- }
- }
- match inst.opcode {
- // original 3dnow instructions. see also
- // `3DNow-Technology-Manual.pdf`
- // * sha256: daee4e23dac983f1744126352d40cc71d47b4a9283a2a1e473837728ca9c51ac
- // * ref: https://www.amd.com/content/dam/amd/en/documents/archived-tech-docs/programmer-references/21928.pdf
- // * order# 21928
- Opcode::FEMMS |
- Opcode::PAVGUSB |
- Opcode::PFADD |
- Opcode::PFSUB |
- Opcode::PFSUBR |
- Opcode::PFACC |
- Opcode::PFCMPGE |
- Opcode::PFCMPGT |
- Opcode::PFCMPEQ |
- Opcode::PFMAX |
- Opcode::PFMIN |
- Opcode::PI2FD |
- Opcode::PF2ID |
- Opcode::PFRCP |
- Opcode::PFRSQRT |
- Opcode::PFMUL |
- Opcode::PFRCPIT1 |
- Opcode::PFRCPIT2 |
- Opcode::PFRSQIT1 |
- Opcode::PMULHRW => {
- if !settings._3dnow() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- // later extension to 3dnow. see also
- // `AMD-Extensions-to-the-3DNow-and-MMX-Instruction-Sets.pdf`
- // * sha256: ad847bd6877a682296fc584b4bbee354bf84c57bb97ba57e9c9adfc63cc5f465
- // * ref: https://refspecs.linuxfoundation.org/AMD-extensions.pdf
- // * order# 22466
- Opcode::PF2IW |
- Opcode::PFNACC |
- Opcode::PFPNACC |
- Opcode::PI2FW |
- Opcode::PSWAPD => {
- if !settings._3dnow() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::TZCNT => {
- if !settings.bmi1() {
- // tzcnt is only supported if bmi1 is enabled. without bmi1, this decodes as
- // bsf.
- inst.opcode = Opcode::BSF;
- }
- }
- Opcode::LDDQU |
- Opcode::ADDSUBPS |
- Opcode::ADDSUBPD |
- Opcode::HADDPS |
- Opcode::HSUBPS |
- Opcode::HADDPD |
- Opcode::HSUBPD |
- Opcode::MOVSHDUP |
- Opcode::MOVSLDUP |
- Opcode::MOVDDUP |
- Opcode::MONITOR |
- Opcode::MWAIT => {
- // via Intel section 5.7, SSE3 Instructions
- if !settings.sse3() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::PHADDW |
- Opcode::PHADDSW |
- Opcode::PHADDD |
- Opcode::PHSUBW |
- Opcode::PHSUBSW |
- Opcode::PHSUBD |
- Opcode::PABSB |
- Opcode::PABSW |
- Opcode::PABSD |
- Opcode::PMADDUBSW |
- Opcode::PMULHRSW |
- Opcode::PSHUFB |
- Opcode::PSIGNB |
- Opcode::PSIGNW |
- Opcode::PSIGND |
- Opcode::PALIGNR => {
- // via Intel section 5.8, SSSE3 Instructions
- if !settings.ssse3() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::PMULLD |
- Opcode::PMULDQ |
- Opcode::MOVNTDQA |
- Opcode::BLENDPD |
- Opcode::BLENDPS |
- Opcode::BLENDVPD |
- Opcode::BLENDVPS |
- Opcode::PBLENDVB |
- Opcode::BLENDW |
- Opcode::PMINUW |
- Opcode::PMINUD |
- Opcode::PMINSB |
- Opcode::PMINSD |
- Opcode::PMAXUW |
- Opcode::PMAXUD |
- Opcode::PMAXSB |
- Opcode::PMAXSD |
- Opcode::ROUNDPS |
- Opcode::ROUNDPD |
- Opcode::ROUNDSS |
- Opcode::ROUNDSD |
- Opcode::PBLENDW |
- Opcode::EXTRACTPS |
- Opcode::INSERTPS |
- Opcode::PINSRB |
- Opcode::PINSRD |
- Opcode::PINSRQ |
- Opcode::PMOVSXBW |
- Opcode::PMOVZXBW |
- Opcode::PMOVSXBD |
- Opcode::PMOVZXBD |
- Opcode::PMOVSXWD |
- Opcode::PMOVZXWD |
- Opcode::PMOVSXBQ |
- Opcode::PMOVZXBQ |
- Opcode::PMOVSXWQ |
- Opcode::PMOVZXWQ |
- Opcode::PMOVSXDQ |
- Opcode::PMOVZXDQ |
- Opcode::DPPS |
- Opcode::DPPD |
- Opcode::MPSADBW |
- Opcode::PHMINPOSUW |
- Opcode::PTEST |
- Opcode::PCMPEQQ |
- Opcode::PEXTRB |
- Opcode::PEXTRW |
- Opcode::PEXTRD |
- Opcode::PEXTRQ |
- Opcode::PACKUSDW => {
- // via Intel section 5.10, SSE4.1 Instructions
- if !settings.sse4_1() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::EXTRQ |
- Opcode::INSERTQ |
- Opcode::MOVNTSS |
- Opcode::MOVNTSD => {
- if !settings.sse4a() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::CRC32 |
- Opcode::PCMPESTRI |
- Opcode::PCMPESTRM |
- Opcode::PCMPISTRI |
- Opcode::PCMPISTRM |
- Opcode::PCMPGTQ => {
- // via Intel section 5.11, SSE4.2 Instructions
- if !settings.sse4_2() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::AESDEC |
- Opcode::AESDECLAST |
- Opcode::AESENC |
- Opcode::AESENCLAST |
- Opcode::AESIMC |
- Opcode::AESKEYGENASSIST => {
- // via Intel section 5.12. AESNI AND PCLMULQDQ
- if !settings.aesni() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::PCLMULQDQ => {
- // via Intel section 5.12. AESNI AND PCLMULQDQ
- if !settings.pclmulqdq() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::XABORT |
- Opcode::XBEGIN |
- Opcode::XEND |
- Opcode::XTEST => {
- if !settings.tsx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::SHA1MSG1 |
- Opcode::SHA1MSG2 |
- Opcode::SHA1NEXTE |
- Opcode::SHA1RNDS4 |
- Opcode::SHA256MSG1 |
- Opcode::SHA256MSG2 |
- Opcode::SHA256RNDS2 => {
- if !settings.sha() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::ENCLV |
- Opcode::ENCLS |
- Opcode::ENCLU => {
- if !settings.sgx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- // AVX...
- Opcode::VMOVDDUP |
- Opcode::VPSHUFLW |
- Opcode::VPSHUFHW |
- Opcode::VHADDPS |
- Opcode::VHSUBPS |
- Opcode::VADDSUBPS |
- Opcode::VCVTPD2DQ |
- Opcode::VLDDQU |
- Opcode::VCOMISD |
- Opcode::VCOMISS |
- Opcode::VUCOMISD |
- Opcode::VUCOMISS |
- Opcode::VADDPD |
- Opcode::VADDPS |
- Opcode::VADDSD |
- Opcode::VADDSS |
- Opcode::VADDSUBPD |
- Opcode::VBLENDPD |
- Opcode::VBLENDPS |
- Opcode::VBLENDVPD |
- Opcode::VBLENDVPS |
- Opcode::VBROADCASTF128 |
- Opcode::VBROADCASTI128 |
- Opcode::VBROADCASTSD |
- Opcode::VBROADCASTSS |
- Opcode::VCMPSD |
- Opcode::VCMPSS |
- Opcode::VCMPPD |
- Opcode::VCMPPS |
- Opcode::VCVTDQ2PD |
- Opcode::VCVTDQ2PS |
- Opcode::VCVTPD2PS |
- Opcode::VCVTPS2DQ |
- Opcode::VCVTPS2PD |
- Opcode::VCVTSS2SD |
- Opcode::VCVTSI2SS |
- Opcode::VCVTSI2SD |
- Opcode::VCVTSD2SI |
- Opcode::VCVTSD2SS |
- Opcode::VCVTSS2SI |
- Opcode::VCVTTPD2DQ |
- Opcode::VCVTTPS2DQ |
- Opcode::VCVTTSS2SI |
- Opcode::VCVTTSD2SI |
- Opcode::VDIVPD |
- Opcode::VDIVPS |
- Opcode::VDIVSD |
- Opcode::VDIVSS |
- Opcode::VDPPD |
- Opcode::VDPPS |
- Opcode::VEXTRACTF128 |
- Opcode::VEXTRACTI128 |
- Opcode::VEXTRACTPS |
- Opcode::VFMADD132PD |
- Opcode::VFMADD132PS |
- Opcode::VFMADD132SD |
- Opcode::VFMADD132SS |
- Opcode::VFMADD213PD |
- Opcode::VFMADD213PS |
- Opcode::VFMADD213SD |
- Opcode::VFMADD213SS |
- Opcode::VFMADD231PD |
- Opcode::VFMADD231PS |
- Opcode::VFMADD231SD |
- Opcode::VFMADD231SS |
- Opcode::VFMADDSUB132PD |
- Opcode::VFMADDSUB132PS |
- Opcode::VFMADDSUB213PD |
- Opcode::VFMADDSUB213PS |
- Opcode::VFMADDSUB231PD |
- Opcode::VFMADDSUB231PS |
- Opcode::VFMSUB132PD |
- Opcode::VFMSUB132PS |
- Opcode::VFMSUB132SD |
- Opcode::VFMSUB132SS |
- Opcode::VFMSUB213PD |
- Opcode::VFMSUB213PS |
- Opcode::VFMSUB213SD |
- Opcode::VFMSUB213SS |
- Opcode::VFMSUB231PD |
- Opcode::VFMSUB231PS |
- Opcode::VFMSUB231SD |
- Opcode::VFMSUB231SS |
- Opcode::VFMSUBADD132PD |
- Opcode::VFMSUBADD132PS |
- Opcode::VFMSUBADD213PD |
- Opcode::VFMSUBADD213PS |
- Opcode::VFMSUBADD231PD |
- Opcode::VFMSUBADD231PS |
- Opcode::VFNMADD132PD |
- Opcode::VFNMADD132PS |
- Opcode::VFNMADD132SD |
- Opcode::VFNMADD132SS |
- Opcode::VFNMADD213PD |
- Opcode::VFNMADD213PS |
- Opcode::VFNMADD213SD |
- Opcode::VFNMADD213SS |
- Opcode::VFNMADD231PD |
- Opcode::VFNMADD231PS |
- Opcode::VFNMADD231SD |
- Opcode::VFNMADD231SS |
- Opcode::VFNMSUB132PD |
- Opcode::VFNMSUB132PS |
- Opcode::VFNMSUB132SD |
- Opcode::VFNMSUB132SS |
- Opcode::VFNMSUB213PD |
- Opcode::VFNMSUB213PS |
- Opcode::VFNMSUB213SD |
- Opcode::VFNMSUB213SS |
- Opcode::VFNMSUB231PD |
- Opcode::VFNMSUB231PS |
- Opcode::VFNMSUB231SD |
- Opcode::VFNMSUB231SS |
- Opcode::VGATHERDPD |
- Opcode::VGATHERDPS |
- Opcode::VGATHERQPD |
- Opcode::VGATHERQPS |
- Opcode::VHADDPD |
- Opcode::VHSUBPD |
- Opcode::VINSERTF128 |
- Opcode::VINSERTI128 |
- Opcode::VINSERTPS |
- Opcode::VMASKMOVDQU |
- Opcode::VMASKMOVPD |
- Opcode::VMASKMOVPS |
- Opcode::VMAXPD |
- Opcode::VMAXPS |
- Opcode::VMAXSD |
- Opcode::VMAXSS |
- Opcode::VMINPD |
- Opcode::VMINPS |
- Opcode::VMINSD |
- Opcode::VMINSS |
- Opcode::VMOVAPD |
- Opcode::VMOVAPS |
- Opcode::VMOVD |
- Opcode::VMOVDQA |
- Opcode::VMOVDQU |
- Opcode::VMOVHLPS |
- Opcode::VMOVHPD |
- Opcode::VMOVHPS |
- Opcode::VMOVLHPS |
- Opcode::VMOVLPD |
- Opcode::VMOVLPS |
- Opcode::VMOVMSKPD |
- Opcode::VMOVMSKPS |
- Opcode::VMOVNTDQ |
- Opcode::VMOVNTDQA |
- Opcode::VMOVNTPD |
- Opcode::VMOVNTPS |
- Opcode::VMOVQ |
- Opcode::VMOVSS |
- Opcode::VMOVSD |
- Opcode::VMOVSHDUP |
- Opcode::VMOVSLDUP |
- Opcode::VMOVUPD |
- Opcode::VMOVUPS |
- Opcode::VMPSADBW |
- Opcode::VMULPD |
- Opcode::VMULPS |
- Opcode::VMULSD |
- Opcode::VMULSS |
- Opcode::VPABSB |
- Opcode::VPABSD |
- Opcode::VPABSW |
- Opcode::VPACKSSDW |
- Opcode::VPACKUSDW |
- Opcode::VPACKSSWB |
- Opcode::VPACKUSWB |
- Opcode::VPADDB |
- Opcode::VPADDD |
- Opcode::VPADDQ |
- Opcode::VPADDSB |
- Opcode::VPADDSW |
- Opcode::VPADDUSB |
- Opcode::VPADDUSW |
- Opcode::VPADDW |
- Opcode::VPALIGNR |
- Opcode::VPAND |
- Opcode::VANDPD |
- Opcode::VANDPS |
- Opcode::VANDNPD |
- Opcode::VANDNPS |
- Opcode::VORPD |
- Opcode::VORPS |
- Opcode::VPANDN |
- Opcode::VPAVGB |
- Opcode::VPAVGW |
- Opcode::VPBLENDD |
- Opcode::VPBLENDVB |
- Opcode::VPBLENDW |
- Opcode::VPBROADCASTB |
- Opcode::VPBROADCASTD |
- Opcode::VPBROADCASTQ |
- Opcode::VPBROADCASTW |
- Opcode::VPCLMULQDQ |
- Opcode::VPCMPEQB |
- Opcode::VPCMPEQD |
- Opcode::VPCMPEQQ |
- Opcode::VPCMPEQW |
- Opcode::VPCMPGTB |
- Opcode::VPCMPGTD |
- Opcode::VPCMPGTQ |
- Opcode::VPCMPGTW |
- Opcode::VPCMPESTRI |
- Opcode::VPCMPESTRM |
- Opcode::VPCMPISTRI |
- Opcode::VPCMPISTRM |
- Opcode::VPERM2F128 |
- Opcode::VPERM2I128 |
- Opcode::VPERMD |
- Opcode::VPERMILPD |
- Opcode::VPERMILPS |
- Opcode::VPERMPD |
- Opcode::VPERMPS |
- Opcode::VPERMQ |
- Opcode::VPEXTRB |
- Opcode::VPEXTRD |
- Opcode::VPEXTRQ |
- Opcode::VPEXTRW |
- Opcode::VPGATHERDD |
- Opcode::VPGATHERDQ |
- Opcode::VPGATHERQD |
- Opcode::VPGATHERQQ |
- Opcode::VPHADDD |
- Opcode::VPHADDSW |
- Opcode::VPHADDW |
- Opcode::VPMADDUBSW |
- Opcode::VPHMINPOSUW |
- Opcode::VPHSUBD |
- Opcode::VPHSUBSW |
- Opcode::VPHSUBW |
- Opcode::VPINSRB |
- Opcode::VPINSRD |
- Opcode::VPINSRQ |
- Opcode::VPINSRW |
- Opcode::VPMADDWD |
- Opcode::VPMASKMOVD |
- Opcode::VPMASKMOVQ |
- Opcode::VPMAXSB |
- Opcode::VPMAXSD |
- Opcode::VPMAXSW |
- Opcode::VPMAXUB |
- Opcode::VPMAXUW |
- Opcode::VPMAXUD |
- Opcode::VPMINSB |
- Opcode::VPMINSW |
- Opcode::VPMINSD |
- Opcode::VPMINUB |
- Opcode::VPMINUW |
- Opcode::VPMINUD |
- Opcode::VPMOVMSKB |
- Opcode::VPMOVSXBD |
- Opcode::VPMOVSXBQ |
- Opcode::VPMOVSXBW |
- Opcode::VPMOVSXDQ |
- Opcode::VPMOVSXWD |
- Opcode::VPMOVSXWQ |
- Opcode::VPMOVZXBD |
- Opcode::VPMOVZXBQ |
- Opcode::VPMOVZXBW |
- Opcode::VPMOVZXDQ |
- Opcode::VPMOVZXWD |
- Opcode::VPMOVZXWQ |
- Opcode::VPMULDQ |
- Opcode::VPMULHRSW |
- Opcode::VPMULHUW |
- Opcode::VPMULHW |
- Opcode::VPMULLQ |
- Opcode::VPMULLD |
- Opcode::VPMULLW |
- Opcode::VPMULUDQ |
- Opcode::VPOR |
- Opcode::VPSADBW |
- Opcode::VPSHUFB |
- Opcode::VPSHUFD |
- Opcode::VPSIGNB |
- Opcode::VPSIGND |
- Opcode::VPSIGNW |
- Opcode::VPSLLD |
- Opcode::VPSLLDQ |
- Opcode::VPSLLQ |
- Opcode::VPSLLVD |
- Opcode::VPSLLVQ |
- Opcode::VPSLLW |
- Opcode::VPSRAD |
- Opcode::VPSRAVD |
- Opcode::VPSRAW |
- Opcode::VPSRLD |
- Opcode::VPSRLDQ |
- Opcode::VPSRLQ |
- Opcode::VPSRLVD |
- Opcode::VPSRLVQ |
- Opcode::VPSRLW |
- Opcode::VPSUBB |
- Opcode::VPSUBD |
- Opcode::VPSUBQ |
- Opcode::VPSUBSB |
- Opcode::VPSUBSW |
- Opcode::VPSUBUSB |
- Opcode::VPSUBUSW |
- Opcode::VPSUBW |
- Opcode::VPTEST |
- Opcode::VPUNPCKHBW |
- Opcode::VPUNPCKHDQ |
- Opcode::VPUNPCKHQDQ |
- Opcode::VPUNPCKHWD |
- Opcode::VPUNPCKLBW |
- Opcode::VPUNPCKLDQ |
- Opcode::VPUNPCKLQDQ |
- Opcode::VPUNPCKLWD |
- Opcode::VPXOR |
- Opcode::VRCPPS |
- Opcode::VROUNDPD |
- Opcode::VROUNDPS |
- Opcode::VROUNDSD |
- Opcode::VROUNDSS |
- Opcode::VRSQRTPS |
- Opcode::VRSQRTSS |
- Opcode::VRCPSS |
- Opcode::VSHUFPD |
- Opcode::VSHUFPS |
- Opcode::VSQRTPD |
- Opcode::VSQRTPS |
- Opcode::VSQRTSS |
- Opcode::VSQRTSD |
- Opcode::VSUBPD |
- Opcode::VSUBPS |
- Opcode::VSUBSD |
- Opcode::VSUBSS |
- Opcode::VTESTPD |
- Opcode::VTESTPS |
- Opcode::VUNPCKHPD |
- Opcode::VUNPCKHPS |
- Opcode::VUNPCKLPD |
- Opcode::VUNPCKLPS |
- Opcode::VXORPD |
- Opcode::VXORPS |
- Opcode::VZEROUPPER |
- Opcode::VZEROALL |
- Opcode::VLDMXCSR |
- Opcode::VSTMXCSR => {
- // TODO: check a table for these
- if !settings.avx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::VAESDEC |
- Opcode::VAESDECLAST |
- Opcode::VAESENC |
- Opcode::VAESENCLAST |
- Opcode::VAESIMC |
- Opcode::VAESKEYGENASSIST => {
- // TODO: check a table for these
- if !settings.avx() || !settings.aesni() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::MOVBE => {
- if !settings.movbe() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::POPCNT => {
- /*
- * from the intel SDM:
- * ```
- * Before an application attempts to use the POPCNT instruction, it must check that
- * the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1) and POPCNT
- * (if CPUID.01H:ECX.POPCNT[bit 23] = 1).
- * ```
- */
- if settings.intel_quirks() && (settings.sse4_2() || settings.popcnt()) {
- return Ok(());
- } else if !settings.popcnt() {
- /*
- * elsewhere from the amd APM:
- * `Instruction Subsets and CPUID Feature Flags` on page 507 indicates that
- * popcnt is present when the popcnt bit is reported by cpuid. this seems to be
- * the less quirky default, so `intel_quirks` is considered the outlier, and
- * before this default.
- * */
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::LZCNT => {
- /*
- * amd APM, `LZCNT` page 212:
- * LZCNT is an Advanced Bit Manipulation (ABM) instruction. Support for the LZCNT
- * instruction is indicated by CPUID Fn8000_0001_ECX[ABM] = 1.
- *
- * meanwhile the intel SDM simply states:
- * ```
- * CPUID.EAX=80000001H:ECX.LZCNT[bit 5]: if 1 indicates the processor supports the
- * LZCNT instruction.
- * ```
- *
- * so that's considered the less-quirky (default) case here.
- * */
- if settings.amd_quirks() && !settings.abm() {
- return Err(DecodeError::InvalidOpcode);
- } else if !settings.lzcnt() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::ADCX |
- Opcode::ADOX => {
- if !settings.adx() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::VMRUN |
- Opcode::VMLOAD |
- Opcode::VMSAVE |
- Opcode::CLGI |
- Opcode::VMMCALL |
- Opcode::INVLPGA => {
- if !settings.svm() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::STGI |
- Opcode::SKINIT => {
- if !settings.svm() || !settings.skinit() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::LAHF |
- Opcode::SAHF => {
- if !settings.lahfsahf() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::VCVTPS2PH |
- Opcode::VCVTPH2PS => {
- /*
- * from intel SDM:
- * ```
- * 14.4.1 Detection of F16C Instructions Application using float 16 instruction
- * must follow a detection sequence similar to AVX to ensure: • The OS has
- * enabled YMM state management support, • The processor support AVX as
- * indicated by the CPUID feature flag, i.e. CPUID.01H:ECX.AVX[bit 28] = 1. •
- * The processor support 16-bit floating-point conversion instructions via a
- * CPUID feature flag (CPUID.01H:ECX.F16C[bit 29] = 1).
- * ```
- *
- * TODO: only the VEX-coded variant of this instruction should be gated on `f16c`.
- * the EVEX-coded variant should be gated on `avx512f` or `avx512vl` if not
- * EVEX.512-coded.
- */
- if !settings.avx() || !settings.f16c() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::RDRAND => {
- if !settings.rdrand() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::RDSEED => {
- if !settings.rdseed() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- Opcode::MONITORX | Opcode::MWAITX | // these are gated on the `monitorx` and `mwaitx` cpuid bits, but are AMD-only.
- Opcode::CLZERO | Opcode::RDPRU => { // again, gated on specific cpuid bits, but AMD-only.
- if !settings.amd_quirks() {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- other => {
- if !settings.bmi1() {
- if BMI1.contains(&other) {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- if !settings.bmi2() {
- if BMI2.contains(&other) {
- return Err(DecodeError::InvalidOpcode);
- }
- }
- }
- }
- Ok(())
-}
diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs
index c07d783..8037d93 100644
--- a/src/real_mode/mod.rs
+++ b/src/real_mode/mod.rs
@@ -3,7 +3,6 @@ mod evex;
#[cfg(feature = "fmt")]
mod display;
pub mod uarch;
-mod isa_settings;
pub use crate::MemoryAccessSize;
@@ -19,6 +18,10 @@ use yaxpeax_arch::annotation::{AnnotatingDecoder, DescriptionSink, NullSink};
use yaxpeax_arch::{DecodeError as ArchDecodeError};
use yaxpeax_arch::safer_unchecked::unreachable_kinda_unchecked as unreachable_unchecked;
+// generate InstDecoder settings and `revise_instruction` here. a bit early, but
+// gets it out of the way..
+crate::isa_settings::gen_arch_isa_settings!(Instruction, Opcode, DecodeError, InstDecoder);
+
use core::fmt;
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -2779,7 +2782,7 @@ fn decode_with_annotation<
return Err(DecodeError::TooLong);
}
- isa_settings::revise_instruction(decoder, instr)?;
+ revise_instruction(decoder, instr)?;
Ok(())
}
@@ -6554,7 +6557,7 @@ fn read_operands<
);
vex::three_byte_vex(words, modrm, instruction, sink)?;
- isa_settings::revise_instruction(decoder, instruction)?;
+ revise_instruction(decoder, instruction)?;
return Ok(());
}
@@ -6586,7 +6589,7 @@ fn read_operands<
);
vex::two_byte_vex(words, modrm, instruction, sink)?;
- isa_settings::revise_instruction(decoder, instruction)?;
+ revise_instruction(decoder, instruction)?;
return Ok(());
}