diff options
| -rw-r--r-- | src/isa_settings.rs | 291 | ||||
| -rw-r--r-- | src/lib.rs | 3 | ||||
| -rw-r--r-- | src/long_mode/isa_settings.rs | 274 | ||||
| -rw-r--r-- | src/protected_mode/isa_settings.rs | 249 | ||||
| -rw-r--r-- | src/real_mode/isa_settings.rs | 249 |
5 files changed, 303 insertions, 763 deletions
diff --git a/src/isa_settings.rs b/src/isa_settings.rs new file mode 100644 index 0000000..e003d80 --- /dev/null +++ b/src/isa_settings.rs @@ -0,0 +1,291 @@ +// x86 feature flags are the same for all instruction bitnesses (16, 32, 64-bit). +// in fact, the per-uarch predefined settings are also the same across bitnesses, though not *all* +// features are present on all bitnesses - at least one feature bit is hidden in non-64-bit +// execution modes. +// +// this is one big macro because the instruction and decoder types are not unified across +// bitnesses, so the whole thing is generic over those identifiers. +// as-is, `gen_arch_isa_settings!(the, module, types)` should do, though. + +macro_rules! gen_isa_settings { + ( + ($inst_ty:ty, $decode_err:ty, $featureful_decoder:ty, $unconditional_decoder:ty, $revise_inst_fn:ident), + $( + $(#[$doc:meta])* + $feature:ident, + $(#[$set_doc:item])* + $set_feature:ident = $idx:expr; + )+ + + { + $( + $(#[$composite_doc:meta])* + $composite_feature:ident = { + $first_inner_feature:ident + $(,$($inner_feature:ident$(,)?)+)? + }$(,)? + )* + } + + { + $( + $(#[$composite_set_doc:meta])* + $composite_set_feature:ident = { + $set_first_inner_feature:ident + $(,$($set_inner_feature:ident$(,)?)+)? + }$(,)? + )* + } + ) => { + /// specific decode settings controlling how an x86 byte sequence is interpreted. + /// + /// this currently exists to specify which extensions are to be accepted or rejected. the two + /// implementations provided by `yaxpeax-x86` are: + /// * [`InstDecoder`], providing configurable enablement or disablement per-extension + /// * [`DecodeEverything`], which allows all extensions supported by `yaxpeax-x86` + /// + /// 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... + pub trait IsaSettings { + $( + $(#[$doc])* + fn $feature(&self) -> bool; + )+ + + $( + $(#[$composite_doc])* + fn $composite_feature(&self) -> bool { + self.$first_inner_feature() + $($(&& self.$inner_feature())+)? + } + )* + + fn revise_instruction(&self, inst: &mut $inst_ty) -> Result<(), $decode_err> { + $revise_inst_fn(self, inst) + } + } + + impl IsaSettings for $unconditional_decoder { + $(fn $feature(&self) -> bool { true })+ + + fn revise_instruction(&self, _inst: &mut $inst_ty) -> Result<(), $decode_err> { + Ok(()) + } + } + + impl IsaSettings for $featureful_decoder { + $( + fn $feature(&self) -> bool { + let i = $idx as usize; + self.flags[i / 64] & (1 << (i % 64)) != 0 + } + )+ + } + + impl $featureful_decoder { + $( + $(#[$set_doc])* + pub fn $set_feature(mut self) -> Self { + let i = $idx as usize; + self.flags[i / 64] |= 1 << (i % 64); + self + } + )+ + + $( + $(#[$composite_set_doc])* + pub fn $composite_set_feature(&self) -> Self { + self.$set_first_inner_feature() + $($(.$set_inner_feature())+)? + } + )* + + $( + $(#[$doc])* + pub fn $feature(&self) -> bool { + <Self as IsaSettings>::$feature(self) + } + )+ + + $( + $(#[$composite_doc])* + pub fn $composite_feature(&self) -> bool { + <Self as IsaSettings>::$composite_feature(self) + } + )* + } + } +} + +macro_rules! gen_arch_isa_settings { + ($inst_ty:ty, $decode_err:ty, $featureful_decoder:ty, $unconditional_decoder:ty, $revise_inst_fn:ident) => { + gen_isa_settings!( + ($inst_ty, $decode_err, $featureful_decoder, $unconditional_decoder, $revise_inst_fn), + _3dnow, with_3dnow = 1; + _3dnowprefetch, with_3dnowprefetch = 2; + abm, with_abm = 3; + adx, with_adx = 4; + aesni, with_aesni = 5; + amd_quirks, with_amd_quirks = 6; + avx, with_avx = 7; + avx2, with_avx2 = 8; + avx512_4fmaps, with_avx512_4fmaps = 10; + avx512_4vnniw, with_avx512_4vnniw = 11; + avx512_bitalg, with_avx512_bitalg = 12; + avx512_bw, with_avx512_bw = 13; + avx512_cd, with_avx512_cd = 14; + avx512_dq, with_avx512_dq = 15; + avx512_er, with_avx512_er = 16; + avx512_f, with_avx512_f = 17; + avx512_fma, with_avx512_fma = 18; + avx512_pf, with_avx512_pf = 19; + avx512_vbmi, with_avx512_vbmi = 20; + avx512_vbmi2, with_avx512_vbmi2 = 21; + avx512_vl, with_avx512_vl = 22; + avx512_vpopcntdq, with_avx512_vpopcntdq = 23; + avx_vnni, with_avx_vnni = 24; + bmi1, with_bmi1 = 25; + #[doc="`bmi2` indicates support for the `BZHI`, `MULX`, `PDEP`, `PEXT`, `RORX`, `SARX`, `SHRX`, "] + #[doc="and `SHLX` instructions. `bmi2` is implemented in all x86_64 chips that implement `bmi`, "] + #[doc="except the amd `piledriver` and `steamroller` microarchitectures."] + bmi2, with_bmi2 = 26; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_EBX_x0`: \"CLFLUSHOPT instruction support.\""] + clflushopt, with_clflushopt = 27; + clwb, with_clwb = 28; + cmov, with_cmov = 29; + cmpxchg16b, with_cmpxchg16b = 30; + cx8, with_cx8 = 31; + f16c, with_f16c = 32; + fma3, with_fma3 = 33; + fma4, with_fma4 = 34; + gfni, with_gfni = 35; + intel_quirks, with_intel_quirks = 36; + invpcid, with_invpcid = 37; + #[doc="`lahfsahf` is only unset for early revisions of 64-bit amd and intel chips. unfortunately"] + #[doc="the clearest documentation on when these instructions were reintroduced into 64-bit"] + #[doc="architectures seems to be"] + #[doc="[wikipedia](https://en.wikipedia.org/wiki/X86-64#Older_implementations):"] + #[doc="```text"] + #[doc="Early AMD64 and Intel 64 CPUs lacked LAHF and SAHF instructions in 64-bit mode. AMD"] + #[doc="introduced these instructions (also in 64-bit mode) with their Athlon 64, Opteron and"] + #[doc="Turion 64 revision D processors in March 2005[48][49][50] while Intel introduced the"] + #[doc="instructions with the Pentium 4 G1 stepping in December 2005. The 64-bit version of Windows"] + #[doc="8.1 requires this feature.[47]"] + #[doc="```"] + #[doc=""] + #[doc="this puts reintroduction of these instructions somewhere in the middle of prescott and k8"] + #[doc="lifecycles, for intel and amd respectively. because there is no specific uarch where these"] + #[doc="features become enabled, prescott and k8 default to not supporting these instructions,"] + #[doc="where later uarches support these instructions."] + lahfsahf, with_lahfsahf = 38; + lzcnt, with_lzcnt = 39; + monitor, with_monitor = 40; + movbe, with_movbe = 41; + mpx, with_mpx = 42; + pclmulqdq, with_pclmulqdq = 43; + pcommit, with_pcommit = 44; + popcnt, with_popcnt = 45; + prefetchw, with_prefetchw = 46; + prefetchwt1, with_prefetchwt1 = 47; + rdrand, with_rdrand = 48; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_EBX_x0`: \"RDSEED instruction support.\""] + rdseed, with_rdseed = 49; + rdtscp, with_rdtscp = 50; + sgx, with_sgx = 51; + sha, with_sha = 52; + skinit, with_skinit = 53; + sse3, with_sse3 = 54; + sse4_1, with_sse4_1 = 55; + sse4_2, with_sse4_2 = 56; + sse4a, with_sse4a = 57; + ssse3, with_ssse3 = 58; + svm, with_svm = 59; + syscall, with_syscall = 60; + tbm, with_tbm = 61; + tsx, with_tsx = 62; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_ECX_x0`: \"VAES 256-bit instruction support.\""] + vaes, with_vaes = 63; + vmx, with_vmx = 64; + xop, with_xop = 65; + xsave, with_xsave = 66; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_000D_EAX_x1`: \"XSAVEC and compact XRSTOR supported.\""] + xsavec, with_xsavec = 67; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_000D_EAX_x1`: \"XSAVES, XRSTOR, and XSS are supported.\""] + xsaves, with_xsaves = 68; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_000D_EAX_x1`: \"XSAVEOPT is available.\""] + xsaveopt, with_xsaveopt = 69; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_EAX_x0`: \"FS and GS base read/write instruction support.\""] + fsgsbase, with_fsgsbase = 70; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_0001_ECX`: \"Support for MWAITX and MONITORX instructions.\""] + monitorx, with_monitorx = 71; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_0008_EBX`: \"WBNOINVD instruction supported.\""] + wbnoinvd, with_wbnoinvd = 72; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_0008_EBX`: \"CLZERO instruction supported.\""] + clzero, with_clzero = 72; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_ECX_x0`: \"RDPID instruction and TSC_AUX MSR support.\""] + rdpid, with_rdpid = 73; + #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_ECX_x0`: \"VPCLMULQDQ 256-bit instruction support.\""] + vpclmulqdq, with_vpclmulqdq = 74; + #[doc="supported in Zen 5, but not mentioned in the AMD APM as of revision 3.36."] + movdir64b, with_movdir64b = 75; + #[doc="supported in Zen 5, but not mentioned in the AMD APM as of revision 3.36."] + enqcmd, with_enqcmd = 76; + + { + sse4 = { + sse4_1, + sse4_2, + } + + #[doc = "returns `true` if this `InstDecoder` has **all** `avx512` features enabled."] + avx512 = { + avx512_4fmaps, + avx512_4vnniw, + avx512_bitalg, + avx512_bw, + avx512_cd, + avx512_dq, + avx512_er, + avx512_f, + avx512_fma, + avx512_pf, + avx512_vbmi, + avx512_vbmi2, + avx512_vl, + avx512_vpopcntdq, + }, + } + + { + with_sse4 = { + with_sse4_1, + with_sse4_2, + } + + with_avx512 = { + with_avx512_4fmaps, + with_avx512_4vnniw, + with_avx512_bitalg, + with_avx512_bw, + with_avx512_cd, + with_avx512_dq, + with_avx512_er, + with_avx512_f, + with_avx512_fma, + with_avx512_pf, + with_avx512_vbmi, + with_avx512_vbmi2, + with_avx512_vl, + with_avx512_vpopcntdq, + } + } + ); + + } +} + +pub(crate) use gen_arch_isa_settings; @@ -128,6 +128,9 @@ extern crate serde; #[cfg(feature="std")] extern crate alloc; +#[macro_use] +mod isa_settings; + pub mod long_mode; pub use long_mode as amd64; pub use long_mode::Arch as x86_64; diff --git a/src/long_mode/isa_settings.rs b/src/long_mode/isa_settings.rs index de3d6e7..77ee7e2 100644 --- a/src/long_mode/isa_settings.rs +++ b/src/long_mode/isa_settings.rs @@ -1,276 +1,8 @@ use super::{BMI1, BMI2, DecodeError, DecodeEverything, InstDecoder, Instruction, Opcode}; -macro_rules! gen_isa_settings { - ( - $( - $(#[$doc:meta])* - $feature:ident, - $(#[$set_doc:item])* - $set_feature:ident = $idx:expr; - )+ - - { - $( - $(#[$composite_doc:meta])* - $composite_feature:ident = { - $first_inner_feature:ident - $(,$($inner_feature:ident$(,)?)+)? - }$(,)? - )* - } - - { - $( - $(#[$composite_set_doc:meta])* - $composite_set_feature:ident = { - $set_first_inner_feature:ident - $(,$($set_inner_feature:ident$(,)?)+)? - }$(,)? - )* - } - ) => { - /// specific decode settings controlling how an x86 byte sequence is interpreted. - /// - /// this currently exists to specify which extensions are to be accepted or rejected. the two - /// implementations provided by `yaxpeax-x86` are: - /// * [`InstDecoder`], providing configurable enablement or disablement per-extension - /// * [`DecodeEverything`], which allows all extensions supported by `yaxpeax-x86` - /// - /// 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... - pub trait IsaSettings { - $( - $(#[$doc])* - fn $feature(&self) -> bool; - )+ - - $( - $(#[$composite_doc])* - fn $composite_feature(&self) -> bool { - self.$first_inner_feature() - $($(&& self.$inner_feature())+)? - } - )* - - fn revise_instruction(&self, inst: &mut Instruction) -> Result<(), DecodeError> { - revise_instruction(self, inst) - } - } - - impl IsaSettings for DecodeEverything { - $(fn $feature(&self) -> bool { true })+ - - fn revise_instruction(&self, _inst: &mut Instruction) -> Result<(), DecodeError> { - Ok(()) - } - } - - impl IsaSettings for InstDecoder { - $( - fn $feature(&self) -> bool { - let i = $idx as usize; - self.flags[i / 64] & (1 << (i % 64)) != 0 - } - )+ - } - - impl InstDecoder { - $( - $(#[$set_doc])* - pub fn $set_feature(mut self) -> Self { - let i = $idx as usize; - self.flags[i / 64] |= 1 << (i % 64); - self - } - )+ - - $( - $(#[$composite_set_doc])* - pub fn $composite_set_feature(&self) -> Self { - self.$set_first_inner_feature() - $($(.$set_inner_feature())+)? - } - )* - - $( - $(#[$doc])* - pub fn $feature(&self) -> bool { - <Self as IsaSettings>::$feature(self) - } - )+ - - $( - $(#[$composite_doc])* - pub fn $composite_feature(&self) -> bool { - <Self as IsaSettings>::$composite_feature(self) - } - )* - } - } -} -gen_isa_settings!( - _3dnow, with_3dnow = 1; - _3dnowprefetch, with_3dnowprefetch = 2; - abm, with_abm = 3; - adx, with_adx = 4; - aesni, with_aesni = 5; - amd_quirks, with_amd_quirks = 6; - avx, with_avx = 7; - avx2, with_avx2 = 8; - avx512_4fmaps, with_avx512_4fmaps = 10; - avx512_4vnniw, with_avx512_4vnniw = 11; - avx512_bitalg, with_avx512_bitalg = 12; - avx512_bw, with_avx512_bw = 13; - avx512_cd, with_avx512_cd = 14; - avx512_dq, with_avx512_dq = 15; - avx512_er, with_avx512_er = 16; - avx512_f, with_avx512_f = 17; - avx512_fma, with_avx512_fma = 18; - avx512_pf, with_avx512_pf = 19; - avx512_vbmi, with_avx512_vbmi = 20; - avx512_vbmi2, with_avx512_vbmi2 = 21; - avx512_vl, with_avx512_vl = 22; - avx512_vpopcntdq, with_avx512_vpopcntdq = 23; - avx_vnni, with_avx_vnni = 24; - bmi1, with_bmi1 = 25; - #[doc="`bmi2` indicates support for the `BZHI`, `MULX`, `PDEP`, `PEXT`, `RORX`, `SARX`, `SHRX`, "] - #[doc="and `SHLX` instructions. `bmi2` is implemented in all x86_64 chips that implement `bmi`, "] - #[doc="except the amd `piledriver` and `steamroller` microarchitectures."] - bmi2, with_bmi2 = 26; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_EBX_x0`: \"CLFLUSHOPT instruction support.\""] - clflushopt, with_clflushopt = 27; - clwb, with_clwb = 28; - cmov, with_cmov = 29; - cmpxchg16b, with_cmpxchg16b = 30; - cx8, with_cx8 = 31; - f16c, with_f16c = 32; - fma3, with_fma3 = 33; - fma4, with_fma4 = 34; - gfni, with_gfni = 35; - intel_quirks, with_intel_quirks = 36; - invpcid, with_invpcid = 37; - #[doc="`lahfsahf` is only unset for early revisions of 64-bit amd and intel chips. unfortunately"] - #[doc="the clearest documentation on when these instructions were reintroduced into 64-bit"] - #[doc="architectures seems to be"] - #[doc="[wikipedia](https://en.wikipedia.org/wiki/X86-64#Older_implementations):"] - #[doc="```text"] - #[doc="Early AMD64 and Intel 64 CPUs lacked LAHF and SAHF instructions in 64-bit mode. AMD"] - #[doc="introduced these instructions (also in 64-bit mode) with their Athlon 64, Opteron and"] - #[doc="Turion 64 revision D processors in March 2005[48][49][50] while Intel introduced the"] - #[doc="instructions with the Pentium 4 G1 stepping in December 2005. The 64-bit version of Windows"] - #[doc="8.1 requires this feature.[47]"] - #[doc="```"] - #[doc=""] - #[doc="this puts reintroduction of these instructions somewhere in the middle of prescott and k8"] - #[doc="lifecycles, for intel and amd respectively. because there is no specific uarch where these"] - #[doc="features become enabled, prescott and k8 default to not supporting these instructions,"] - #[doc="where later uarches support these instructions."] - lahfsahf, with_lahfsahf = 38; - lzcnt, with_lzcnt = 39; - monitor, with_monitor = 40; - movbe, with_movbe = 41; - mpx, with_mpx = 42; - pclmulqdq, with_pclmulqdq = 43; - pcommit, with_pcommit = 44; - popcnt, with_popcnt = 45; - prefetchw, with_prefetchw = 46; - prefetchwt1, with_prefetchwt1 = 47; - rdrand, with_rdrand = 48; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_EBX_x0`: \"RDSEED instruction support.\""] - rdseed, with_rdseed = 49; - rdtscp, with_rdtscp = 50; - sgx, with_sgx = 51; - sha, with_sha = 52; - skinit, with_skinit = 53; - sse3, with_sse3 = 54; - sse4_1, with_sse4_1 = 55; - sse4_2, with_sse4_2 = 56; - sse4a, with_sse4a = 57; - ssse3, with_ssse3 = 58; - svm, with_svm = 59; - syscall, with_syscall = 60; - tbm, with_tbm = 61; - tsx, with_tsx = 62; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_ECX_x0`: \"VAES 256-bit instruction support.\""] - vaes, with_vaes = 63; - vmx, with_vmx = 64; - xop, with_xop = 65; - xsave, with_xsave = 66; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_000D_EAX_x1`: \"XSAVEC and compact XRSTOR supported.\""] - xsavec, with_xsavec = 67; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_000D_EAX_x1`: \"XSAVES, XRSTOR, and XSS are supported.\""] - xsaves, with_xsaves = 68; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_000D_EAX_x1`: \"XSAVEOPT is available.\""] - xsaveopt, with_xsaveopt = 69; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_EAX_x0`: \"FS and GS base read/write instruction support.\""] - fsgsbase, with_fsgsbase = 70; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_0001_ECX`: \"Support for MWAITX and MONITORX instructions.\""] - monitorx, with_monitorx = 71; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_0008_EBX`: \"WBNOINVD instruction supported.\""] - wbnoinvd, with_wbnoinvd = 72; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_0008_EBX`: \"CLZERO instruction supported.\""] - clzero, with_clzero = 72; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_ECX_x0`: \"RDPID instruction and TSC_AUX MSR support.\""] - rdpid, with_rdpid = 73; - #[doc="from AMD APM Vol 3 `CPUID Fn0000_0007_ECX_x0`: \"VPCLMULQDQ 256-bit instruction support.\""] - vpclmulqdq, with_vpclmulqdq = 74; - #[doc="supported in Zen 5, but not mentioned in the AMD APM as of revision 3.36."] - movdir64b, with_movdir64b = 75; - #[doc="supported in Zen 5, but not mentioned in the AMD APM as of revision 3.36."] - enqcmd, with_enqcmd = 76; - - { - sse4 = { - sse4_1, - sse4_2, - } - - #[doc = "returns `true` if this `InstDecoder` has **all** `avx512` features enabled."] - avx512 = { - avx512_4fmaps, - avx512_4vnniw, - avx512_bitalg, - avx512_bw, - avx512_cd, - avx512_dq, - avx512_er, - avx512_f, - avx512_fma, - avx512_pf, - avx512_vbmi, - avx512_vbmi2, - avx512_vl, - avx512_vpopcntdq, - }, - } - - { - with_sse4 = { - with_sse4_1, - with_sse4_2, - } - - with_avx512 = { - with_avx512_4fmaps, - with_avx512_4vnniw, - with_avx512_bitalg, - with_avx512_bw, - with_avx512_cd, - with_avx512_dq, - with_avx512_er, - with_avx512_f, - with_avx512_fma, - with_avx512_pf, - with_avx512_vbmi, - with_avx512_vbmi2, - with_avx512_vl, - with_avx512_vpopcntdq, - } - } +crate::isa_settings::gen_arch_isa_settings!( + Instruction, DecodeError, InstDecoder, DecodeEverything, + revise_instruction ); /// optionally reject or reinterpret instruction according to settings for this decode diff --git a/src/protected_mode/isa_settings.rs b/src/protected_mode/isa_settings.rs index 55d18a7..77ee7e2 100644 --- a/src/protected_mode/isa_settings.rs +++ b/src/protected_mode/isa_settings.rs @@ -1,251 +1,8 @@ use super::{BMI1, BMI2, DecodeError, DecodeEverything, InstDecoder, Instruction, Opcode}; -macro_rules! gen_isa_settings { - ( - $( - $(#[$doc:meta])* - $feature:ident, - $(#[$set_doc:item])* - $set_feature:ident = $idx:expr; - )+ - - { - $( - $(#[$composite_doc:meta])* - $composite_feature:ident = { - $first_inner_feature:ident - $(,$($inner_feature:ident$(,)?)+)? - }$(,)? - )* - } - - { - $( - $(#[$composite_set_doc:meta])* - $composite_set_feature:ident = { - $set_first_inner_feature:ident - $(,$($set_inner_feature:ident$(,)?)+)? - }$(,)? - )* - } - ) => { - /// specific decode settings controlling how an x86 byte sequence is interpreted. - /// - /// this currently exists to specify which extensions are to be accepted or rejected. the two - /// implementations provided by `yaxpeax-x86` are: - /// * [`InstDecoder`], providing configurable enablement or disablement per-extension - /// * [`DecodeEverything`], which allows all extensions supported by `yaxpeax-x86` - /// - /// 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... - pub trait IsaSettings { - $( - $(#[$doc])* - fn $feature(&self) -> bool; - )+ - - $( - $(#[$composite_doc])* - fn $composite_feature(&self) -> bool { - self.$first_inner_feature() - $($(&& self.$inner_feature())+)? - } - )* - - fn revise_instruction(&self, inst: &mut Instruction) -> Result<(), DecodeError> { - revise_instruction(self, inst) - } - } - - impl IsaSettings for DecodeEverything { - $(fn $feature(&self) -> bool { true })+ - - fn revise_instruction(&self, _inst: &mut Instruction) -> Result<(), DecodeError> { - Ok(()) - } - } - - impl IsaSettings for InstDecoder { - $( - fn $feature(&self) -> bool { - let i = $idx as usize; - self.flags[i / 64] & (1 << (i % 64)) != 0 - } - )+ - } - - impl InstDecoder { - $( - $(#[$set_doc])* - pub fn $set_feature(mut self) -> Self { - let i = $idx as usize; - self.flags[i / 64] |= 1 << (i % 64); - self - } - )+ - - $( - $(#[$composite_set_doc])* - pub fn $composite_set_feature(&self) -> Self { - self.$set_first_inner_feature() - $($(.$set_inner_feature())+)? - } - )* - - $( - $(#[$doc])* - pub fn $feature(&self) -> bool { - <Self as IsaSettings>::$feature(self) - } - )+ - - $( - $(#[$composite_doc])* - pub fn $composite_feature(&self) -> bool { - <Self as IsaSettings>::$composite_feature(self) - } - )* - } - } -} -gen_isa_settings!( - _3dnow, with_3dnow = 1; - _3dnowprefetch, with_3dnowprefetch = 2; - abm, with_abm = 3; - adx, with_adx = 4; - aesni, with_aesni = 5; - amd_quirks, with_amd_quirks = 6; - avx, with_avx = 7; - avx2, with_avx2 = 8; - avx512_4fmaps, with_avx512_4fmaps = 10; - avx512_4vnniw, with_avx512_4vnniw = 11; - avx512_bitalg, with_avx512_bitalg = 12; - avx512_bw, with_avx512_bw = 13; - avx512_cd, with_avx512_cd = 14; - avx512_dq, with_avx512_dq = 15; - avx512_er, with_avx512_er = 16; - avx512_f, with_avx512_f = 17; - avx512_fma, with_avx512_fma = 18; - avx512_pf, with_avx512_pf = 19; - avx512_vbmi, with_avx512_vbmi = 20; - avx512_vbmi2, with_avx512_vbmi2 = 21; - avx512_vl, with_avx512_vl = 22; - avx512_vpopcntdq, with_avx512_vpopcntdq = 23; - avx_vnni, with_avx_vnni = 24; - bmi1, with_bmi1 = 25; - #[doc="`bmi2` indicates support for the `BZHI`, `MULX`, `PDEP`, `PEXT`, `RORX`, `SARX`, `SHRX`, "] - #[doc="and `SHLX` instructions. `bmi2` is implemented in all x86_64 chips that implement `bmi`, "] - #[doc="except the amd `piledriver` and `steamroller` microarchitectures."] - bmi2, with_bmi2 = 26; - clflushopt, with_clflushopt = 27; - clwb, with_clwb = 28; - cmov, with_cmov = 29; - cmpxchg16b, with_cmpxchg16b = 30; - cx8, with_cx8 = 31; - f16c, with_f16c = 32; - fma3, with_fma3 = 33; - fma4, with_fma4 = 34; - gfni, with_gfni = 35; - intel_quirks, with_intel_quirks = 36; - invpcid, with_invpcid = 37; - #[doc="`lahfsahf` is only unset for early revisions of 64-bit amd and intel chips. unfortunately"] - #[doc="the clearest documentation on when these instructions were reintroduced into 64-bit"] - #[doc="architectures seems to be"] - #[doc="[wikipedia](https://en.wikipedia.org/wiki/X86-64#Older_implementations):"] - #[doc="```text"] - #[doc="Early AMD64 and Intel 64 CPUs lacked LAHF and SAHF instructions in 64-bit mode. AMD"] - #[doc="introduced these instructions (also in 64-bit mode) with their Athlon 64, Opteron and"] - #[doc="Turion 64 revision D processors in March 2005[48][49][50] while Intel introduced the"] - #[doc="instructions with the Pentium 4 G1 stepping in December 2005. The 64-bit version of Windows"] - #[doc="8.1 requires this feature.[47]"] - #[doc="```"] - #[doc=""] - #[doc="this puts reintroduction of these instructions somewhere in the middle of prescott and k8"] - #[doc="lifecycles, for intel and amd respectively. because there is no specific uarch where these"] - #[doc="features become enabled, prescott and k8 default to not supporting these instructions,"] - #[doc="where later uarches support these instructions."] - lahfsahf, with_lahfsahf = 38; - lzcnt, with_lzcnt = 39; - monitor, with_monitor = 40; - movbe, with_movbe = 41; - mpx, with_mpx = 42; - pclmulqdq, with_pclmulqdq = 43; - pcommit, with_pcommit = 44; - popcnt, with_popcnt = 45; - prefetchw, with_prefetchw = 46; - prefetchwt1, with_prefetchwt1 = 47; - rdrand, with_rdrand = 48; - rdseed, with_rdseed = 49; - rdtscp, with_rdtscp = 50; - sgx, with_sgx = 51; - sha, with_sha = 52; - skinit, with_skinit = 53; - sse3, with_sse3 = 54; - sse4_1, with_sse4_1 = 55; - sse4_2, with_sse4_2 = 56; - sse4a, with_sse4a = 57; - ssse3, with_ssse3 = 58; - svm, with_svm = 59; - syscall, with_syscall = 60; - tbm, with_tbm = 61; - tsx, with_tsx = 62; - vaes, with_vaes = 63; - vmx, with_vmx = 64; - xop, with_xop = 65; - xsave, with_xsave = 66; - - { - sse4 = { - sse4_1, - sse4_2, - } - - #[doc = "returns `true` if this `InstDecoder` has **all** `avx512` features enabled."] - avx512 = { - avx512_4fmaps, - avx512_4vnniw, - avx512_bitalg, - avx512_bw, - avx512_cd, - avx512_dq, - avx512_er, - avx512_f, - avx512_fma, - avx512_pf, - avx512_vbmi, - avx512_vbmi2, - avx512_vl, - avx512_vpopcntdq, - }, - } - - { - with_sse4 = { - with_sse4_1, - with_sse4_2, - } - - with_avx512 = { - with_avx512_4fmaps, - with_avx512_4vnniw, - with_avx512_bitalg, - with_avx512_bw, - with_avx512_cd, - with_avx512_dq, - with_avx512_er, - with_avx512_f, - with_avx512_fma, - with_avx512_pf, - with_avx512_vbmi, - with_avx512_vbmi2, - with_avx512_vl, - with_avx512_vpopcntdq, - } - } +crate::isa_settings::gen_arch_isa_settings!( + Instruction, DecodeError, InstDecoder, DecodeEverything, + revise_instruction ); /// optionally reject or reinterpret instruction according to settings for this decode diff --git a/src/real_mode/isa_settings.rs b/src/real_mode/isa_settings.rs index 55d18a7..77ee7e2 100644 --- a/src/real_mode/isa_settings.rs +++ b/src/real_mode/isa_settings.rs @@ -1,251 +1,8 @@ use super::{BMI1, BMI2, DecodeError, DecodeEverything, InstDecoder, Instruction, Opcode}; -macro_rules! gen_isa_settings { - ( - $( - $(#[$doc:meta])* - $feature:ident, - $(#[$set_doc:item])* - $set_feature:ident = $idx:expr; - )+ - - { - $( - $(#[$composite_doc:meta])* - $composite_feature:ident = { - $first_inner_feature:ident - $(,$($inner_feature:ident$(,)?)+)? - }$(,)? - )* - } - - { - $( - $(#[$composite_set_doc:meta])* - $composite_set_feature:ident = { - $set_first_inner_feature:ident - $(,$($set_inner_feature:ident$(,)?)+)? - }$(,)? - )* - } - ) => { - /// specific decode settings controlling how an x86 byte sequence is interpreted. - /// - /// this currently exists to specify which extensions are to be accepted or rejected. the two - /// implementations provided by `yaxpeax-x86` are: - /// * [`InstDecoder`], providing configurable enablement or disablement per-extension - /// * [`DecodeEverything`], which allows all extensions supported by `yaxpeax-x86` - /// - /// 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... - pub trait IsaSettings { - $( - $(#[$doc])* - fn $feature(&self) -> bool; - )+ - - $( - $(#[$composite_doc])* - fn $composite_feature(&self) -> bool { - self.$first_inner_feature() - $($(&& self.$inner_feature())+)? - } - )* - - fn revise_instruction(&self, inst: &mut Instruction) -> Result<(), DecodeError> { - revise_instruction(self, inst) - } - } - - impl IsaSettings for DecodeEverything { - $(fn $feature(&self) -> bool { true })+ - - fn revise_instruction(&self, _inst: &mut Instruction) -> Result<(), DecodeError> { - Ok(()) - } - } - - impl IsaSettings for InstDecoder { - $( - fn $feature(&self) -> bool { - let i = $idx as usize; - self.flags[i / 64] & (1 << (i % 64)) != 0 - } - )+ - } - - impl InstDecoder { - $( - $(#[$set_doc])* - pub fn $set_feature(mut self) -> Self { - let i = $idx as usize; - self.flags[i / 64] |= 1 << (i % 64); - self - } - )+ - - $( - $(#[$composite_set_doc])* - pub fn $composite_set_feature(&self) -> Self { - self.$set_first_inner_feature() - $($(.$set_inner_feature())+)? - } - )* - - $( - $(#[$doc])* - pub fn $feature(&self) -> bool { - <Self as IsaSettings>::$feature(self) - } - )+ - - $( - $(#[$composite_doc])* - pub fn $composite_feature(&self) -> bool { - <Self as IsaSettings>::$composite_feature(self) - } - )* - } - } -} -gen_isa_settings!( - _3dnow, with_3dnow = 1; - _3dnowprefetch, with_3dnowprefetch = 2; - abm, with_abm = 3; - adx, with_adx = 4; - aesni, with_aesni = 5; - amd_quirks, with_amd_quirks = 6; - avx, with_avx = 7; - avx2, with_avx2 = 8; - avx512_4fmaps, with_avx512_4fmaps = 10; - avx512_4vnniw, with_avx512_4vnniw = 11; - avx512_bitalg, with_avx512_bitalg = 12; - avx512_bw, with_avx512_bw = 13; - avx512_cd, with_avx512_cd = 14; - avx512_dq, with_avx512_dq = 15; - avx512_er, with_avx512_er = 16; - avx512_f, with_avx512_f = 17; - avx512_fma, with_avx512_fma = 18; - avx512_pf, with_avx512_pf = 19; - avx512_vbmi, with_avx512_vbmi = 20; - avx512_vbmi2, with_avx512_vbmi2 = 21; - avx512_vl, with_avx512_vl = 22; - avx512_vpopcntdq, with_avx512_vpopcntdq = 23; - avx_vnni, with_avx_vnni = 24; - bmi1, with_bmi1 = 25; - #[doc="`bmi2` indicates support for the `BZHI`, `MULX`, `PDEP`, `PEXT`, `RORX`, `SARX`, `SHRX`, "] - #[doc="and `SHLX` instructions. `bmi2` is implemented in all x86_64 chips that implement `bmi`, "] - #[doc="except the amd `piledriver` and `steamroller` microarchitectures."] - bmi2, with_bmi2 = 26; - clflushopt, with_clflushopt = 27; - clwb, with_clwb = 28; - cmov, with_cmov = 29; - cmpxchg16b, with_cmpxchg16b = 30; - cx8, with_cx8 = 31; - f16c, with_f16c = 32; - fma3, with_fma3 = 33; - fma4, with_fma4 = 34; - gfni, with_gfni = 35; - intel_quirks, with_intel_quirks = 36; - invpcid, with_invpcid = 37; - #[doc="`lahfsahf` is only unset for early revisions of 64-bit amd and intel chips. unfortunately"] - #[doc="the clearest documentation on when these instructions were reintroduced into 64-bit"] - #[doc="architectures seems to be"] - #[doc="[wikipedia](https://en.wikipedia.org/wiki/X86-64#Older_implementations):"] - #[doc="```text"] - #[doc="Early AMD64 and Intel 64 CPUs lacked LAHF and SAHF instructions in 64-bit mode. AMD"] - #[doc="introduced these instructions (also in 64-bit mode) with their Athlon 64, Opteron and"] - #[doc="Turion 64 revision D processors in March 2005[48][49][50] while Intel introduced the"] - #[doc="instructions with the Pentium 4 G1 stepping in December 2005. The 64-bit version of Windows"] - #[doc="8.1 requires this feature.[47]"] - #[doc="```"] - #[doc=""] - #[doc="this puts reintroduction of these instructions somewhere in the middle of prescott and k8"] - #[doc="lifecycles, for intel and amd respectively. because there is no specific uarch where these"] - #[doc="features become enabled, prescott and k8 default to not supporting these instructions,"] - #[doc="where later uarches support these instructions."] - lahfsahf, with_lahfsahf = 38; - lzcnt, with_lzcnt = 39; - monitor, with_monitor = 40; - movbe, with_movbe = 41; - mpx, with_mpx = 42; - pclmulqdq, with_pclmulqdq = 43; - pcommit, with_pcommit = 44; - popcnt, with_popcnt = 45; - prefetchw, with_prefetchw = 46; - prefetchwt1, with_prefetchwt1 = 47; - rdrand, with_rdrand = 48; - rdseed, with_rdseed = 49; - rdtscp, with_rdtscp = 50; - sgx, with_sgx = 51; - sha, with_sha = 52; - skinit, with_skinit = 53; - sse3, with_sse3 = 54; - sse4_1, with_sse4_1 = 55; - sse4_2, with_sse4_2 = 56; - sse4a, with_sse4a = 57; - ssse3, with_ssse3 = 58; - svm, with_svm = 59; - syscall, with_syscall = 60; - tbm, with_tbm = 61; - tsx, with_tsx = 62; - vaes, with_vaes = 63; - vmx, with_vmx = 64; - xop, with_xop = 65; - xsave, with_xsave = 66; - - { - sse4 = { - sse4_1, - sse4_2, - } - - #[doc = "returns `true` if this `InstDecoder` has **all** `avx512` features enabled."] - avx512 = { - avx512_4fmaps, - avx512_4vnniw, - avx512_bitalg, - avx512_bw, - avx512_cd, - avx512_dq, - avx512_er, - avx512_f, - avx512_fma, - avx512_pf, - avx512_vbmi, - avx512_vbmi2, - avx512_vl, - avx512_vpopcntdq, - }, - } - - { - with_sse4 = { - with_sse4_1, - with_sse4_2, - } - - with_avx512 = { - with_avx512_4fmaps, - with_avx512_4vnniw, - with_avx512_bitalg, - with_avx512_bw, - with_avx512_cd, - with_avx512_dq, - with_avx512_er, - with_avx512_f, - with_avx512_fma, - with_avx512_pf, - with_avx512_vbmi, - with_avx512_vbmi2, - with_avx512_vl, - with_avx512_vpopcntdq, - } - } +crate::isa_settings::gen_arch_isa_settings!( + Instruction, DecodeError, InstDecoder, DecodeEverything, + revise_instruction ); /// optionally reject or reinterpret instruction according to settings for this decode |
