-// cpu.cpp - written and placed in the public domain by Wei Dai\r
-\r
-#include "pch.h"\r
-\r
-#ifndef CRYPTOPP_IMPORTS\r
-\r
-#include "cpu.h"\r
-#include "misc.h"\r
-#include <algorithm>\r
-\r
-#ifdef __GNUC__\r
-#include <signal.h>\r
-#include <setjmp.h>\r
-#endif\r
-\r
-#ifdef CRYPTOPP_MSVC6PP_OR_LATER\r
-#include <emmintrin.h>\r
-#endif\r
-\r
-NAMESPACE_BEGIN(CryptoPP)\r
-\r
-#ifdef CRYPTOPP_X86_ASM_AVAILABLE\r
-\r
-#ifndef _MSC_VER\r
-typedef void (*SigHandler)(int);\r
-\r
-static jmp_buf s_jmpNoCPUID;\r
-static void SigIllHandlerCPUID(int)\r
-{\r
- longjmp(s_jmpNoCPUID, 1);\r
-}\r
-#endif\r
-\r
-bool CpuId(word32 input, word32 *output)\r
-{\r
-#ifdef _MSC_VER\r
- __try\r
- {\r
- __asm\r
- {\r
- mov eax, input\r
- cpuid\r
- mov edi, output\r
- mov [edi], eax\r
- mov [edi+4], ebx\r
- mov [edi+8], ecx\r
- mov [edi+12], edx\r
- }\r
- }\r
- __except (1)\r
- {\r
- return false;\r
- }\r
- return true;\r
-#else\r
- SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);\r
- if (oldHandler == SIG_ERR)\r
- return false;\r
-\r
- bool result = true;\r
- if (setjmp(s_jmpNoCPUID))\r
- result = false;\r
- else\r
- {\r
- __asm__\r
- (\r
- // save ebx in case -fPIC is being used\r
-#if CRYPTOPP_BOOL_X86\r
- "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"\r
-#else\r
- "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"\r
-#endif\r
- : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])\r
- : "a" (input)\r
- );\r
- }\r
-\r
- signal(SIGILL, oldHandler);\r
- return result;\r
-#endif\r
-}\r
-\r
-#ifndef _MSC_VER\r
-static jmp_buf s_jmpNoSSE2;\r
-static void SigIllHandlerSSE2(int)\r
-{\r
- longjmp(s_jmpNoSSE2, 1);\r
-}\r
-#endif\r
-\r
-#elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64\r
-\r
-bool CpuId(word32 input, word32 *output)\r
-{\r
- __cpuid((int *)output, input);\r
- return true;\r
-}\r
-\r
-#endif\r
-\r
-#ifdef CRYPTOPP_CPUID_AVAILABLE\r
-\r
-static bool TrySSE2()\r
-{\r
-#if CRYPTOPP_BOOL_X64\r
- return true;\r
-#elif defined(_MSC_VER)\r
- __try\r
- {\r
-#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
- AS2(por xmm0, xmm0) // executing SSE2 instruction\r
-#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE\r
- __mm128i x = _mm_setzero_si128();\r
- return _mm_cvtsi128_si32(x) == 0;\r
-#endif\r
- }\r
- __except (1)\r
- {\r
- return false;\r
- }\r
- return true;\r
-#elif defined(__GNUC__)\r
- SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);\r
- if (oldHandler == SIG_ERR)\r
- return false;\r
-\r
- bool result = true;\r
- if (setjmp(s_jmpNoSSE2))\r
- result = false;\r
- else\r
- {\r
-#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE\r
- __asm __volatile ("por %xmm0, %xmm0");\r
-#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE\r
- __mm128i x = _mm_setzero_si128();\r
- result = _mm_cvtsi128_si32(x) == 0;\r
-#endif\r
- }\r
-\r
- signal(SIGILL, oldHandler);\r
- return result;\r
-#else\r
- return false;\r
-#endif\r
-}\r
-\r
-bool g_x86DetectionDone = false;\r
-bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_isP4 = false;\r
-word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;\r
-\r
-void DetectX86Features()\r
-{\r
- word32 cpuid[4], cpuid1[4];\r
- if (!CpuId(0, cpuid))\r
- return;\r
- if (!CpuId(1, cpuid1))\r
- return;\r
-\r
- g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;\r
- if ((cpuid1[3] & (1 << 26)) != 0)\r
- g_hasSSE2 = TrySSE2();\r
- g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));\r
-\r
- if ((cpuid1[3] & (1 << 25)) != 0)\r
- g_hasISSE = true;\r
- else\r
- {\r
- word32 cpuid2[4];\r
- CpuId(0x080000000, cpuid2);\r
- if (cpuid2[0] >= 0x080000001)\r
- {\r
- CpuId(0x080000001, cpuid2);\r
- g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;\r
- }\r
- }\r
-\r
- std::swap(cpuid[2], cpuid[3]);\r
- if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)\r
- {\r
- g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;\r
- g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);\r
- }\r
- else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)\r
- {\r
- CpuId(0x80000005, cpuid);\r
- g_cacheLineSize = GETBYTE(cpuid[2], 0);\r
- }\r
-\r
- if (!g_cacheLineSize)\r
- g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;\r
-\r
- g_x86DetectionDone = true;\r
-}\r
-\r
-#endif\r
-\r
-NAMESPACE_END\r
-\r
-#endif\r
+// cpu.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "cpu.h"
+#include "misc.h"
+#include <algorithm>
+
+#ifdef __GNUC__
+#include <signal.h>
+#include <setjmp.h>
+#endif
+
+#ifdef CRYPTOPP_MSVC6PP_OR_LATER
+#include <emmintrin.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef CRYPTOPP_X86_ASM_AVAILABLE
+
+#ifndef _MSC_VER
+typedef void (*SigHandler)(int);
+
+static jmp_buf s_jmpNoCPUID;
+static void SigIllHandlerCPUID(int)
+{
+ longjmp(s_jmpNoCPUID, 1);
+}
+#endif
+
+bool CpuId(word32 input, word32 *output)
+{
+#ifdef _MSC_VER
+ __try
+ {
+ __asm
+ {
+ mov eax, input
+ cpuid
+ mov edi, output
+ mov [edi], eax
+ mov [edi+4], ebx
+ mov [edi+8], ecx
+ mov [edi+12], edx
+ }
+ }
+ __except (1)
+ {
+ return false;
+ }
+ return true;
+#else
+ SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
+ if (oldHandler == SIG_ERR)
+ return false;
+
+ bool result = true;
+ if (setjmp(s_jmpNoCPUID))
+ result = false;
+ else
+ {
+ __asm__
+ (
+ // save ebx in case -fPIC is being used
+#if CRYPTOPP_BOOL_X86
+ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+#else
+ "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
+#endif
+ : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
+ : "a" (input)
+ );
+ }
+
+ signal(SIGILL, oldHandler);
+ return result;
+#endif
+}
+
+#ifndef _MSC_VER
+static jmp_buf s_jmpNoSSE2;
+static void SigIllHandlerSSE2(int)
+{
+ longjmp(s_jmpNoSSE2, 1);
+}
+#endif
+
+#elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
+
+bool CpuId(word32 input, word32 *output)
+{
+ __cpuid((int *)output, input);
+ return true;
+}
+
+#endif
+
+#ifdef CRYPTOPP_CPUID_AVAILABLE
+
+static bool TrySSE2()
+{
+#if CRYPTOPP_BOOL_X64
+ return true;
+#elif defined(_MSC_VER)
+ __try
+ {
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ AS2(por xmm0, xmm0) // executing SSE2 instruction
+#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+ __mm128i x = _mm_setzero_si128();
+ return _mm_cvtsi128_si32(x) == 0;
+#endif
+ }
+ __except (1)
+ {
+ return false;
+ }
+ return true;
+#elif defined(__GNUC__)
+ SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
+ if (oldHandler == SIG_ERR)
+ return false;
+
+ bool result = true;
+ if (setjmp(s_jmpNoSSE2))
+ result = false;
+ else
+ {
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ __asm __volatile ("por %xmm0, %xmm0");
+#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+ __mm128i x = _mm_setzero_si128();
+ result = _mm_cvtsi128_si32(x) == 0;
+#endif
+ }
+
+ signal(SIGILL, oldHandler);
+ return result;
+#else
+ return false;
+#endif
+}
+
+bool g_x86DetectionDone = false;
+bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_isP4 = false;
+word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
+
+void DetectX86Features()
+{
+ word32 cpuid[4], cpuid1[4];
+ if (!CpuId(0, cpuid))
+ return;
+ if (!CpuId(1, cpuid1))
+ return;
+
+ g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
+ if ((cpuid1[3] & (1 << 26)) != 0)
+ g_hasSSE2 = TrySSE2();
+ g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
+
+ if ((cpuid1[3] & (1 << 25)) != 0)
+ g_hasISSE = true;
+ else
+ {
+ word32 cpuid2[4];
+ CpuId(0x080000000, cpuid2);
+ if (cpuid2[0] >= 0x080000001)
+ {
+ CpuId(0x080000001, cpuid2);
+ g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
+ }
+ }
+
+ std::swap(cpuid[2], cpuid[3]);
+ if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)
+ {
+ g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
+ g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
+ }
+ else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)
+ {
+ CpuId(0x80000005, cpuid);
+ g_cacheLineSize = GETBYTE(cpuid[2], 0);
+ }
+
+ if (!g_cacheLineSize)
+ g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
+
+ g_x86DetectionDone = true;
+}
+
+#endif
+
+NAMESPACE_END
+
+#endif