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.

377 lines
6.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef IA32DETECT_H
  9. #define IA32DETECT_H
  10. #ifdef PLATFORM_WINDOWS_PC
  11. #include <intrin.h>
  12. #endif
  13. /*
  14. This section from http://iss.cs.cornell.edu/ia32.htm
  15. */
  16. typedef unsigned bit;
  17. enum CPUVendor
  18. {
  19. INTEL,
  20. AMD,
  21. UNKNOWN_VENDOR
  22. };
  23. class ia32detect
  24. {
  25. public:
  26. enum type_t
  27. {
  28. type_OEM,
  29. type_OverDrive,
  30. type_Dual,
  31. type_reserved
  32. };
  33. enum brand_t
  34. {
  35. brand_na,
  36. brand_Celeron,
  37. brand_PentiumIII,
  38. brand_PentiumIIIXeon,
  39. brand_reserved1,
  40. brand_reserved2,
  41. brand_PentiumIIIMobile,
  42. brand_reserved3,
  43. brand_Pentium4,
  44. brand_invalid
  45. };
  46. # pragma pack(push, 1)
  47. struct version_t
  48. {
  49. bit Stepping : 4;
  50. bit Model : 4;
  51. bit Family : 4;
  52. bit Type : 2;
  53. bit Reserved1 : 2;
  54. bit XModel : 4;
  55. bit XFamily : 8;
  56. bit Reserved2 : 4;
  57. };
  58. struct misc_t
  59. {
  60. byte Brand;
  61. byte CLFLUSH;
  62. byte Reserved;
  63. byte APICId;
  64. };
  65. struct feature_t
  66. {
  67. bit FPU : 1; // Floating Point Unit On-Chip
  68. bit VME : 1; // Virtual 8086 Mode Enhancements
  69. bit DE : 1; // Debugging Extensions
  70. bit PSE : 1; // Page Size Extensions
  71. bit TSC : 1; // Time Stamp Counter
  72. bit MSR : 1; // Model Specific Registers
  73. bit PAE : 1; // Physical Address Extension
  74. bit MCE : 1; // Machine Check Exception
  75. bit CX8 : 1; // CMPXCHG8 Instruction
  76. bit APIC : 1; // APIC On-Chip
  77. bit Reserved1 : 1;
  78. bit SEP : 1; // SYSENTER and SYSEXIT instructions
  79. bit MTRR : 1; // Memory Type Range Registers
  80. bit PGE : 1; // PTE Global Bit
  81. bit MCA : 1; // Machine Check Architecture
  82. bit CMOV : 1; // Conditional Move Instructions
  83. bit PAT : 1; // Page Attribute Table
  84. bit PSE36 : 1; // 32-bit Page Size Extension
  85. bit PSN : 1; // Processor Serial Number
  86. bit CLFSH : 1; // CLFLUSH Instruction
  87. bit Reserved2 : 1;
  88. bit DS : 1; // Debug Store
  89. bit ACPI : 1; // Thermal Monitor and Software Controlled Clock Facilities
  90. bit MMX : 1; // Intel MMX Technology
  91. bit FXSR : 1; // FXSAVE and FXRSTOR Instructions
  92. bit SSE : 1; // Intel SSE Technology
  93. bit SSE2 : 1; // Intel SSE2 Technology
  94. bit SS : 1; // Self Snoop
  95. bit HTT : 1; // Hyper Threading
  96. bit TM : 1; // Thermal Monitor
  97. bit Reserved3 : 1;
  98. bit PBE : 1; // Pending Brk. EN.
  99. };
  100. # pragma pack(pop)
  101. tstring vendor_name;
  102. CPUVendor vendor;
  103. tstring brand;
  104. version_t version;
  105. misc_t misc;
  106. feature_t feature;
  107. byte *cache;
  108. ia32detect ()
  109. {
  110. cache = 0;
  111. uint32 m = init0();
  112. uint32 *d = new uint32[m * 4];
  113. for (uint32 i = 1; i <= m; i++)
  114. {
  115. #ifdef COMPILER_MSVC64
  116. __cpuid((int *) (d + (i-1) * 4), i);
  117. #else
  118. uint32 *t = d + (i - 1) * 4;
  119. __asm
  120. {
  121. mov eax, i;
  122. mov esi, t;
  123. cpuid;
  124. mov dword ptr [esi + 0x0], eax;
  125. mov dword ptr [esi + 0x4], ebx;
  126. mov dword ptr [esi + 0x8], ecx;
  127. mov dword ptr [esi + 0xC], edx;
  128. }
  129. #endif
  130. }
  131. if (m >= 1)
  132. init1(d);
  133. if (m >= 2)
  134. init2(d[4] & 0xFF);
  135. delete [] d;
  136. init0x80000000();
  137. //-----------------------------------------------------------------------
  138. // Get the vendor of the processor
  139. //-----------------------------------------------------------------------
  140. if (_tcscmp(vendor_name.c_str(), _T("GenuineIntel")) == 0)
  141. {
  142. vendor = INTEL;
  143. }
  144. else if (_tcscmp(vendor_name.c_str(), _T("AuthenticAMD")) == 0)
  145. {
  146. vendor = AMD;
  147. }
  148. else
  149. {
  150. vendor = UNKNOWN_VENDOR;
  151. }
  152. }
  153. const tstring version_text () const
  154. {
  155. tchar b[128];
  156. _stprintf(b, _T("%d.%d.%d %s XVersion(%d.%d)"),
  157. version.Family, version.Model, version.Stepping, type_text(), version.XFamily, version.XModel);
  158. return tstring(b);
  159. }
  160. protected:
  161. const tchar * type_text () const
  162. {
  163. static const tchar *text[] =
  164. {
  165. _T("Intel OEM Processor"),
  166. _T("Intel OverDrive(R) Processor"),
  167. _T("Intel Dual Processor"),
  168. _T("reserved")
  169. };
  170. return text[version.Type];
  171. }
  172. const tstring brand_text () const
  173. {
  174. static const tchar *text[] =
  175. {
  176. _T("n/a"),
  177. _T("Celeron"),
  178. _T("Pentium III"),
  179. _T("Pentium III Xeon"),
  180. _T("reserved (4)"),
  181. _T("reserved (5)"),
  182. _T("Pentium III Mobile"),
  183. _T("reserved (7)"),
  184. _T("Pentium 4")
  185. };
  186. if (misc.Brand < brand_invalid)
  187. return tstring(text[misc.Brand]);
  188. else
  189. {
  190. tchar b[32];
  191. _stprintf(b, _T("Brand %d (Update)"), misc.Brand);
  192. return tstring(b);
  193. }
  194. }
  195. private:
  196. uint32 init0 ()
  197. {
  198. uint32 m;
  199. int data[4 + 1];
  200. tchar * s1;
  201. s1 = (tchar *) &data[1];
  202. __cpuid(data, 0);
  203. data[4] = 0;
  204. // Returns something like this:
  205. // data[0] = 0x0000000b
  206. // data[1] = 0x756e6547 Genu
  207. // data[2] = 0x6c65746e ntel
  208. // data[3] = 0x49656e69 ineI
  209. // data[4] = 0x00000000
  210. m = data[0];
  211. int t = data[2];
  212. data[2] = data[3];
  213. data[3] = t;
  214. vendor_name = s1;
  215. return m;
  216. }
  217. void init1 (uint32 *d)
  218. {
  219. version = *(version_t *)&d[0];
  220. misc = *(misc_t *)&d[1];
  221. feature = *(feature_t *)&d[3];
  222. }
  223. void process2 (uint32 d, bool c[])
  224. {
  225. if ((d & 0x80000000) == 0)
  226. for (int i = 0; i < 32; i += 8)
  227. c[(d >> i) & 0xFF] = true;
  228. }
  229. void init2 (byte count)
  230. {
  231. uint32 d[4];
  232. bool c[256];
  233. for (int ci1 = 0; ci1 < 256; ci1++)
  234. c[ci1] = false;
  235. for (int i = 0; i < count; i++)
  236. {
  237. #ifdef COMPILER_MSVC64
  238. __cpuid((int *) d, 2);
  239. #else
  240. __asm
  241. {
  242. mov eax, 2;
  243. lea esi, d;
  244. cpuid;
  245. mov [esi + 0x0], eax;
  246. mov [esi + 0x4], ebx;
  247. mov [esi + 0x8], ecx;
  248. mov [esi + 0xC], edx;
  249. }
  250. #endif
  251. if (i == 0)
  252. d[0] &= 0xFFFFFF00;
  253. process2(d[0], c);
  254. process2(d[1], c);
  255. process2(d[2], c);
  256. process2(d[3], c);
  257. }
  258. int m = 0;
  259. for (int ci2 = 0; ci2 < 256; ci2++)
  260. if (c[ci2])
  261. m++;
  262. cache = new byte[m];
  263. m = 0;
  264. for (int ci3 = 1; ci3 < 256; ci3++)
  265. if (c[ci3])
  266. cache[m++] = ci3;
  267. cache[m] = 0;
  268. }
  269. void init0x80000000 ()
  270. {
  271. uint32 m;
  272. #ifdef COMPILER_MSVC64
  273. int data[4];
  274. __cpuid(data, 0x80000000);
  275. m = data[0];
  276. #else
  277. __asm
  278. {
  279. mov eax, 0x80000000;
  280. cpuid;
  281. mov m, eax
  282. }
  283. #endif
  284. if ((m & 0x80000000) != 0)
  285. {
  286. uint32 *d = new uint32[(m - 0x80000000) * 4];
  287. for (uint32 i = 0x80000001; i <= m; i++)
  288. {
  289. uint32 *t = d + (i - 0x80000001) * 4;
  290. #ifdef COMPILER_MSVC64
  291. __cpuid((int *) (d + (i - 0x80000001) * 4), i);
  292. #else
  293. __asm
  294. {
  295. mov eax, i;
  296. mov esi, t;
  297. cpuid;
  298. mov dword ptr [esi + 0x0], eax;
  299. mov dword ptr [esi + 0x4], ebx;
  300. mov dword ptr [esi + 0x8], ecx;
  301. mov dword ptr [esi + 0xC], edx;
  302. }
  303. #endif
  304. }
  305. if (m >= 0x80000002)
  306. brand = (tchar *)(d + 4);
  307. // note the assignment to brand above does a copy, we need to delete
  308. delete[] d;
  309. }
  310. }
  311. };
  312. #endif // IA32DETECT_H