2
0

platformCPU.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. // switch on processor family code
  171. switch ((processor >> 8) & 0xf)
  172. {
  173. // K6 Family
  174. case 5:
  175. // switch on processor model code
  176. switch ((processor >> 4) & 0xf)
  177. {
  178. case 0:
  179. case 1:
  180. case 2:
  181. case 3:
  182. pInfo.type = CPU_AMD_K6_3;
  183. pInfo.name = StringTable->insert("AMD K5");
  184. break;
  185. case 4:
  186. case 5:
  187. case 6:
  188. case 7:
  189. pInfo.type = CPU_AMD_K6;
  190. pInfo.name = StringTable->insert("AMD K6");
  191. break;
  192. case 8:
  193. pInfo.type = CPU_AMD_K6_2;
  194. pInfo.name = StringTable->insert("AMD K6-2");
  195. break;
  196. case 9:
  197. case 10:
  198. case 11:
  199. case 12:
  200. case 13:
  201. case 14:
  202. case 15:
  203. pInfo.type = CPU_AMD_K6_3;
  204. pInfo.name = StringTable->insert("AMD K6-3");
  205. break;
  206. }
  207. break;
  208. // Athlon Family
  209. case 6:
  210. pInfo.type = CPU_AMD_Athlon;
  211. pInfo.name = StringTable->insert("AMD Athlon");
  212. break;
  213. default:
  214. pInfo.type = CPU_AMD_Unknown;
  215. pInfo.name = StringTable->insert("AMD (unknown)");
  216. break;
  217. }
  218. }
  219. //--------------------------------------
  220. else
  221. if (dStricmp(vendor, "CyrixInstead") == 0)
  222. {
  223. switch (processor)
  224. {
  225. case 0x520:
  226. pInfo.type = CPU_Cyrix_6x86;
  227. pInfo.name = StringTable->insert("Cyrix 6x86");
  228. break;
  229. case 0x440:
  230. pInfo.type = CPU_Cyrix_MediaGX;
  231. pInfo.name = StringTable->insert("Cyrix Media GX");
  232. break;
  233. case 0x600:
  234. pInfo.type = CPU_Cyrix_6x86MX;
  235. pInfo.name = StringTable->insert("Cyrix 6x86mx/MII");
  236. break;
  237. case 0x540:
  238. pInfo.type = CPU_Cyrix_GXm;
  239. pInfo.name = StringTable->insert("Cyrix GXm");
  240. break;
  241. default:
  242. pInfo.type = CPU_Cyrix_Unknown;
  243. pInfo.name = StringTable->insert("Cyrix (unknown)");
  244. break;
  245. }
  246. }
  247. // Get multithreading caps.
  248. CPUInfo::EConfig config = CPUInfo::CPUCount( pInfo.numLogicalProcessors, pInfo.numAvailableCores, pInfo.numPhysicalProcessors );
  249. pInfo.isHyperThreaded = CPUInfo::isHyperThreaded( config );
  250. pInfo.isMultiCore = CPUInfo::isMultiCore( config );
  251. // Trigger the signal
  252. Platform::SystemInfoReady.trigger();
  253. }