Crypto++  8.0
Free C++ class library of cryptographic schemes
cpu.cpp
1 // cpu.cpp - originally written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "config.h"
5 
6 #ifndef EXCEPTION_EXECUTE_HANDLER
7 # define EXCEPTION_EXECUTE_HANDLER 1
8 #endif
9 
10 #ifndef CRYPTOPP_IMPORTS
11 
12 #include "cpu.h"
13 #include "misc.h"
14 #include "stdcpp.h"
15 
16 #ifdef _AIX
17 # include <sys/systemcfg.h>
18 #endif
19 
20 #ifdef __linux__
21 # include <unistd.h>
22 #endif
23 
24 // Capability queries, requires Glibc 2.16, http://lwn.net/Articles/519085/
25 // CRYPTOPP_GLIBC_VERSION not used because config.h is missing <feature.h>
26 #if (((__GLIBC__ * 100) + __GLIBC_MINOR__) >= 216)
27 # define CRYPTOPP_GETAUXV_AVAILABLE 1
28 #endif
29 
30 #if CRYPTOPP_GETAUXV_AVAILABLE
31 # include <sys/auxv.h>
32 #else
33 #ifndef AT_HWCAP
34 # define AT_HWCAP 16
35 #endif
36 #ifndef AT_HWCAP2
37 # define AT_HWCAP2 26
38 #endif
39 unsigned long int getauxval(unsigned long int) { return 0; }
40 #endif
41 
42 #if defined(__APPLE__)
43 # include <sys/utsname.h>
44 #endif
45 
46 // The cpu-features header and source file are located in
47 // "$ANDROID_NDK_ROOT/sources/android/cpufeatures".
48 // setenv-android.sh will copy the header and source file
49 // into PWD and the makefile will build it in place.
50 #if defined(__ANDROID__)
51 # include "cpu-features.h"
52 #endif
53 
54 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
55 # include <signal.h>
56 # include <setjmp.h>
57 #endif
58 
59 // Visual Studio 2008 and below is missing _xgetbv. See x64dll.asm for the body.
60 #if defined(_MSC_VER) && _MSC_VER <= 1500 && defined(_M_X64)
61 extern "C" unsigned long long __fastcall ExtendedControlRegister(unsigned int);
62 #endif
63 
64 ANONYMOUS_NAMESPACE_BEGIN
65 
66 #if defined(__APPLE__)
67 enum {PowerMac=1, Mac, iPhone, iPod, iPad, AppleTV, AppleWatch};
68 void GetAppleMachineInfo(unsigned int& device, unsigned int& version)
69 {
70  device = version = 0;
71 
72  struct utsname systemInfo;
73  systemInfo.machine[0] = '\0';
74  uname(&systemInfo);
75 
76  std::string machine(systemInfo.machine);
77  if (machine.find("PowerMac") != std::string::npos ||
78  machine.find("Power Macintosh") != std::string::npos)
79  device = PowerMac;
80  else if (machine.find("Mac") != std::string::npos ||
81  machine.find("Macintosh") != std::string::npos)
82  device = Mac;
83  else if (machine.find("iPhone") != std::string::npos)
84  device = iPhone;
85  else if (machine.find("iPod") != std::string::npos)
86  device = iPod;
87  else if (machine.find("iPad") != std::string::npos)
88  device = iPad;
89  else if (machine.find("AppleTV") != std::string::npos)
90  device = AppleTV;
91  else if (machine.find("AppleWatch") != std::string::npos)
92  device = AppleWatch;
93 
94  std::string::size_type pos = machine.find_first_of("0123456789");
95  if (pos != std::string::npos)
96  version = std::atoi(machine.substr(pos).c_str());
97 }
98 
99 // http://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
100 bool IsAppleMachineARMv8(unsigned int device, unsigned int version)
101 {
102  if ((device == iPhone && version >= 6) ||
103  (device == iPad && version >= 4))
104  {
105  return true;
106  }
107  return false;
108 }
109 
110 bool IsAppleMachineARMv84(unsigned int device, unsigned int version)
111 {
112  return false;
113 }
114 #endif // __APPLE__
115 
116 ANONYMOUS_NAMESPACE_END
117 
118 NAMESPACE_BEGIN(CryptoPP)
119 
120 #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
121 extern "C" {
122  typedef void (*SigHandler)(int);
123 }
124 
125 extern "C"
126 {
127  static jmp_buf s_jmpNoCPUID;
128  static void SigIllHandlerCPUID(int unused)
129  {
130  CRYPTOPP_UNUSED(unused);
131  longjmp(s_jmpNoCPUID, 1);
132  }
133 }
134 #endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
135 
136 // *************************** IA-32 CPUs ***************************
137 
138 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
139 
140 extern bool CPU_ProbeSSE2();
141 
142 #if _MSC_VER >= 1600
143 
144 inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
145 {
146  __cpuidex((int *)output, func, subfunc);
147  return true;
148 }
149 
150 #elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
151 
152 inline bool CpuId(word32 func, word32 subfunc, word32 output[4])
153 {
154  if (subfunc != 0)
155  return false;
156 
157  __cpuid((int *)output, func);
158  return true;
159 }
160 
161 #else
162 
163 // Borland/Embarcadero and Issue 498
164 // cpu.cpp (131): E2211 Inline assembly not allowed in inline and template functions
165 bool CpuId(word32 func, word32 subfunc, word32 output[4])
166 {
167 #if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY) || defined(__BORLANDC__)
168  __try
169  {
170  // Borland/Embarcadero and Issue 500
171  // Local variables for cpuid output
172  word32 a, b, c, d;
173  __asm
174  {
175  mov eax, func
176  mov ecx, subfunc
177  cpuid
178  mov [a], eax
179  mov [b], ebx
180  mov [c], ecx
181  mov [d], edx
182  }
183  output[0] = a;
184  output[1] = b;
185  output[2] = c;
186  output[3] = d;
187  }
188  // GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION
189  __except (EXCEPTION_EXECUTE_HANDLER)
190  {
191  return false;
192  }
193 
194  // func = 0 returns the highest basic function understood in EAX. If the CPU does
195  // not return non-0, then it is mostly useless. The code below converts basic
196  // function value to a true/false return value.
197  if(func == 0)
198  return output[0] != 0;
199 
200  return true;
201 #else
202  // longjmp and clobber warnings. Volatile is required.
203  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
204  volatile bool result = true;
205 
206  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
207  if (oldHandler == SIG_ERR)
208  return false;
209 
210 # ifndef __MINGW32__
211  volatile sigset_t oldMask;
212  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask) != 0)
213  return false;
214 # endif
215 
216  if (setjmp(s_jmpNoCPUID))
217  result = false;
218  else
219  {
220  asm volatile
221  (
222  // save ebx in case -fPIC is being used
223  // TODO: this might need an early clobber on EDI.
224 # if CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
225  "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
226 # else
227  "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
228 # endif
229  : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
230  : "a" (func), "c" (subfunc)
231  : "cc"
232  );
233  }
234 
235 # ifndef __MINGW32__
236  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
237 # endif
238 
239  signal(SIGILL, oldHandler);
240  return result;
241 #endif
242 }
243 
244 #endif
245 
246 bool CRYPTOPP_SECTION_INIT g_x86DetectionDone = false;
247 bool CRYPTOPP_SECTION_INIT g_hasSSE2 = false;
248 bool CRYPTOPP_SECTION_INIT g_hasSSSE3 = false;
249 bool CRYPTOPP_SECTION_INIT g_hasSSE41 = false;
250 bool CRYPTOPP_SECTION_INIT g_hasSSE42 = false;
251 bool CRYPTOPP_SECTION_INIT g_hasAVX = false;
252 bool CRYPTOPP_SECTION_INIT g_hasAVX2 = false;
253 bool CRYPTOPP_SECTION_INIT g_hasAESNI = false;
254 bool CRYPTOPP_SECTION_INIT g_hasCLMUL = false;
255 bool CRYPTOPP_SECTION_INIT g_hasADX = false;
256 bool CRYPTOPP_SECTION_INIT g_hasSHA = false;
257 bool CRYPTOPP_SECTION_INIT g_hasRDRAND = false;
258 bool CRYPTOPP_SECTION_INIT g_hasRDSEED = false;
259 bool CRYPTOPP_SECTION_INIT g_isP4 = false;
260 bool CRYPTOPP_SECTION_INIT g_hasPadlockRNG = false;
261 bool CRYPTOPP_SECTION_INIT g_hasPadlockACE = false;
262 bool CRYPTOPP_SECTION_INIT g_hasPadlockACE2 = false;
263 bool CRYPTOPP_SECTION_INIT g_hasPadlockPHE = false;
264 bool CRYPTOPP_SECTION_INIT g_hasPadlockPMM = false;
265 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
266 
267 static inline bool IsIntel(const word32 output[4])
268 {
269  // This is the "GenuineIntel" string
270  return (output[1] /*EBX*/ == 0x756e6547) &&
271  (output[2] /*ECX*/ == 0x6c65746e) &&
272  (output[3] /*EDX*/ == 0x49656e69);
273 }
274 
275 static inline bool IsAMD(const word32 output[4])
276 {
277  // This is the "AuthenticAMD" string. Some early K5's can return "AMDisbetter!"
278  return (output[1] /*EBX*/ == 0x68747541) &&
279  (output[2] /*ECX*/ == 0x444D4163) &&
280  (output[3] /*EDX*/ == 0x69746E65);
281 }
282 
283 static inline bool IsHygon(const word32 output[4])
284 {
285  // This is the "HygonGenuine" string.
286  return (output[1] /*EBX*/ == 0x6f677948) &&
287  (output[2] /*ECX*/ == 0x656e6975) &&
288  (output[3] /*EDX*/ == 0x6e65476e);
289 }
290 
291 static inline bool IsVIA(const word32 output[4])
292 {
293  // This is the "CentaurHauls" string. Some non-PadLock's can return "VIA VIA VIA "
294  return (output[1] /*EBX*/ == 0x746e6543) &&
295  (output[2] /*ECX*/ == 0x736c7561) &&
296  (output[3] /*EDX*/ == 0x48727561);
297 }
298 
299 void DetectX86Features()
300 {
301  // Coverity finding CID 171239...
302  word32 cpuid0[4]={0}, cpuid1[4]={0}, cpuid2[4]={0};
303  if (!CpuId(0, 0, cpuid0))
304  return;
305  if (!CpuId(1, 0, cpuid1))
306  return;
307 
308  // cpuid1[2] & (1 << 27) is XSAVE/XRESTORE and signals OS support for SSE; use it to avoid probes.
309  // See http://github.com/weidai11/cryptopp/issues/511 and http://stackoverflow.com/a/22521619/608639
310  if ((cpuid1[3] & (1 << 26)) != 0)
311  g_hasSSE2 = ((cpuid1[2] & (1 << 27)) != 0) || CPU_ProbeSSE2();
312 
313  g_hasSSSE3 = g_hasSSE2 && ((cpuid1[2] & (1<< 9)) != 0);
314  g_hasSSE41 = g_hasSSE2 && ((cpuid1[2] & (1<<19)) != 0);
315  g_hasSSE42 = g_hasSSE2 && ((cpuid1[2] & (1<<20)) != 0);
316  g_hasAESNI = g_hasSSE2 && ((cpuid1[2] & (1<<25)) != 0);
317  g_hasCLMUL = g_hasSSE2 && ((cpuid1[2] & (1<< 1)) != 0);
318 
319  // AVX is similar to SSE, but check both bits 27 (SSE) and 28 (AVX).
320  // https://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
321  CRYPTOPP_CONSTANT(YMM_FLAG = (3 << 1))
322  CRYPTOPP_CONSTANT(AVX_FLAG = (3 << 27))
323  if ((cpuid1[2] & AVX_FLAG) == AVX_FLAG)
324  {
325 
326 // Unable to perform the necessary tests
327 #if defined(CRYPTOPP_DISABLE_ASM)
328  g_hasAVX = false;
329 
330 // GCC 4.1/Binutils 2.17 cannot consume xgetbv
331 #elif defined(__GNUC__) || (__SUNPRO_CC >= 0x5100) || defined(__BORLANDC__)
332  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71659 and
333  // http://www.agner.org/optimize/vectorclass/read.php?i=65
334  word32 a=0, d=0;
335  __asm __volatile
336  (
337  // "xgetbv" : "=a"(a), "=d"(d) : "c"(0) :
338  ".byte 0x0f, 0x01, 0xd0" "\n\t"
339  : "=a"(a), "=d"(d) : "c"(0) : "cc"
340  );
341  word64 xcr0 = a | static_cast<word64>(d) << 32;
342  g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
343 
344 // Visual Studio 2008 and below lack xgetbv
345 #elif defined(_MSC_VER) && _MSC_VER <= 1500 && defined(_M_IX86)
346  word32 a=0, d=0;
347  __asm {
348  push eax
349  push edx
350  push ecx
351  mov ecx, 0
352  _emit 0x0f
353  _emit 0x01
354  _emit 0xd0
355  mov a, eax
356  mov d, edx
357  pop ecx
358  pop edx
359  pop eax
360  }
361  word64 xcr0 = a | static_cast<word64>(d) << 32;
362  g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
363 
364 // Visual Studio 2008 and below lack xgetbv
365 #elif defined(_MSC_VER) && _MSC_VER <= 1500 && defined(_M_X64)
366  word64 xcr0 = ExtendedControlRegister(0);
367  g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
368 
369 // Downlevel SunCC
370 #elif defined(__SUNPRO_CC)
371  g_hasAVX = false;
372 
373 // _xgetbv is available
374 #else
375  word64 xcr0 = _xgetbv(0);
376  g_hasAVX = (xcr0 & YMM_FLAG) == YMM_FLAG;
377 #endif
378  }
379 
380  if (IsIntel(cpuid0))
381  {
382  CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30))
383  CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18))
384  CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19))
385  CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29))
386  CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5))
387 
388  g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
389  g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
390  g_hasRDRAND = (cpuid1[2] /*ECX*/ & RDRAND_FLAG) != 0;
391 
392  if (cpuid0[0] /*EAX*/ >= 7)
393  {
394  if (CpuId(7, 0, cpuid2))
395  {
396  g_hasRDSEED = (cpuid2[1] /*EBX*/ & RDSEED_FLAG) != 0;
397  g_hasADX = (cpuid2[1] /*EBX*/ & ADX_FLAG) != 0;
398  g_hasSHA = (cpuid2[1] /*EBX*/ & SHA_FLAG) != 0;
399  g_hasAVX2 = (cpuid2[1] /*EBX*/ & AVX2_FLAG) != 0;
400  }
401  }
402  }
403  else if (IsAMD(cpuid0) || IsHygon(cpuid0))
404  {
405  CRYPTOPP_CONSTANT(RDRAND_FLAG = (1 << 30))
406  CRYPTOPP_CONSTANT(RDSEED_FLAG = (1 << 18))
407  CRYPTOPP_CONSTANT( ADX_FLAG = (1 << 19))
408  CRYPTOPP_CONSTANT( SHA_FLAG = (1 << 29))
409  CRYPTOPP_CONSTANT( AVX2_FLAG = (1 << 5))
410 
411  CpuId(0x80000005, 0, cpuid2);
412  g_cacheLineSize = GETBYTE(cpuid2[2], 0);
413  g_hasRDRAND = (cpuid1[2] /*ECX*/ & RDRAND_FLAG) != 0;
414 
415  if (cpuid0[0] /*EAX*/ >= 7)
416  {
417  if (CpuId(7, 0, cpuid2))
418  {
419  g_hasRDSEED = (cpuid2[1] /*EBX*/ & RDSEED_FLAG) != 0;
420  g_hasADX = (cpuid2[1] /*EBX*/ & ADX_FLAG) != 0;
421  g_hasSHA = (cpuid2[1] /*EBX*/ & SHA_FLAG) != 0;
422  g_hasAVX2 = (cpuid2[1] /*EBX*/ & AVX2_FLAG) != 0;
423  }
424  }
425  }
426  else if (IsVIA(cpuid0))
427  {
428  CRYPTOPP_CONSTANT( RNG_FLAGS = (0x3 << 2))
429  CRYPTOPP_CONSTANT( ACE_FLAGS = (0x3 << 6))
430  CRYPTOPP_CONSTANT(ACE2_FLAGS = (0x3 << 8))
431  CRYPTOPP_CONSTANT( PHE_FLAGS = (0x3 << 10))
432  CRYPTOPP_CONSTANT( PMM_FLAGS = (0x3 << 12))
433 
434  CpuId(0xC0000000, 0, cpuid2);
435  if (cpuid2[0] >= 0xC0000001)
436  {
437  // Extended features available
438  CpuId(0xC0000001, 0, cpuid2);
439  g_hasPadlockRNG = (cpuid2[3] /*EDX*/ & RNG_FLAGS) == RNG_FLAGS;
440  g_hasPadlockACE = (cpuid2[3] /*EDX*/ & ACE_FLAGS) == ACE_FLAGS;
441  g_hasPadlockACE2 = (cpuid2[3] /*EDX*/ & ACE2_FLAGS) == ACE2_FLAGS;
442  g_hasPadlockPHE = (cpuid2[3] /*EDX*/ & PHE_FLAGS) == PHE_FLAGS;
443  g_hasPadlockPMM = (cpuid2[3] /*EDX*/ & PMM_FLAGS) == PMM_FLAGS;
444  }
445  }
446 
447  if (g_cacheLineSize == 0)
448  g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
449 
450  *const_cast<volatile bool*>(&g_x86DetectionDone) = true;
451 }
452 
453 // *************************** ARM-32, Aarch32 and Aarch64 ***************************
454 
455 #elif (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8)
456 
457 bool CRYPTOPP_SECTION_INIT g_ArmDetectionDone = false;
458 bool CRYPTOPP_SECTION_INIT g_hasARMv7 = false;
459 bool CRYPTOPP_SECTION_INIT g_hasNEON = false;
460 bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
461 bool CRYPTOPP_SECTION_INIT g_hasCRC32 = false;
462 bool CRYPTOPP_SECTION_INIT g_hasAES = false;
463 bool CRYPTOPP_SECTION_INIT g_hasSHA1 = false;
464 bool CRYPTOPP_SECTION_INIT g_hasSHA2 = false;
465 bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
466 bool CRYPTOPP_SECTION_INIT g_hasSHA3 = false;
467 bool CRYPTOPP_SECTION_INIT g_hasSM3 = false;
468 bool CRYPTOPP_SECTION_INIT g_hasSM4 = false;
469 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
470 
471 // ARM does not have an unprivliged equivalent to CPUID on IA-32. We have to jump through some
472 // hoops to detect features on a wide array of platforms. Our strategy is two part. First,
473 // attempt to *Query* the OS for a feature, like using getauxval on Linux. If that fails,
474 // then *Probe* the cpu executing an instruction and an observe a SIGILL if unsupported.
475 // The probes are in source files where compilation options like -march=armv8-a+crc make
476 // intrinsics available. They are expensive when compared to a standard OS feature query.
477 // Always perform the feature quesry first. For Linux see
478 // http://sourceware.org/ml/libc-help/2017-08/msg00012.html
479 // Avoid probes on Apple platforms because Apple's signal handling for SIGILLs appears broken.
480 // We are trying to figure out a way to feature test without probes. Also see
481 // http://stackoverflow.com/a/11197770/608639 and
482 // http://gist.github.com/erkanyildiz/390a480f27e86f8cd6ba
483 
484 extern bool CPU_ProbeARMv7();
485 extern bool CPU_ProbeNEON();
486 extern bool CPU_ProbeCRC32();
487 extern bool CPU_ProbeAES();
488 extern bool CPU_ProbeSHA1();
489 extern bool CPU_ProbeSHA2();
490 extern bool CPU_ProbeSHA512();
491 extern bool CPU_ProbeSHA3();
492 extern bool CPU_ProbeSM3();
493 extern bool CPU_ProbeSM4();
494 extern bool CPU_ProbePMULL();
495 
496 // https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
497 #ifndef HWCAP_ARMv7
498 # define HWCAP_ARMv7 (1 << 29)
499 #endif
500 #ifndef HWCAP_ASIMD
501 # define HWCAP_ASIMD (1 << 1)
502 #endif
503 #ifndef HWCAP_ARM_NEON
504 # define HWCAP_ARM_NEON 4096
505 #endif
506 #ifndef HWCAP_CRC32
507 # define HWCAP_CRC32 (1 << 7)
508 #endif
509 #ifndef HWCAP2_CRC32
510 # define HWCAP2_CRC32 (1 << 4)
511 #endif
512 #ifndef HWCAP_PMULL
513 # define HWCAP_PMULL (1 << 4)
514 #endif
515 #ifndef HWCAP2_PMULL
516 # define HWCAP2_PMULL (1 << 1)
517 #endif
518 #ifndef HWCAP_AES
519 # define HWCAP_AES (1 << 3)
520 #endif
521 #ifndef HWCAP2_AES
522 # define HWCAP2_AES (1 << 0)
523 #endif
524 #ifndef HWCAP_SHA1
525 # define HWCAP_SHA1 (1 << 5)
526 #endif
527 #ifndef HWCAP_SHA2
528 # define HWCAP_SHA2 (1 << 6)
529 #endif
530 #ifndef HWCAP2_SHA1
531 # define HWCAP2_SHA1 (1 << 2)
532 #endif
533 #ifndef HWCAP2_SHA2
534 # define HWCAP2_SHA2 (1 << 3)
535 #endif
536 #ifndef HWCAP_SHA3
537 # define HWCAP_SHA3 (1 << 17)
538 #endif
539 #ifndef HWCAP_SM3
540 # define HWCAP_SM3 (1 << 18)
541 #endif
542 #ifndef HWCAP_SM4
543 # define HWCAP_SM4 (1 << 19)
544 #endif
545 #ifndef HWCAP_SHA512
546 # define HWCAP_SHA512 (1 << 21)
547 #endif
548 
549 inline bool CPU_QueryARMv7()
550 {
551 #if defined(__aarch32__) || defined(__aarch64__)
552  // ARMv7 or above
553  return true;
554 #elif defined(__ANDROID__) && defined(__arm__)
555  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
556  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0))
557  return true;
558 #elif defined(__linux__) && defined(__arm__)
559  if ((getauxval(AT_HWCAP) & HWCAP_ARMv7) != 0)
560  return true;
561 #elif defined(__APPLE__) && defined(__arm__)
562  // Apple hardware is ARMv7 or above.
563  return true;
564 #endif
565  return false;
566 }
567 
568 inline bool CPU_QueryNEON()
569 {
570 #if defined(__ANDROID__) && defined(__aarch64__)
571  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
572  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_ASIMD) != 0))
573  return true;
574 #elif defined(__ANDROID__) && defined(__arm__)
575  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
576  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0))
577  return true;
578 #elif defined(__linux__) && defined(__aarch64__)
579  if ((getauxval(AT_HWCAP) & HWCAP_ASIMD) != 0)
580  return true;
581 #elif defined(__linux__) && defined(__aarch32__)
582  if ((getauxval(AT_HWCAP2) & HWCAP2_ASIMD) != 0)
583  return true;
584 #elif defined(__linux__) && defined(__arm__)
585  if ((getauxval(AT_HWCAP) & HWCAP_ARM_NEON) != 0)
586  return true;
587 #elif defined(__APPLE__) && defined(__aarch64__)
588  // Core feature set for Aarch32 and Aarch64.
589  return true;
590 #endif
591  return false;
592 }
593 
594 inline bool CPU_QueryCRC32()
595 {
596 #if defined(__ANDROID__) && defined(__aarch64__)
597  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
598  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_CRC32) != 0))
599  return true;
600 #elif defined(__ANDROID__) && defined(__aarch32__)
601  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
602  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_CRC32) != 0))
603  return true;
604 #elif defined(__linux__) && defined(__aarch64__)
605  if ((getauxval(AT_HWCAP) & HWCAP_CRC32) != 0)
606  return true;
607 #elif defined(__linux__) && defined(__aarch32__)
608  if ((getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0)
609  return true;
610 #elif defined(__APPLE__) && defined(__aarch64__)
611  // No compiler support. CRC intrinsics result in a failed compiled.
612  return false;
613 #endif
614  return false;
615 }
616 
617 inline bool CPU_QueryPMULL()
618 {
619 #if defined(__ANDROID__) && defined(__aarch64__)
620  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
621  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_PMULL) != 0))
622  return true;
623 #elif defined(__ANDROID__) && defined(__aarch32__)
624  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
625  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_PMULL) != 0))
626  return true;
627 #elif defined(__linux__) && defined(__aarch64__)
628  if ((getauxval(AT_HWCAP) & HWCAP_PMULL) != 0)
629  return true;
630 #elif defined(__linux__) && defined(__aarch32__)
631  if ((getauxval(AT_HWCAP2) & HWCAP2_PMULL) != 0)
632  return true;
633 #elif defined(__APPLE__) && defined(__aarch64__)
634  // No compiler support. PMULL intrinsics result in a failed compiled.
635  return false;
636 #endif
637  return false;
638 }
639 
640 inline bool CPU_QueryAES()
641 {
642 #if defined(__ANDROID__) && defined(__aarch64__)
643  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
644  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES) != 0))
645  return true;
646 #elif defined(__ANDROID__) && defined(__aarch32__)
647  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
648  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES) != 0))
649  return true;
650 #elif defined(__linux__) && defined(__aarch64__)
651  if ((getauxval(AT_HWCAP) & HWCAP_AES) != 0)
652  return true;
653 #elif defined(__linux__) && defined(__aarch32__)
654  if ((getauxval(AT_HWCAP2) & HWCAP2_AES) != 0)
655  return true;
656 #elif defined(__APPLE__) && defined(__aarch64__)
657  unsigned int device, version;
658  GetAppleMachineInfo(device, version);
659  return IsAppleMachineARMv8(device, version);
660 #endif
661  return false;
662 }
663 
664 inline bool CPU_QuerySHA1()
665 {
666 #if defined(__ANDROID__) && defined(__aarch64__)
667  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
668  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA1) != 0))
669  return true;
670 #elif defined(__ANDROID__) && defined(__aarch32__)
671  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
672  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA1) != 0))
673  return true;
674 #elif defined(__linux__) && defined(__aarch64__)
675  if ((getauxval(AT_HWCAP) & HWCAP_SHA1) != 0)
676  return true;
677 #elif defined(__linux__) && defined(__aarch32__)
678  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA1) != 0)
679  return true;
680 #elif defined(__APPLE__) && defined(__aarch64__)
681  unsigned int device, version;
682  GetAppleMachineInfo(device, version);
683  return IsAppleMachineARMv8(device, version);
684 #endif
685  return false;
686 }
687 
688 inline bool CPU_QuerySHA2()
689 {
690 #if defined(__ANDROID__) && defined(__aarch64__)
691  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
692  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA2) != 0))
693  return true;
694 #elif defined(__ANDROID__) && defined(__aarch32__)
695  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
696  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA2) != 0))
697  return true;
698 #elif defined(__linux__) && defined(__aarch64__)
699  if ((getauxval(AT_HWCAP) & HWCAP_SHA2) != 0)
700  return true;
701 #elif defined(__linux__) && defined(__aarch32__)
702  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA2) != 0)
703  return true;
704 #elif defined(__APPLE__) && defined(__aarch64__)
705  unsigned int device, version;
706  GetAppleMachineInfo(device, version);
707  return IsAppleMachineARMv8(device, version);
708 #endif
709  return false;
710 }
711 
712 inline bool CPU_QuerySHA512()
713 {
714 // Some ARMv8.4 features are disabled at the moment
715 #if defined(__ANDROID__) && defined(__aarch64__) && 0
716  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
717  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA512) != 0))
718  return true;
719 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
720  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
721  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA512) != 0))
722  return true;
723 #elif defined(__linux__) && defined(__aarch64__)
724  if ((getauxval(AT_HWCAP) & HWCAP_SHA512) != 0)
725  return true;
726 #elif defined(__linux__) && defined(__aarch32__)
727  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA512) != 0)
728  return true;
729 #elif defined(__APPLE__) && defined(__aarch64__) && 0
730  unsigned int device, version;
731  GetAppleMachineInfo(device, version);
732  return IsAppleMachineARMv84(device, version);
733 #endif
734  return false;
735 }
736 
737 inline bool CPU_QuerySHA3()
738 {
739 // Some ARMv8.4 features are disabled at the moment
740 #if defined(__ANDROID__) && defined(__aarch64__) && 0
741  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
742  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SHA3) != 0))
743  return true;
744 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
745  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
746  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SHA3) != 0))
747  return true;
748 #elif defined(__linux__) && defined(__aarch64__)
749  if ((getauxval(AT_HWCAP) & HWCAP_SHA3) != 0)
750  return true;
751 #elif defined(__linux__) && defined(__aarch32__)
752  if ((getauxval(AT_HWCAP2) & HWCAP2_SHA3) != 0)
753  return true;
754 #elif defined(__APPLE__) && defined(__aarch64__) && 0
755  unsigned int device, version;
756  GetAppleMachineInfo(device, version);
757  return IsAppleMachineARMv84(device, version);
758 #endif
759  return false;
760 }
761 
762 inline bool CPU_QuerySM3()
763 {
764 // Some ARMv8.4 features are disabled at the moment
765 #if defined(__ANDROID__) && defined(__aarch64__) && 0
766  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
767  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM3) != 0))
768  return true;
769 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
770  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
771  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM3) != 0))
772  return true;
773 #elif defined(__linux__) && defined(__aarch64__)
774  if ((getauxval(AT_HWCAP) & HWCAP_SM3) != 0)
775  return true;
776 #elif defined(__linux__) && defined(__aarch32__)
777  if ((getauxval(AT_HWCAP2) & HWCAP2_SM3) != 0)
778  return true;
779 #elif defined(__APPLE__) && defined(__aarch64__) && 0
780  unsigned int device, version;
781  GetAppleMachineInfo(device, version);
782  return IsAppleMachineARMv84(device, version);
783 #endif
784  return false;
785 }
786 
787 inline bool CPU_QuerySM4()
788 {
789 // Some ARMv8.4 features are disabled at the moment
790 #if defined(__ANDROID__) && defined(__aarch64__) && 0
791  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM64) != 0) &&
792  ((android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_SM4) != 0))
793  return true;
794 #elif defined(__ANDROID__) && defined(__aarch32__) && 0
795  if (((android_getCpuFamily() & ANDROID_CPU_FAMILY_ARM) != 0) &&
796  ((android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_SM4) != 0))
797  return true;
798 #elif defined(__linux__) && defined(__aarch64__)
799  if ((getauxval(AT_HWCAP) & HWCAP_SM4) != 0)
800  return true;
801 #elif defined(__linux__) && defined(__aarch32__)
802  if ((getauxval(AT_HWCAP2) & HWCAP2_SM4) != 0)
803  return true;
804 #elif defined(__APPLE__) && defined(__aarch64__) && 0
805  unsigned int device, version;
806  GetAppleMachineInfo(device, version);
807  return IsAppleMachineARMv84(device, version);
808 #endif
809  return false;
810 }
811 
812 void DetectArmFeatures()
813 {
814  // The CPU_ProbeXXX's return false for OSes which
815  // can't tolerate SIGILL-based probes
816  g_hasARMv7 = CPU_QueryARMv7() || CPU_ProbeARMv7();
817  g_hasNEON = CPU_QueryNEON() || CPU_ProbeNEON();
818  g_hasCRC32 = CPU_QueryCRC32() || CPU_ProbeCRC32();
819  g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
820  g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
821  g_hasSHA1 = CPU_QuerySHA1() || CPU_ProbeSHA1();
822  g_hasSHA2 = CPU_QuerySHA2() || CPU_ProbeSHA2();
823  g_hasSHA512 = CPU_QuerySHA512(); // || CPU_ProbeSHA512();
824  g_hasSHA3 = CPU_QuerySHA3(); // || CPU_ProbeSHA3();
825  g_hasSM3 = CPU_QuerySM3(); // || CPU_ProbeSM3();
826  g_hasSM4 = CPU_QuerySM4(); // || CPU_ProbeSM4();
827 
828 #if defined(__linux__) && defined(_SC_LEVEL1_DCACHE_LINESIZE)
829  // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
830  // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
831  int cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
832  if (cacheLineSize > 0)
833  g_cacheLineSize = cacheLineSize;
834 #endif
835 
836  *const_cast<volatile bool*>(&g_ArmDetectionDone) = true;
837 }
838 
839 // *************************** PowerPC and PowerPC64 ***************************
840 
841 #elif (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
842 
843 bool CRYPTOPP_SECTION_INIT g_PowerpcDetectionDone = false;
844 bool CRYPTOPP_SECTION_INIT g_hasAltivec = false;
845 bool CRYPTOPP_SECTION_INIT g_hasPower7 = false;
846 bool CRYPTOPP_SECTION_INIT g_hasPower8 = false;
847 bool CRYPTOPP_SECTION_INIT g_hasPower9 = false;
848 bool CRYPTOPP_SECTION_INIT g_hasAES = false;
849 bool CRYPTOPP_SECTION_INIT g_hasPMULL = false;
850 bool CRYPTOPP_SECTION_INIT g_hasSHA256 = false;
851 bool CRYPTOPP_SECTION_INIT g_hasSHA512 = false;
852 bool CRYPTOPP_SECTION_INIT g_hasDARN = false;
853 word32 CRYPTOPP_SECTION_INIT g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
854 
855 extern bool CPU_ProbeAltivec();
856 extern bool CPU_ProbePower7();
857 extern bool CPU_ProbePower8();
858 extern bool CPU_ProbePower9();
859 extern bool CPU_ProbeAES();
860 extern bool CPU_ProbePMULL();
861 extern bool CPU_ProbeSHA256();
862 extern bool CPU_ProbeSHA512();
863 extern bool CPU_ProbeDARN();
864 
865 // Linux define values from 64-Bit ELF V2 ABI Specification.
866 // http://openpowerfoundation.org/wp-content/uploads/resources/leabi/content/ch_preface.html
867 #ifndef PPC_FEATURE_HAS_ALTIVEC
868 # define PPC_FEATURE_HAS_ALTIVEC 0x10000000
869 #endif
870 #ifndef PPC_FEATURE_ARCH_2_06
871 # define PPC_FEATURE_ARCH_2_06 0x00000100
872 #endif
873 #ifndef PPC_FEATURE2_ARCH_2_07
874 # define PPC_FEATURE2_ARCH_2_07 0x80000000
875 #endif
876 #ifndef PPC_FEATURE2_ARCH_3_00
877 # define PPC_FEATURE2_ARCH_3_00 0x00800000
878 #endif
879 #ifndef PPC_FEATURE2_VEC_CRYPTO
880 # define PPC_FEATURE2_VEC_CRYPTO 0x02000000
881 #endif
882 
883 // AIX defines. We used to just call __power_7_andup()
884 // and friends but at Power9, too many compilers were
885 // missing __power_9_andup(). Instead we switched to
886 // a pattern similar to OpenSSL caps testing.
887 #ifndef __power_6_andup
888 # define __power_6_andup() __power_set(0xffffffffU<<14)
889 #endif
890 #ifndef __power_7_andup
891 # define __power_7_andup() __power_set(0xffffffffU<<15)
892 #endif
893 #ifndef __power_8_andup
894 # define __power_8_andup() __power_set(0xffffffffU<<16)
895 #endif
896 #ifndef __power_9_andup
897 # define __power_9_andup() __power_set(0xffffffffU<<17)
898 #endif
899 
900 // AIX first supported Altivec at Power6, though it
901 // was available much earlier for other vendors.
902 inline bool CPU_QueryAltivec()
903 {
904 #if defined(__linux__)
905  if ((getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC) != 0)
906  return true;
907 #elif defined(_AIX)
908  if (__power_6_andup() != 0)
909  return true;
910 #elif defined(__APPLE__) && defined(__POWERPC__)
911  unsigned int device, version;
912  GetAppleMachineInfo(device, version);
913  return device == PowerMac;
914 #endif
915  return false;
916 }
917 
918 inline bool CPU_QueryPower7()
919 {
920  // Power7 and ISA 2.06
921 #if defined(__linux__)
922  if ((getauxval(AT_HWCAP) & PPC_FEATURE_ARCH_2_06) != 0)
923  return true;
924 #elif defined(_AIX)
925  if (__power_7_andup() != 0)
926  return true;
927 #endif
928  return false;
929 }
930 
931 inline bool CPU_QueryPower8()
932 {
933  // Power8 and ISA 2.07 provide in-core crypto.
934 #if defined(__linux__)
935  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07) != 0)
936  return true;
937 #elif defined(_AIX)
938  if (__power_8_andup() != 0)
939  return true;
940 #endif
941  return false;
942 }
943 
944 inline bool CPU_QueryPower9()
945 {
946  // Power9 and ISA 3.0.
947 #if defined(__linux__)
948  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
949  return true;
950 #elif defined(_AIX)
951  if (__power_9_andup() != 0)
952  return true;
953 #endif
954  return false;
955 }
956 
957 inline bool CPU_QueryAES()
958 {
959  // Power8 and ISA 2.07 provide in-core crypto. Glibc
960  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
961 #if defined(__linux__)
962  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
963  return true;
964 #elif defined(_AIX)
965  if (__power_8_andup() != 0)
966  return true;
967 #endif
968  return false;
969 }
970 
971 inline bool CPU_QueryPMULL()
972 {
973  // Power8 and ISA 2.07 provide in-core crypto. Glibc
974  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
975 #if defined(__linux__)
976  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
977  return true;
978 #elif defined(_AIX)
979  if (__power_8_andup() != 0)
980  return true;
981 #endif
982  return false;
983 }
984 
985 inline bool CPU_QuerySHA256()
986 {
987  // Power8 and ISA 2.07 provide in-core crypto. Glibc
988  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
989 #if defined(__linux__)
990  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
991  return true;
992 #elif defined(_AIX)
993  if (__power_8_andup() != 0)
994  return true;
995 #endif
996  return false;
997 }
998 inline bool CPU_QuerySHA512()
999 {
1000  // Power8 and ISA 2.07 provide in-core crypto. Glibc
1001  // 2.24 or higher is required for PPC_FEATURE2_VEC_CRYPTO.
1002 #if defined(__linux__)
1003  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) != 0)
1004  return true;
1005 #elif defined(_AIX)
1006  if (__power_8_andup() != 0)
1007  return true;
1008 #endif
1009  return false;
1010 }
1011 
1012 // Power9 random number generator
1013 inline bool CPU_QueryDARN()
1014 {
1015  // Power9 and ISA 3.0 provide DARN.
1016 #if defined(__linux__)
1017  if ((getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00) != 0)
1018  return true;
1019 #elif defined(_AIX)
1020  if (__power_9_andup() != 0)
1021  return true;
1022 #endif
1023  return false;
1024 }
1025 
1026 void DetectPowerpcFeatures()
1027 {
1028  // The CPU_ProbeXXX's return false for OSes which
1029  // can't tolerate SIGILL-based probes, like Apple
1030  g_hasAltivec = CPU_QueryAltivec() || CPU_ProbeAltivec();
1031  g_hasPower7 = CPU_QueryPower7() || CPU_ProbePower7();
1032  g_hasPower8 = CPU_QueryPower8() || CPU_ProbePower8();
1033  g_hasPower9 = CPU_QueryPower9() || CPU_ProbePower9();
1034  g_hasPMULL = CPU_QueryPMULL() || CPU_ProbePMULL();
1035  g_hasAES = CPU_QueryAES() || CPU_ProbeAES();
1036  g_hasSHA256 = CPU_QuerySHA256() || CPU_ProbeSHA256();
1037  g_hasSHA512 = CPU_QuerySHA512() || CPU_ProbeSHA512();
1038  g_hasDARN = CPU_QueryDARN() || CPU_ProbeDARN();
1039 
1040 #if defined(_AIX) && defined(SC_L1C_DLS)
1041  // /usr/include/sys/systemcfg.h
1042  int cacheLineSize = getsystemcfg(SC_L1C_DLS);
1043  if (cacheLineSize > 0)
1044  g_cacheLineSize = cacheLineSize;
1045 #elif defined(__linux__) && defined(_SC_LEVEL1_DCACHE_LINESIZE)
1046  // Glibc does not implement on some platforms. The runtime returns 0 instead of error.
1047  // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/sysconf.c
1048  int cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
1049  if (cacheLineSize > 0)
1050  g_cacheLineSize = cacheLineSize;
1051 #endif
1052 
1053  *const_cast<volatile bool*>(&g_PowerpcDetectionDone) = true;
1054 }
1055 
1056 #endif
1057 NAMESPACE_END
1058 
1059 // *************************** C++ Static Initialization ***************************
1060 
1061 ANONYMOUS_NAMESPACE_BEGIN
1062 
1063 class InitCpu
1064 {
1065 public:
1066  InitCpu()
1067  {
1068 #if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
1069  CryptoPP::DetectX86Features();
1070 #elif CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARMV8
1071  CryptoPP::DetectArmFeatures();
1072 #elif CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64
1073  CryptoPP::DetectPowerpcFeatures();
1074 #endif
1075  }
1076 };
1077 
1078 // This is not really needed because HasSSE() and friends can dynamically initialize.
1079 // Everything depends on CPU features so we initialize it once at load time.
1080 // Dynamic initialization will be used if init priorities are not available.
1081 
1082 #if HAVE_GCC_INIT_PRIORITY
1083  const InitCpu s_init __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 10))) = InitCpu();
1084 #elif HAVE_MSC_INIT_PRIORITY
1085  #pragma warning(disable: 4075)
1086  #pragma init_seg(".CRT$XCU")
1087  const InitCpu s_init;
1088  #pragma warning(default: 4075)
1089 #elif HAVE_XLC_INIT_PRIORITY
1090  // XLC needs constant, not a define
1091  #pragma priority(270)
1092  const InitCpu s_init;
1093 #else
1094  const InitCpu s_init;
1095 #endif
1096 
1097 ANONYMOUS_NAMESPACE_END
1098 
1099 #endif // CRYPTOPP_IMPORTS
Utility functions for the Crypto++ library.
Library configuration file.
Common C++ header files.
Precompiled header file.
Functions for CPU features and intrinsics.
Crypto++ library namespace.