Team Fortress 2 Source Code as on 22/4/2020
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.

190 lines
3.9 KiB

  1. /* CpuArch.c -- CPU specific code
  2. 2012-05-29: Igor Pavlov : Public domain */
  3. #include "Precomp.h"
  4. #include "CpuArch.h"
  5. #ifdef MY_CPU_X86_OR_AMD64
  6. #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
  7. #define USE_ASM
  8. #endif
  9. #if !defined(USE_ASM) && _MSC_VER >= 1500
  10. #include <intrin.h>
  11. #endif
  12. #if defined(USE_ASM) && !defined(MY_CPU_AMD64)
  13. static UInt32 CheckFlag(UInt32 flag)
  14. {
  15. #ifdef _MSC_VER
  16. __asm pushfd;
  17. __asm pop EAX;
  18. __asm mov EDX, EAX;
  19. __asm xor EAX, flag;
  20. __asm push EAX;
  21. __asm popfd;
  22. __asm pushfd;
  23. __asm pop EAX;
  24. __asm xor EAX, EDX;
  25. __asm push EDX;
  26. __asm popfd;
  27. __asm and flag, EAX;
  28. #else
  29. __asm__ __volatile__ (
  30. "pushf\n\t"
  31. "pop %%EAX\n\t"
  32. "movl %%EAX,%%EDX\n\t"
  33. "xorl %0,%%EAX\n\t"
  34. "push %%EAX\n\t"
  35. "popf\n\t"
  36. "pushf\n\t"
  37. "pop %%EAX\n\t"
  38. "xorl %%EDX,%%EAX\n\t"
  39. "push %%EDX\n\t"
  40. "popf\n\t"
  41. "andl %%EAX, %0\n\t":
  42. "=c" (flag) : "c" (flag));
  43. #endif
  44. return flag;
  45. }
  46. #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
  47. #else
  48. #define CHECK_CPUID_IS_SUPPORTED
  49. #endif
  50. static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
  51. {
  52. #ifdef USE_ASM
  53. #ifdef _MSC_VER
  54. UInt32 a2, b2, c2, d2;
  55. __asm xor EBX, EBX;
  56. __asm xor ECX, ECX;
  57. __asm xor EDX, EDX;
  58. __asm mov EAX, function;
  59. __asm cpuid;
  60. __asm mov a2, EAX;
  61. __asm mov b2, EBX;
  62. __asm mov c2, ECX;
  63. __asm mov d2, EDX;
  64. *a = a2;
  65. *b = b2;
  66. *c = c2;
  67. *d = d2;
  68. #else
  69. __asm__ __volatile__ (
  70. #if defined(MY_CPU_X86) && defined(__PIC__)
  71. "mov %%ebx, %%edi;"
  72. "cpuid;"
  73. "xchgl %%ebx, %%edi;"
  74. : "=a" (*a) ,
  75. "=D" (*b) ,
  76. #else
  77. "cpuid"
  78. : "=a" (*a) ,
  79. "=b" (*b) ,
  80. #endif
  81. "=c" (*c) ,
  82. "=d" (*d)
  83. : "0" (function)) ;
  84. #endif
  85. #else
  86. int CPUInfo[4];
  87. __cpuid(CPUInfo, function);
  88. *a = CPUInfo[0];
  89. *b = CPUInfo[1];
  90. *c = CPUInfo[2];
  91. *d = CPUInfo[3];
  92. #endif
  93. }
  94. Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
  95. {
  96. CHECK_CPUID_IS_SUPPORTED
  97. MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
  98. MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
  99. return True;
  100. }
  101. static UInt32 kVendors[][3] =
  102. {
  103. { 0x756E6547, 0x49656E69, 0x6C65746E},
  104. { 0x68747541, 0x69746E65, 0x444D4163},
  105. { 0x746E6543, 0x48727561, 0x736C7561}
  106. };
  107. int x86cpuid_GetFirm(const Cx86cpuid *p)
  108. {
  109. unsigned i;
  110. for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
  111. {
  112. const UInt32 *v = kVendors[i];
  113. if (v[0] == p->vendor[0] &&
  114. v[1] == p->vendor[1] &&
  115. v[2] == p->vendor[2])
  116. return (int)i;
  117. }
  118. return -1;
  119. }
  120. Bool CPU_Is_InOrder()
  121. {
  122. Cx86cpuid p;
  123. int firm;
  124. UInt32 family, model;
  125. if (!x86cpuid_CheckAndRead(&p))
  126. return True;
  127. family = x86cpuid_GetFamily(&p);
  128. model = x86cpuid_GetModel(&p);
  129. firm = x86cpuid_GetFirm(&p);
  130. switch (firm)
  131. {
  132. case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
  133. /* Atom CPU */
  134. model == 0x100C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
  135. || model == 0x2006 /* 45 nm, Z6xx */
  136. || model == 0x2007 /* 32 nm, Z2460 */
  137. || model == 0x3005 /* 32 nm, Z2760 */
  138. || model == 0x3006 /* 32 nm, N2xxx, D2xxx */
  139. )));
  140. case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
  141. case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
  142. }
  143. return True;
  144. }
  145. #if !defined(MY_CPU_AMD64) && defined(_WIN32)
  146. #include <windows.h>
  147. static Bool CPU_Sys_Is_SSE_Supported()
  148. {
  149. OSVERSIONINFO vi;
  150. vi.dwOSVersionInfoSize = sizeof(vi);
  151. if (!GetVersionEx(&vi))
  152. return False;
  153. return (vi.dwMajorVersion >= 5);
  154. }
  155. #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
  156. #else
  157. #define CHECK_SYS_SSE_SUPPORT
  158. #endif
  159. Bool CPU_Is_Aes_Supported()
  160. {
  161. Cx86cpuid p;
  162. CHECK_SYS_SSE_SUPPORT
  163. if (!x86cpuid_CheckAndRead(&p))
  164. return False;
  165. return (p.c >> 25) & 1;
  166. }
  167. #endif