1 // Copyright 2016-2021 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 #![cfg_attr(
16     not(any(target_arch = "x86", target_arch = "x86_64")),
17     allow(dead_code)
18 )]
19 
20 pub(crate) struct Feature {
21     word: usize,
22     mask: u32,
23 }
24 
25 impl Feature {
26     #[allow(clippy::needless_return)]
27     #[inline(always)]
available(&self, _: super::Features) -> bool28     pub fn available(&self, _: super::Features) -> bool {
29         #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
30         {
31             prefixed_extern! {
32                 static mut OPENSSL_ia32cap_P: [u32; 4];
33             }
34             return self.mask == self.mask & unsafe { OPENSSL_ia32cap_P[self.word] };
35         }
36 
37         #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
38         {
39             return false;
40         }
41     }
42 }
43 
44 pub(crate) const ADX: Feature = Feature {
45     word: 2,
46     mask: 1 << 19,
47 };
48 
49 pub(crate) const BMI1: Feature = Feature {
50     word: 2,
51     mask: 1 << 3,
52 };
53 
54 pub(crate) const BMI2: Feature = Feature {
55     word: 2,
56     mask: 1 << 8,
57 };
58 
59 pub(crate) const FXSR: Feature = Feature {
60     word: 0,
61     mask: 1 << 24,
62 };
63 
64 pub(crate) const PCLMULQDQ: Feature = Feature {
65     word: 1,
66     mask: 1 << 1,
67 };
68 
69 pub(crate) const SSSE3: Feature = Feature {
70     word: 1,
71     mask: 1 << 9,
72 };
73 
74 pub(crate) const SSE41: Feature = Feature {
75     word: 1,
76     mask: 1 << 19,
77 };
78 
79 #[cfg(target_arch = "x86_64")]
80 pub(crate) const MOVBE: Feature = Feature {
81     word: 1,
82     mask: 1 << 22,
83 };
84 
85 pub(crate) const AES: Feature = Feature {
86     word: 1,
87     mask: 1 << 25,
88 };
89 
90 #[cfg(target_arch = "x86_64")]
91 pub(crate) const AVX: Feature = Feature {
92     word: 1,
93     mask: 1 << 28,
94 };
95 
96 #[cfg(all(target_arch = "x86_64", test))]
97 mod x86_64_tests {
98     use super::*;
99 
100     #[test]
test_avx_movbe_mask()101     fn test_avx_movbe_mask() {
102         // This is the OpenSSL style of testing these bits.
103         assert_eq!((AVX.mask | MOVBE.mask) >> 22, 0x41);
104     }
105 }
106