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.

383 lines
6.7 KiB

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