8#include <botan/cpuid.h>
9#include <botan/types.h>
10#include <botan/exceptn.h>
11#include <botan/parsing.h>
18#if defined(BOTAN_TARGET_SUPPORTS_SSE2)
19 return CPUID::has_sse2();
20#elif defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
21 return CPUID::has_altivec();
22#elif defined(BOTAN_TARGET_SUPPORTS_NEON)
23 return CPUID::has_neon();
32 std::vector<std::string>
flags;
34#define CPUID_PRINT(flag) do { if(has_##flag()) { flags.push_back(#flag); } } while(0)
36#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
61#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
67#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
95 state() = CPUID_Data();
98CPUID::CPUID_Data::CPUID_Data()
100 m_cache_line_size = 0;
101 m_processor_features = 0;
103#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) || \
104 defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) || \
105 defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
107 m_processor_features = detect_cpu_features(&m_cache_line_size);
113 if(m_cache_line_size == 0)
114 m_cache_line_size = BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE;
116 m_endian_status = runtime_check_endian();
120CPUID::Endian_Status CPUID::CPUID_Data::runtime_check_endian()
123 const uint32_t endian32 = 0x01234567;
124 const uint8_t* e8 =
reinterpret_cast<const uint8_t*
>(&endian32);
126 CPUID::Endian_Status endian = CPUID::Endian_Status::Unknown;
128 if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67)
130 endian = CPUID::Endian_Status::Big;
132 else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01)
134 endian = CPUID::Endian_Status::Little;
138 throw Internal_Error(
"Unexpected endian at runtime, neither big nor little");
142#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
143 BOTAN_ASSERT(endian == CPUID::Endian_Status::Little,
"Build and runtime endian match");
144#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
145 BOTAN_ASSERT(endian == CPUID::Endian_Status::Big,
"Build and runtime endian match");
151std::vector<Botan::CPUID::CPUID_bits>
154#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
155 if(tok ==
"sse2" || tok ==
"simd")
156 return {Botan::CPUID::CPUID_SSE2_BIT};
158 return {Botan::CPUID::CPUID_SSSE3_BIT};
160 return {Botan::CPUID::CPUID_SSE41_BIT};
162 return {Botan::CPUID::CPUID_SSE42_BIT};
164 if(tok ==
"aesni" || tok ==
"aes_ni")
165 return {Botan::CPUID::CPUID_AESNI_BIT};
167 return {Botan::CPUID::CPUID_CLMUL_BIT};
169 return {Botan::CPUID::CPUID_AVX2_BIT};
171 return {Botan::CPUID::CPUID_AVX512F_BIT};
172 if(tok ==
"avx512_icelake")
173 return {Botan::CPUID::CPUID_AVX512_ICL_BIT};
175 if(tok ==
"sha" || tok==
"intel_sha")
176 return {Botan::CPUID::CPUID_SHA_BIT};
178 return {Botan::CPUID::CPUID_RDTSC_BIT};
180 return {Botan::CPUID::CPUID_BMI1_BIT};
182 return {Botan::CPUID::CPUID_BMI2_BIT};
184 return {Botan::CPUID::CPUID_ADX_BIT};
186 return {Botan::CPUID::CPUID_RDRAND_BIT};
188 return {Botan::CPUID::CPUID_RDSEED_BIT};
189 if(tok ==
"avx512_aes")
190 return {Botan::CPUID::CPUID_AVX512_AES_BIT};
191 if(tok ==
"avx512_clmul")
192 return {Botan::CPUID::CPUID_AVX512_CLMUL_BIT};
194#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
195 if(tok ==
"altivec" || tok ==
"simd")
196 return {Botan::CPUID::CPUID_ALTIVEC_BIT};
197 if(tok ==
"power_crypto")
198 return {Botan::CPUID::CPUID_POWER_CRYPTO_BIT};
199 if(tok ==
"darn_rng")
200 return {Botan::CPUID::CPUID_DARN_BIT};
202#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
203 if(tok ==
"neon" || tok ==
"simd")
204 return {Botan::CPUID::CPUID_ARM_NEON_BIT};
206 return {Botan::CPUID::CPUID_ARM_SVE_BIT};
207 if(tok ==
"armv8sha1" || tok ==
"arm_sha1")
208 return {Botan::CPUID::CPUID_ARM_SHA1_BIT};
209 if(tok ==
"armv8sha2" || tok ==
"arm_sha2")
210 return {Botan::CPUID::CPUID_ARM_SHA2_BIT};
211 if(tok ==
"armv8aes" || tok ==
"arm_aes")
212 return {Botan::CPUID::CPUID_ARM_AES_BIT};
213 if(tok ==
"armv8pmull" || tok ==
"arm_pmull")
214 return {Botan::CPUID::CPUID_ARM_PMULL_BIT};
215 if(tok ==
"armv8sha3" || tok ==
"arm_sha3")
216 return {Botan::CPUID::CPUID_ARM_SHA3_BIT};
217 if(tok ==
"armv8sha2_512" || tok ==
"arm_sha2_512")
218 return {Botan::CPUID::CPUID_ARM_SHA2_512_BIT};
219 if(tok ==
"armv8sm3" || tok ==
"arm_sm3")
220 return {Botan::CPUID::CPUID_ARM_SM3_BIT};
221 if(tok ==
"armv8sm4" || tok ==
"arm_sm4")
222 return {Botan::CPUID::CPUID_ARM_SM4_BIT};
#define BOTAN_UNUSED(...)
#define BOTAN_ASSERT(expr, assertion_made)
static std::vector< CPUID::CPUID_bits > bit_from_string(const std::string &tok)
static std::string to_string()
static void print(std::ostream &o)
static bool has_simd_32()
#define CPUID_PRINT(flag)
std::string string_join(const std::vector< std::string > &strs, char delim)