Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
3.7 KiB

  1. // cpu.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #ifndef CRYPTOPP_IMPORTS
  4. #include "cpu.h"
  5. #include "misc.h"
  6. #include <algorithm>
  7. #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
  8. #include <signal.h>
  9. #include <setjmp.h>
  10. #endif
  11. #if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
  12. #include <emmintrin.h>
  13. #endif
  14. NAMESPACE_BEGIN(CryptoPP)
  15. #ifdef CRYPTOPP_CPUID_AVAILABLE
  16. #if _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
  17. bool CpuId(word32 input, word32 *output)
  18. {
  19. __cpuid((int *)output, input);
  20. return true;
  21. }
  22. #else
  23. #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
  24. extern "C" {
  25. typedef void (*SigHandler)(int);
  26. static jmp_buf s_jmpNoCPUID;
  27. static void SigIllHandlerCPUID(int)
  28. {
  29. longjmp(s_jmpNoCPUID, 1);
  30. }
  31. static jmp_buf s_jmpNoSSE2;
  32. static void SigIllHandlerSSE2(int)
  33. {
  34. longjmp(s_jmpNoSSE2, 1);
  35. }
  36. }
  37. #endif
  38. bool CpuId(word32 input, word32 *output)
  39. {
  40. #ifdef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
  41. __try
  42. {
  43. __asm
  44. {
  45. mov eax, input
  46. cpuid
  47. mov edi, output
  48. mov [edi], eax
  49. mov [edi+4], ebx
  50. mov [edi+8], ecx
  51. mov [edi+12], edx
  52. }
  53. }
  54. __except (1)
  55. {
  56. return false;
  57. }
  58. return true;
  59. #else
  60. SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
  61. if (oldHandler == SIG_ERR)
  62. return false;
  63. bool result = true;
  64. if (setjmp(s_jmpNoCPUID))
  65. result = false;
  66. else
  67. {
  68. asm
  69. (
  70. // save ebx in case -fPIC is being used
  71. #if CRYPTOPP_BOOL_X86
  72. "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
  73. #else
  74. "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
  75. #endif
  76. : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
  77. : "a" (input)
  78. );
  79. }
  80. signal(SIGILL, oldHandler);
  81. return result;
  82. #endif
  83. }
  84. #endif
  85. static bool TrySSE2()
  86. {
  87. #if CRYPTOPP_BOOL_X64
  88. return true;
  89. #elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
  90. __try
  91. {
  92. #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
  93. AS2(por xmm0, xmm0) // executing SSE2 instruction
  94. #elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
  95. __m128i x = _mm_setzero_si128();
  96. return _mm_cvtsi128_si32(x) == 0;
  97. #endif
  98. }
  99. __except (1)
  100. {
  101. return false;
  102. }
  103. return true;
  104. #else
  105. SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
  106. if (oldHandler == SIG_ERR)
  107. return false;
  108. bool result = true;
  109. if (setjmp(s_jmpNoSSE2))
  110. result = false;
  111. else
  112. {
  113. #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
  114. __asm __volatile ("por %xmm0, %xmm0");
  115. #elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
  116. __m128i x = _mm_setzero_si128();
  117. result = _mm_cvtsi128_si32(x) == 0;
  118. #endif
  119. }
  120. signal(SIGILL, oldHandler);
  121. return result;
  122. #endif
  123. }
  124. bool g_x86DetectionDone = false;
  125. bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_hasAESNI = false, g_hasCLMUL = false, g_isP4 = false;
  126. word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
  127. void DetectX86Features()
  128. {
  129. word32 cpuid[4], cpuid1[4];
  130. if (!CpuId(0, cpuid))
  131. return;
  132. if (!CpuId(1, cpuid1))
  133. return;
  134. g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
  135. if ((cpuid1[3] & (1 << 26)) != 0)
  136. g_hasSSE2 = TrySSE2();
  137. g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
  138. g_hasAESNI = g_hasSSE2 && (cpuid1[2] & (1<<25));
  139. g_hasCLMUL = g_hasSSE2 && (cpuid1[2] & (1<<1));
  140. if ((cpuid1[3] & (1 << 25)) != 0)
  141. g_hasISSE = true;
  142. else
  143. {
  144. word32 cpuid2[4];
  145. CpuId(0x080000000, cpuid2);
  146. if (cpuid2[0] >= 0x080000001)
  147. {
  148. CpuId(0x080000001, cpuid2);
  149. g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
  150. }
  151. }
  152. std::swap(cpuid[2], cpuid[3]);
  153. if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)
  154. {
  155. g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
  156. g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
  157. }
  158. else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)
  159. {
  160. CpuId(0x80000005, cpuid);
  161. g_cacheLineSize = GETBYTE(cpuid[2], 0);
  162. }
  163. if (!g_cacheLineSize)
  164. g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
  165. g_x86DetectionDone = true;
  166. }
  167. #endif
  168. NAMESPACE_END
  169. #endif