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