Skip to main content

std_detect\detect\os\windows/
aarch64.rs

1//! Run-time feature detection for Aarch64 on Windows.
2
3use crate::detect::{Feature, cache};
4
5/// Try to read the features using IsProcessorFeaturePresent.
6pub(crate) fn detect_features() -> cache::Initializer {
7    type DWORD = u32;
8    type BOOL = i32;
9
10    const FALSE: BOOL = 0;
11    // The following Microsoft documents isn't updated for aarch64.
12    // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent
13    // These are defined in winnt.h of Windows SDK
14    const PF_ARM_VFP_32_REGISTERS_AVAILABLE: u32 = 18;
15    const PF_ARM_NEON_INSTRUCTIONS_AVAILABLE: u32 = 19;
16    const PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE: u32 = 30;
17    const PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE: u32 = 31;
18    const PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE: u32 = 34;
19    const PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE: u32 = 43;
20    const PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE: u32 = 44;
21    const PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE: u32 = 45;
22    const PF_ARM_SVE_INSTRUCTIONS_AVAILABLE: u32 = 46;
23    const PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE: u32 = 47;
24    const PF_ARM_SVE2_1_INSTRUCTIONS_AVAILABLE: u32 = 48;
25    const PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE: u32 = 49;
26    const PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE: u32 = 50;
27    const PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE: u32 = 51;
28    // const PF_ARM_SVE_BF16_INSTRUCTIONS_AVAILABLE: u32 = 52;
29    // const PF_ARM_SVE_EBF16_INSTRUCTIONS_AVAILABLE: u32 = 53;
30    const PF_ARM_SVE_B16B16_INSTRUCTIONS_AVAILABLE: u32 = 54;
31    const PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE: u32 = 55;
32    const PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE: u32 = 56;
33    // const PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE: u32 = 57;
34    // const PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE: u32 = 58;
35    // const PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE: u32 = 59;
36
37    unsafe extern "system" {
38        fn IsProcessorFeaturePresent(ProcessorFeature: DWORD) -> BOOL;
39    }
40
41    let mut value = cache::Initializer::default();
42    {
43        let mut enable_feature = |f, enable| {
44            if enable {
45                value.set(f as u32);
46            }
47        };
48
49        // Some features may be supported on current CPU,
50        // but no way to detect it by OS API.
51        // Also, we require unsafe block for the extern "system" calls.
52        unsafe {
53            enable_feature(
54                Feature::fp,
55                IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE) != FALSE,
56            );
57            enable_feature(
58                Feature::asimd,
59                IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) != FALSE,
60            );
61            enable_feature(
62                Feature::crc,
63                IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != FALSE,
64            );
65            enable_feature(
66                Feature::lse,
67                IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE) != FALSE,
68            );
69            enable_feature(
70                Feature::dotprod,
71                IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) != FALSE,
72            );
73            enable_feature(
74                Feature::jsconv,
75                IsProcessorFeaturePresent(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE) != FALSE,
76            );
77            enable_feature(
78                Feature::rcpc,
79                IsProcessorFeaturePresent(PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE) != FALSE,
80            );
81            enable_feature(
82                Feature::sve,
83                IsProcessorFeaturePresent(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE) != FALSE,
84            );
85            enable_feature(
86                Feature::sve2,
87                IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE) != FALSE,
88            );
89            enable_feature(
90                Feature::sve2p1,
91                IsProcessorFeaturePresent(PF_ARM_SVE2_1_INSTRUCTIONS_AVAILABLE) != FALSE,
92            );
93            enable_feature(
94                Feature::sve2_aes,
95                IsProcessorFeaturePresent(PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE) != FALSE
96                    && IsProcessorFeaturePresent(PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE)
97                        != FALSE,
98            );
99            enable_feature(
100                Feature::sve2_bitperm,
101                IsProcessorFeaturePresent(PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE) != FALSE,
102            );
103            enable_feature(
104                Feature::sve_b16b16,
105                IsProcessorFeaturePresent(PF_ARM_SVE_B16B16_INSTRUCTIONS_AVAILABLE) != FALSE,
106            );
107            enable_feature(
108                Feature::sve2_sha3,
109                IsProcessorFeaturePresent(PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE) != FALSE,
110            );
111            enable_feature(
112                Feature::sve2_sm4,
113                IsProcessorFeaturePresent(PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE) != FALSE,
114            );
115            // PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE means aes, sha1, sha2 and
116            // pmull support
117            let crypto =
118                IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != FALSE;
119            enable_feature(Feature::aes, crypto);
120            enable_feature(Feature::pmull, crypto);
121            enable_feature(Feature::sha2, crypto);
122        }
123    }
124    value
125}