89 auto query=[](
char const * key,
bool & value)
noexcept {
90 int data=0; std::size_t size=
sizeof(data);
91 if(sysctlbyname(key,&data,&size,
nullptr,0)!=0)
return errno==ENOENT ? 0 : -1;
92 if(size!=
sizeof(data))
return -1;
93 value=data!=0;
return 1;
95 bool baseline=
false, half=
false;
98 auto status=query(
"hw.optional.arm.FEAT_FP16",half);
99 if(status==0) status=query(
"hw.optional.neon_fp16",half);
104 auto extra=[&](
arm_feature f,
char const * first,
char const * second=
nullptr) {
106 auto observed=query(first,a)==1;
107 if(second) observed=(query(second,b)==1)&&observed;
109 if(observed && a && b) result.
raw.extra_features.
set(f,
true);
111 extra(arm_feature::aes,
"hw.optional.arm.FEAT_AES");
112 extra(arm_feature::pmull,
"hw.optional.arm.FEAT_PMULL");
113 extra(arm_feature::sha1,
"hw.optional.arm.FEAT_SHA1");
114 extra(arm_feature::sha2,
"hw.optional.arm.FEAT_SHA256");
115 extra(arm_feature::sha3,
"hw.optional.arm.FEAT_SHA3");
116 extra(arm_feature::sha512,
"hw.optional.arm.FEAT_SHA512");
117 extra(arm_feature::sm3,
"hw.optional.arm.FEAT_SM3");
118 extra(arm_feature::sm4,
"hw.optional.arm.FEAT_SM4");
119 extra(arm_feature::crc,
"hw.optional.armv8_crc32");
120 extra(arm_feature::lse,
"hw.optional.arm.FEAT_LSE");
121 extra(arm_feature::rdm,
"hw.optional.arm.FEAT_RDM");
122 extra(arm_feature::fp16fml,
"hw.optional.arm.FEAT_FHM");
123 extra(arm_feature::dotprod,
"hw.optional.arm.FEAT_DotProd");
124 extra(arm_feature::complxnum,
"hw.optional.arm.FEAT_FCMA");
125 extra(arm_feature::jsconv,
"hw.optional.arm.FEAT_JSCVT");
126 extra(arm_feature::rcpc,
"hw.optional.arm.FEAT_LRCPC");
127 extra(arm_feature::pauth,
"hw.optional.arm.FEAT_PAuth");
128 extra(arm_feature::i8mm,
"hw.optional.arm.FEAT_I8MM");
129#elif defined(__linux__)
131 auto hwcap=getauxval(AT_HWCAP);
132 if(hwcap==0 && errno!=0)
return result;
134 result.
raw.
fp=(hwcap&HWCAP_FP)!=0;
135 result.
raw.
asimd=(hwcap&HWCAP_ASIMD)!=0;
142 extra(arm_feature::aes,HWCAP_AES);
143 extra(arm_feature::pmull,HWCAP_PMULL);
144 extra(arm_feature::sha1,HWCAP_SHA1);
145 extra(arm_feature::sha2,HWCAP_SHA2);
146 extra(arm_feature::crc,HWCAP_CRC32);
147 extra(arm_feature::lse,HWCAP_ATOMICS);
149 extra(arm_feature::rdm,HWCAP_ASIMDRDM);
152 extra(arm_feature::fp16fml,HWCAP_ASIMDFHM);
155 extra(arm_feature::dotprod,HWCAP_ASIMDDP);
158 extra(arm_feature::complxnum,HWCAP_FCMA);
161 extra(arm_feature::jsconv,HWCAP_JSCVT);
164 extra(arm_feature::rcpc,HWCAP_LRCPC);
167 extra(arm_feature::sha3,HWCAP_SHA3);
170 extra(arm_feature::sha512,HWCAP_SHA512);
173 extra(arm_feature::sm3,HWCAP_SM3);
176 extra(arm_feature::sm4,HWCAP_SM4);
178#if defined(HWCAP_PACA) && defined(HWCAP_PACG)
179 extra(arm_feature::pauth,HWCAP_PACA|HWCAP_PACG);
182 auto hwcap2=getauxval(AT_HWCAP2);
183 if(hwcap2!=0 || errno==0) {
186 result.
raw.extra_features.
set(arm_feature::i8mm,(hwcap2&HWCAP2_I8MM)!=0);
190 result.
raw.
bf16=(hwcap2&HWCAP2_BF16)!=0;
194 result.
raw.
ebf16=(hwcap2&HWCAP2_EBF16)!=0;
199 result.
raw.
fp=IsProcessorFeaturePresent(PF_ARM_V8_INSTRUCTIONS_AVAILABLE)!=0;
200 result.
raw.
asimd=IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE)!=0;
202 constexpr DWORD fp16_feature=67;
204 constexpr DWORD bf16_feature=68;
205 constexpr DWORD ebf16_feature=69;
207 result.
raw.
bf16=IsProcessorFeaturePresent(bf16_feature)!=0;
208 result.
raw.
ebf16=IsProcessorFeaturePresent(ebf16_feature)!=0;
211 if(IsProcessorFeaturePresent(selector)) result.
raw.extra_features.
set(f,
true);
215 constexpr arm_feature crypto[]{arm_feature::aes,arm_feature::pmull,arm_feature::sha1,arm_feature::sha2};
216 if(IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE))
217 for(
auto feature:crypto) {
219 result.
raw.extra_features.
set(feature,
true);
221 extra(arm_feature::crc,PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
222 extra(arm_feature::lse,PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE);
223 extra(arm_feature::dotprod,43);
224 extra(arm_feature::jsconv,44);
225 extra(arm_feature::rcpc,45);
226 extra(arm_feature::sha3,64);
227 extra(arm_feature::sha512,65);
228 extra(arm_feature::i8mm,66);
232 auto features=detail::decode_arm_features(result.
raw);
233 result.
present=features.present;