platformCPU.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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. BIT_FPU = BIT(0),
  31. BIT_RDTSC = BIT(4),
  32. BIT_MMX = BIT(23),
  33. BIT_SSE = BIT(25),
  34. BIT_SSE2 = BIT(26),
  35. BIT_3DNOW = BIT(31),
  36. // These use a different value for comparison than the above flags
  37. BIT_SSE3 = BIT(0),
  38. BIT_SSE3xt = BIT(9),
  39. BIT_SSE4_1 = BIT(19),
  40. BIT_SSE4_2 = BIT(20),
  41. };
  42. // fill the specified structure with information obtained from asm code
  43. void SetProcessorInfo(Platform::SystemInfo_struct::Processor& pInfo,
  44. char* vendor, U32 processor, U32 properties, U32 properties2)
  45. {
  46. Platform::SystemInfo.processor.properties |= (properties & BIT_FPU) ? CPU_PROP_FPU : 0;
  47. Platform::SystemInfo.processor.properties |= (properties & BIT_RDTSC) ? CPU_PROP_RDTSC : 0;
  48. Platform::SystemInfo.processor.properties |= (properties & BIT_MMX) ? CPU_PROP_MMX : 0;
  49. if (dStricmp(vendor, "GenuineIntel") == 0)
  50. {
  51. pInfo.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0;
  52. pInfo.properties |= (properties & BIT_SSE2) ? CPU_PROP_SSE2 : 0;
  53. pInfo.properties |= (properties2 & BIT_SSE3) ? CPU_PROP_SSE3 : 0;
  54. pInfo.properties |= (properties2 & BIT_SSE3xt) ? CPU_PROP_SSE3xt : 0;
  55. pInfo.properties |= (properties2 & BIT_SSE4_1) ? CPU_PROP_SSE4_1 : 0;
  56. pInfo.properties |= (properties2 & BIT_SSE4_2) ? CPU_PROP_SSE4_2 : 0;
  57. pInfo.type = CPU_Intel_Unknown;
  58. // switch on processor family code
  59. switch ((processor >> 8) & 0x0f)
  60. {
  61. case 4:
  62. pInfo.type = CPU_Intel_486;
  63. pInfo.name = StringTable->insert("Intel 486 class");
  64. break;
  65. // Pentium Family
  66. case 5:
  67. // switch on processor model code
  68. switch ((processor >> 4) & 0xf)
  69. {
  70. case 1:
  71. case 2:
  72. case 3:
  73. pInfo.type = CPU_Intel_Pentium;
  74. pInfo.name = StringTable->insert("Intel Pentium");
  75. break;
  76. case 4:
  77. pInfo.type = CPU_Intel_PentiumMMX;
  78. pInfo.name = StringTable->insert("Intel Pentium MMX");
  79. break;
  80. default:
  81. pInfo.type = CPU_Intel_Pentium;
  82. pInfo.name = StringTable->insert( "Intel (unknown)" );
  83. break;
  84. }
  85. break;
  86. // Pentium Pro/II/II family
  87. case 6:
  88. {
  89. U32 extendedModel = ( processor & 0xf0000 ) >> 16;
  90. // switch on processor model code
  91. switch ((processor >> 4) & 0xf)
  92. {
  93. case 1:
  94. pInfo.type = CPU_Intel_PentiumPro;
  95. pInfo.name = StringTable->insert("Intel Pentium Pro");
  96. break;
  97. case 3:
  98. case 5:
  99. pInfo.type = CPU_Intel_PentiumII;
  100. pInfo.name = StringTable->insert("Intel Pentium II");
  101. break;
  102. case 6:
  103. pInfo.type = CPU_Intel_PentiumCeleron;
  104. pInfo.name = StringTable->insert("Intel Pentium Celeron");
  105. break;
  106. case 7:
  107. case 8:
  108. case 11:
  109. pInfo.type = CPU_Intel_PentiumIII;
  110. pInfo.name = StringTable->insert("Intel Pentium III");
  111. break;
  112. case 0xA:
  113. if( extendedModel == 1)
  114. {
  115. pInfo.type = CPU_Intel_Corei7Xeon;
  116. pInfo.name = StringTable->insert( "Intel Core i7 / Xeon" );
  117. }
  118. else
  119. {
  120. pInfo.type = CPU_Intel_PentiumIII;
  121. pInfo.name = StringTable->insert( "Intel Pentium III Xeon" );
  122. }
  123. break;
  124. case 0xD:
  125. if( extendedModel == 1 )
  126. {
  127. pInfo.type = CPU_Intel_Corei7Xeon;
  128. pInfo.name = StringTable->insert( "Intel Core i7 / Xeon" );
  129. }
  130. else
  131. {
  132. pInfo.type = CPU_Intel_PentiumM;
  133. pInfo.name = StringTable->insert( "Intel Pentium/Celeron M" );
  134. }
  135. break;
  136. case 0xE:
  137. pInfo.type = CPU_Intel_Core;
  138. pInfo.name = StringTable->insert( "Intel Core" );
  139. break;
  140. case 0xF:
  141. pInfo.type = CPU_Intel_Core2;
  142. pInfo.name = StringTable->insert( "Intel Core 2" );
  143. break;
  144. default:
  145. pInfo.type = CPU_Intel_PentiumPro;
  146. pInfo.name = StringTable->insert( "Intel (unknown)" );
  147. break;
  148. }
  149. break;
  150. }
  151. // Pentium4 Family
  152. case 0xf:
  153. pInfo.type = CPU_Intel_Pentium4;
  154. pInfo.name = StringTable->insert( "Intel Pentium 4" );
  155. break;
  156. default:
  157. pInfo.type = CPU_Intel_Unknown;
  158. pInfo.name = StringTable->insert( "Intel (unknown)" );
  159. break;
  160. }
  161. }
  162. //--------------------------------------
  163. else
  164. if (dStricmp(vendor, "AuthenticAMD") == 0)
  165. {
  166. // AthlonXP processors support SSE
  167. pInfo.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0;
  168. pInfo.properties |= ( properties & BIT_SSE2 ) ? CPU_PROP_SSE2 : 0;
  169. pInfo.properties |= (properties & BIT_3DNOW) ? CPU_PROP_3DNOW : 0;
  170. // Phenom and PhenomII support SSE3, SSE4a
  171. pInfo.properties |= ( properties2 & BIT_SSE3 ) ? CPU_PROP_SSE3 : 0;
  172. pInfo.properties |= ( properties2 & BIT_SSE4_1 ) ? CPU_PROP_SSE4_1 : 0;
  173. // switch on processor family code
  174. switch ((processor >> 8) & 0xf)
  175. {
  176. // K6 Family
  177. case 5:
  178. // switch on processor model code
  179. switch ((processor >> 4) & 0xf)
  180. {
  181. case 0:
  182. case 1:
  183. case 2:
  184. case 3:
  185. pInfo.type = CPU_AMD_K6_3;
  186. pInfo.name = StringTable->insert("AMD K5");
  187. break;
  188. case 4:
  189. case 5:
  190. case 6:
  191. case 7:
  192. pInfo.type = CPU_AMD_K6;
  193. pInfo.name = StringTable->insert("AMD K6");
  194. break;
  195. case 8:
  196. pInfo.type = CPU_AMD_K6_2;
  197. pInfo.name = StringTable->insert("AMD K6-2");
  198. break;
  199. case 9:
  200. case 10:
  201. case 11:
  202. case 12:
  203. case 13:
  204. case 14:
  205. case 15:
  206. pInfo.type = CPU_AMD_K6_3;
  207. pInfo.name = StringTable->insert("AMD K6-3");
  208. break;
  209. }
  210. break;
  211. // Athlon Family
  212. case 6:
  213. pInfo.type = CPU_AMD_Athlon;
  214. pInfo.name = StringTable->insert("AMD Athlon");
  215. break;
  216. // Phenom Family
  217. case 15:
  218. pInfo.type = CPU_AMD_Phenom;
  219. pInfo.name = StringTable->insert("AMD Phenom");
  220. break;
  221. // Phenom II Family
  222. case 16:
  223. pInfo.type = CPU_AMD_PhenomII;
  224. pInfo.name = StringTable->insert("AMD Phenom II");
  225. break;
  226. // Bulldozer Family
  227. case 17:
  228. pInfo.type = CPU_AMD_Bulldozer;
  229. pInfo.name = StringTable->insert("AMD Bulldozer");
  230. break;
  231. default:
  232. pInfo.type = CPU_AMD_Unknown;
  233. pInfo.name = StringTable->insert("AMD (unknown)");
  234. break;
  235. }
  236. }
  237. //--------------------------------------
  238. else
  239. if (dStricmp(vendor, "CyrixInstead") == 0)
  240. {
  241. switch (processor)
  242. {
  243. case 0x520:
  244. pInfo.type = CPU_Cyrix_6x86;
  245. pInfo.name = StringTable->insert("Cyrix 6x86");
  246. break;
  247. case 0x440:
  248. pInfo.type = CPU_Cyrix_MediaGX;
  249. pInfo.name = StringTable->insert("Cyrix Media GX");
  250. break;
  251. case 0x600:
  252. pInfo.type = CPU_Cyrix_6x86MX;
  253. pInfo.name = StringTable->insert("Cyrix 6x86mx/MII");
  254. break;
  255. case 0x540:
  256. pInfo.type = CPU_Cyrix_GXm;
  257. pInfo.name = StringTable->insert("Cyrix GXm");
  258. break;
  259. default:
  260. pInfo.type = CPU_Cyrix_Unknown;
  261. pInfo.name = StringTable->insert("Cyrix (unknown)");
  262. break;
  263. }
  264. }
  265. // Get multithreading caps.
  266. CPUInfo::EConfig config = CPUInfo::CPUCount( pInfo.numLogicalProcessors, pInfo.numAvailableCores, pInfo.numPhysicalProcessors );
  267. pInfo.isHyperThreaded = CPUInfo::isHyperThreaded( config );
  268. pInfo.isMultiCore = CPUInfo::isMultiCore( config );
  269. // Trigger the signal
  270. Platform::SystemInfoReady.trigger();
  271. }