platformCPU.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "platform/platformCPUCount.h"
  24. #include "core/strings/stringFunctions.h"
  25. #include "core/stringTable.h"
  26. #include "core/util/tSignal.h"
  27. Signal<void(void)> Platform::SystemInfoReady;
  28. enum CPUFlags
  29. {
  30. // EDX Register flags
  31. BIT_FPU = BIT(0),
  32. BIT_RDTSC = BIT(4),
  33. BIT_MMX = BIT(23),
  34. BIT_SSE = BIT(25),
  35. BIT_SSE2 = BIT(26),
  36. BIT_3DNOW = BIT(31),
  37. // These use a different value for comparison than the above flags (ECX Register)
  38. BIT_SSE3 = BIT(0),
  39. BIT_SSE3xt = BIT(9),
  40. BIT_SSE4_1 = BIT(19),
  41. BIT_SSE4_2 = BIT(20),
  42. };
  43. // fill the specified structure with information obtained from asm code
  44. void SetProcessorInfo(Platform::SystemInfo_struct::Processor& pInfo,
  45. char* vendor, U32 processor, U32 properties, U32 properties2)
  46. {
  47. Platform::SystemInfo.processor.properties |= (properties & BIT_FPU) ? CPU_PROP_FPU : 0;
  48. Platform::SystemInfo.processor.properties |= (properties & BIT_RDTSC) ? CPU_PROP_RDTSC : 0;
  49. Platform::SystemInfo.processor.properties |= (properties & BIT_MMX) ? CPU_PROP_MMX : 0;
  50. if (dStricmp(vendor, "GenuineIntel") == 0)
  51. {
  52. pInfo.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0;
  53. pInfo.properties |= (properties & BIT_SSE2) ? CPU_PROP_SSE2 : 0;
  54. pInfo.properties |= (properties2 & BIT_SSE3) ? CPU_PROP_SSE3 : 0;
  55. pInfo.properties |= (properties2 & BIT_SSE3xt) ? CPU_PROP_SSE3xt : 0;
  56. pInfo.properties |= (properties2 & BIT_SSE4_1) ? CPU_PROP_SSE4_1 : 0;
  57. pInfo.properties |= (properties2 & BIT_SSE4_2) ? CPU_PROP_SSE4_2 : 0;
  58. pInfo.type = CPU_Intel_Unknown;
  59. // switch on processor family code
  60. switch ((processor >> 8) & 0x0f)
  61. {
  62. case 4:
  63. pInfo.type = CPU_Intel_486;
  64. pInfo.name = StringTable->insert("Intel 486 class");
  65. break;
  66. // Pentium Family
  67. case 5:
  68. // switch on processor model code
  69. switch ((processor >> 4) & 0xf)
  70. {
  71. case 1:
  72. case 2:
  73. case 3:
  74. pInfo.type = CPU_Intel_Pentium;
  75. pInfo.name = StringTable->insert("Intel Pentium");
  76. break;
  77. case 4:
  78. pInfo.type = CPU_Intel_PentiumMMX;
  79. pInfo.name = StringTable->insert("Intel Pentium MMX");
  80. break;
  81. default:
  82. pInfo.type = CPU_Intel_Pentium;
  83. pInfo.name = StringTable->insert( "Intel (unknown)" );
  84. break;
  85. }
  86. break;
  87. // Pentium Pro/II/II family
  88. case 6:
  89. {
  90. U32 extendedModel = ( processor & 0xf0000 ) >> 16;
  91. // switch on processor model code
  92. switch ((processor >> 4) & 0xf)
  93. {
  94. case 1:
  95. pInfo.type = CPU_Intel_PentiumPro;
  96. pInfo.name = StringTable->insert("Intel Pentium Pro");
  97. break;
  98. case 3:
  99. case 5:
  100. pInfo.type = CPU_Intel_PentiumII;
  101. pInfo.name = StringTable->insert("Intel Pentium II");
  102. break;
  103. case 6:
  104. pInfo.type = CPU_Intel_PentiumCeleron;
  105. pInfo.name = StringTable->insert("Intel Pentium Celeron");
  106. break;
  107. case 7:
  108. case 8:
  109. case 11:
  110. pInfo.type = CPU_Intel_PentiumIII;
  111. pInfo.name = StringTable->insert("Intel Pentium III");
  112. break;
  113. case 0xA:
  114. if( extendedModel == 1)
  115. {
  116. pInfo.type = CPU_Intel_Corei7Xeon;
  117. pInfo.name = StringTable->insert( "Intel Core i7 / Xeon" );
  118. }
  119. else
  120. {
  121. pInfo.type = CPU_Intel_PentiumIII;
  122. pInfo.name = StringTable->insert( "Intel Pentium III Xeon" );
  123. }
  124. break;
  125. case 0xD:
  126. if( extendedModel == 1 )
  127. {
  128. pInfo.type = CPU_Intel_Corei7Xeon;
  129. pInfo.name = StringTable->insert( "Intel Core i7 / Xeon" );
  130. }
  131. else
  132. {
  133. pInfo.type = CPU_Intel_PentiumM;
  134. pInfo.name = StringTable->insert( "Intel Pentium/Celeron M" );
  135. }
  136. break;
  137. case 0xE:
  138. pInfo.type = CPU_Intel_Core;
  139. pInfo.name = StringTable->insert( "Intel Core" );
  140. break;
  141. case 0xF:
  142. pInfo.type = CPU_Intel_Core2;
  143. pInfo.name = StringTable->insert( "Intel Core 2" );
  144. break;
  145. default:
  146. pInfo.type = CPU_Intel_PentiumPro;
  147. pInfo.name = StringTable->insert( "Intel (unknown)" );
  148. break;
  149. }
  150. break;
  151. }
  152. // Pentium4 Family
  153. case 0xf:
  154. pInfo.type = CPU_Intel_Pentium4;
  155. pInfo.name = StringTable->insert( "Intel Pentium 4" );
  156. break;
  157. default:
  158. pInfo.type = CPU_Intel_Unknown;
  159. pInfo.name = StringTable->insert( "Intel (unknown)" );
  160. break;
  161. }
  162. }
  163. //--------------------------------------
  164. else
  165. if (dStricmp(vendor, "AuthenticAMD") == 0)
  166. {
  167. // AthlonXP processors support SSE
  168. pInfo.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0;
  169. pInfo.properties |= ( properties & BIT_SSE2 ) ? CPU_PROP_SSE2 : 0;
  170. pInfo.properties |= (properties & BIT_3DNOW) ? CPU_PROP_3DNOW : 0;
  171. // Phenom and PhenomII support SSE3, SSE4a
  172. pInfo.properties |= ( properties2 & BIT_SSE3 ) ? CPU_PROP_SSE3 : 0;
  173. pInfo.properties |= ( properties2 & BIT_SSE4_1 ) ? CPU_PROP_SSE4_1 : 0;
  174. // switch on processor family code
  175. switch ((processor >> 8) & 0xf)
  176. {
  177. // K6 Family
  178. case 5:
  179. // switch on processor model code
  180. switch ((processor >> 4) & 0xf)
  181. {
  182. case 0:
  183. case 1:
  184. case 2:
  185. case 3:
  186. pInfo.type = CPU_AMD_K6_3;
  187. pInfo.name = StringTable->insert("AMD K5");
  188. break;
  189. case 4:
  190. case 5:
  191. case 6:
  192. case 7:
  193. pInfo.type = CPU_AMD_K6;
  194. pInfo.name = StringTable->insert("AMD K6");
  195. break;
  196. case 8:
  197. pInfo.type = CPU_AMD_K6_2;
  198. pInfo.name = StringTable->insert("AMD K6-2");
  199. break;
  200. case 9:
  201. case 10:
  202. case 11:
  203. case 12:
  204. case 13:
  205. case 14:
  206. case 15:
  207. pInfo.type = CPU_AMD_K6_3;
  208. pInfo.name = StringTable->insert("AMD K6-3");
  209. break;
  210. }
  211. break;
  212. // Athlon Family
  213. case 6:
  214. pInfo.type = CPU_AMD_Athlon;
  215. pInfo.name = StringTable->insert("AMD Athlon");
  216. break;
  217. // Phenom Family
  218. case 15:
  219. pInfo.type = CPU_AMD_Phenom;
  220. pInfo.name = StringTable->insert("AMD Phenom");
  221. break;
  222. // Phenom II Family
  223. case 16:
  224. pInfo.type = CPU_AMD_PhenomII;
  225. pInfo.name = StringTable->insert("AMD Phenom II");
  226. break;
  227. // Bulldozer Family
  228. case 17:
  229. pInfo.type = CPU_AMD_Bulldozer;
  230. pInfo.name = StringTable->insert("AMD Bulldozer");
  231. break;
  232. default:
  233. pInfo.type = CPU_AMD_Unknown;
  234. pInfo.name = StringTable->insert("AMD (unknown)");
  235. break;
  236. }
  237. }
  238. //--------------------------------------
  239. else
  240. if (dStricmp(vendor, "CyrixInstead") == 0)
  241. {
  242. switch (processor)
  243. {
  244. case 0x520:
  245. pInfo.type = CPU_Cyrix_6x86;
  246. pInfo.name = StringTable->insert("Cyrix 6x86");
  247. break;
  248. case 0x440:
  249. pInfo.type = CPU_Cyrix_MediaGX;
  250. pInfo.name = StringTable->insert("Cyrix Media GX");
  251. break;
  252. case 0x600:
  253. pInfo.type = CPU_Cyrix_6x86MX;
  254. pInfo.name = StringTable->insert("Cyrix 6x86mx/MII");
  255. break;
  256. case 0x540:
  257. pInfo.type = CPU_Cyrix_GXm;
  258. pInfo.name = StringTable->insert("Cyrix GXm");
  259. break;
  260. default:
  261. pInfo.type = CPU_Cyrix_Unknown;
  262. pInfo.name = StringTable->insert("Cyrix (unknown)");
  263. break;
  264. }
  265. }
  266. // Get multithreading caps.
  267. CPUInfo::EConfig config = CPUInfo::CPUCount( pInfo.numLogicalProcessors, pInfo.numAvailableCores, pInfo.numPhysicalProcessors );
  268. pInfo.isHyperThreaded = CPUInfo::isHyperThreaded( config );
  269. pInfo.isMultiCore = CPUInfo::isMultiCore( config );
  270. // Trigger the signal
  271. Platform::SystemInfoReady.trigger();
  272. }