You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

cpuid_x86.c 58 kB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497
  1. /*********************************************************************/
  2. /* Copyright 2009, 2010 The University of Texas at Austin. */
  3. /* All rights reserved. */
  4. /* */
  5. /* Redistribution and use in source and binary forms, with or */
  6. /* without modification, are permitted provided that the following */
  7. /* conditions are met: */
  8. /* */
  9. /* 1. Redistributions of source code must retain the above */
  10. /* copyright notice, this list of conditions and the following */
  11. /* disclaimer. */
  12. /* */
  13. /* 2. Redistributions in binary form must reproduce the above */
  14. /* copyright notice, this list of conditions and the following */
  15. /* disclaimer in the documentation and/or other materials */
  16. /* provided with the distribution. */
  17. /* */
  18. /* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF TEXAS AT */
  19. /* AUSTIN ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, */
  20. /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
  21. /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
  22. /* DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT */
  23. /* AUSTIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */
  24. /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
  25. /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */
  26. /* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */
  27. /* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
  28. /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
  29. /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */
  30. /* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
  31. /* POSSIBILITY OF SUCH DAMAGE. */
  32. /* */
  33. /* The views and conclusions contained in the software and */
  34. /* documentation are those of the authors and should not be */
  35. /* interpreted as representing official policies, either expressed */
  36. /* or implied, of The University of Texas at Austin. */
  37. /*********************************************************************/
  38. #include <stdio.h>
  39. #include <string.h>
  40. #include "cpuid.h"
  41. #if defined(_MSC_VER) && !defined(__clang__)
  42. #define C_INLINE __inline
  43. #else
  44. #define C_INLINE inline
  45. #endif
  46. /*
  47. #ifdef NO_AVX
  48. #define CPUTYPE_HASWELL CPUTYPE_NEHALEM
  49. #define CORE_HASWELL CORE_NEHALEM
  50. #define CPUTYPE_SKYLAKEX CPUTYPE_NEHALEM
  51. #define CORE_SKYLAKEX CORE_NEHALEM
  52. #define CPUTYPE_SANDYBRIDGE CPUTYPE_NEHALEM
  53. #define CORE_SANDYBRIDGE CORE_NEHALEM
  54. #define CPUTYPE_BULLDOZER CPUTYPE_BARCELONA
  55. #define CORE_BULLDOZER CORE_BARCELONA
  56. #define CPUTYPE_PILEDRIVER CPUTYPE_BARCELONA
  57. #define CORE_PILEDRIVER CORE_BARCELONA
  58. #endif
  59. */
  60. #if defined(_MSC_VER) && !defined(__clang__)
  61. void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
  62. {
  63. int cpuInfo[4] = {-1};
  64. __cpuid(cpuInfo, op);
  65. *eax = cpuInfo[0];
  66. *ebx = cpuInfo[1];
  67. *ecx = cpuInfo[2];
  68. *edx = cpuInfo[3];
  69. }
  70. void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, int *edx)
  71. {
  72. int cpuInfo[4] = {-1};
  73. __cpuidex(cpuInfo, op, count);
  74. *eax = cpuInfo[0];
  75. *ebx = cpuInfo[1];
  76. *ecx = cpuInfo[2];
  77. *edx = cpuInfo[3];
  78. }
  79. #else
  80. #ifndef CPUIDEMU
  81. #if defined(__APPLE__) && defined(__i386__)
  82. void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx);
  83. void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, int *edx);
  84. #else
  85. static C_INLINE void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx){
  86. #if defined(__i386__) && defined(__PIC__)
  87. __asm__ __volatile__
  88. ("mov %%ebx, %%edi;"
  89. "cpuid;"
  90. "xchgl %%ebx, %%edi;"
  91. : "=a" (*eax), "=D" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op), "c" (0) : "cc");
  92. #else
  93. __asm__ __volatile__
  94. ("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op) , "c" (0) : "cc");
  95. #endif
  96. }
  97. static C_INLINE void cpuid_count(int op, int count ,int *eax, int *ebx, int *ecx, int *edx){
  98. #if defined(__i386__) && defined(__PIC__)
  99. __asm__ __volatile__
  100. ("mov %%ebx, %%edi;"
  101. "cpuid;"
  102. "xchgl %%ebx, %%edi;"
  103. : "=a" (*eax), "=D" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (op), "2" (count) : "cc");
  104. #else
  105. __asm__ __volatile__
  106. ("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (op), "2" (count) : "cc");
  107. #endif
  108. }
  109. #endif
  110. #else
  111. typedef struct {
  112. unsigned int id, a, b, c, d;
  113. } idlist_t;
  114. typedef struct {
  115. char *vendor;
  116. char *name;
  117. int start, stop;
  118. } vendor_t;
  119. extern idlist_t idlist[];
  120. extern vendor_t vendor[];
  121. static int cv = VENDOR;
  122. void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx){
  123. static int current = 0;
  124. int start = vendor[cv].start;
  125. int stop = vendor[cv].stop;
  126. int count = stop - start;
  127. if ((current < start) || (current > stop)) current = start;
  128. while ((count > 0) && (idlist[current].id != op)) {
  129. current ++;
  130. if (current > stop) current = start;
  131. count --;
  132. }
  133. *eax = idlist[current].a;
  134. *ebx = idlist[current].b;
  135. *ecx = idlist[current].c;
  136. *edx = idlist[current].d;
  137. }
  138. void cpuid_count (unsigned int op, unsigned int count, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) {
  139. return cpuid (op, eax, ebx, ecx, edx);
  140. }
  141. #endif
  142. #endif // _MSC_VER
  143. static C_INLINE int have_cpuid(void){
  144. int eax, ebx, ecx, edx;
  145. cpuid(0, &eax, &ebx, &ecx, &edx);
  146. return eax;
  147. }
  148. static C_INLINE int have_excpuid(void){
  149. int eax, ebx, ecx, edx;
  150. cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
  151. return eax & 0xffff;
  152. }
  153. #ifndef NO_AVX
  154. static C_INLINE void xgetbv(int op, int * eax, int * edx){
  155. //Use binary code for xgetbv
  156. #if defined(_MSC_VER) && !defined(__clang__)
  157. *eax = __xgetbv(op);
  158. #else
  159. __asm__ __volatile__
  160. (".byte 0x0f, 0x01, 0xd0": "=a" (*eax), "=d" (*edx) : "c" (op) : "cc");
  161. #endif
  162. }
  163. #endif
  164. int support_avx(){
  165. #ifndef NO_AVX
  166. int eax, ebx, ecx, edx;
  167. int ret=0;
  168. cpuid(1, &eax, &ebx, &ecx, &edx);
  169. if ((ecx & (1 << 28)) != 0 && (ecx & (1 << 27)) != 0 && (ecx & (1 << 26)) != 0){
  170. xgetbv(0, &eax, &edx);
  171. if((eax & 6) == 6){
  172. ret=1; //OS supports saving xmm and ymm registers (6 = (1<<1) | (1<<2))
  173. }
  174. }
  175. return ret;
  176. #else
  177. return 0;
  178. #endif
  179. }
  180. int support_avx2(){
  181. #ifndef NO_AVX2
  182. int eax, ebx, ecx=0, edx;
  183. int ret=0;
  184. if (!support_avx())
  185. return 0;
  186. cpuid(7, &eax, &ebx, &ecx, &edx);
  187. if((ebx & (1<<5)) != 0)
  188. ret=1; //CPU supports AVX2
  189. return ret;
  190. #else
  191. return 0;
  192. #endif
  193. }
  194. int support_avx512(){
  195. #if !defined(NO_AVX) && !defined(NO_AVX512)
  196. int eax, ebx, ecx, edx;
  197. int ret=0;
  198. if (!support_avx())
  199. return 0;
  200. cpuid(7, &eax, &ebx, &ecx, &edx);
  201. if((ebx & (1<<5)) == 0){
  202. ret=0; //cpu does not have avx2 flag
  203. }
  204. if((ebx & (1<<31)) != 0){ //AVX512VL flag
  205. xgetbv(0, &eax, &edx);
  206. if((eax & 0xe0) == 0xe0)
  207. ret=1; //OS supports saving zmm registers
  208. }
  209. return ret;
  210. #else
  211. return 0;
  212. #endif
  213. }
  214. int support_avx512_bf16(){
  215. #if !defined(NO_AVX) && !defined(NO_AVX512)
  216. int eax, ebx, ecx, edx;
  217. int ret=0;
  218. if (!support_avx512())
  219. return 0;
  220. cpuid_count(7, 1, &eax, &ebx, &ecx, &edx);
  221. if((eax & 32) == 32){
  222. ret=1; // CPUID.7.1:EAX[bit 5] indicates whether avx512_bf16 supported or not
  223. }
  224. return ret;
  225. #else
  226. return 0;
  227. #endif
  228. }
  229. #define BIT_AMX_TILE 0x01000000
  230. #define BIT_AMX_BF16 0x00400000
  231. #define BIT_AMX_ENBD 0x00060000
  232. int support_amx_bf16() {
  233. #if !defined(NO_AVX) && !defined(NO_AVX512)
  234. int eax, ebx, ecx, edx;
  235. int ret=0;
  236. if (!support_avx512())
  237. return 0;
  238. // CPUID.7.0:EDX indicates AMX support
  239. cpuid_count(7, 0, &eax, &ebx, &ecx, &edx);
  240. if ((edx & BIT_AMX_TILE) && (edx & BIT_AMX_BF16)) {
  241. // CPUID.D.0:EAX[17:18] indicates AMX enabled
  242. cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
  243. if ((eax & BIT_AMX_ENBD) == BIT_AMX_ENBD)
  244. ret = 1;
  245. }
  246. return ret;
  247. #else
  248. return 0;
  249. #endif
  250. }
  251. int get_vendor(void){
  252. int eax, ebx, ecx, edx;
  253. char vendor[13];
  254. cpuid(0, &eax, &ebx, &ecx, &edx);
  255. *(int *)(&vendor[0]) = ebx;
  256. *(int *)(&vendor[4]) = edx;
  257. *(int *)(&vendor[8]) = ecx;
  258. vendor[12] = (char)0;
  259. if (!strcmp(vendor, "GenuineIntel")) return VENDOR_INTEL;
  260. if (!strcmp(vendor, " UMC UMC UMC")) return VENDOR_UMC;
  261. if (!strcmp(vendor, "AuthenticAMD")) return VENDOR_AMD;
  262. if (!strcmp(vendor, "CyrixInstead")) return VENDOR_CYRIX;
  263. if (!strcmp(vendor, "NexGenDriven")) return VENDOR_NEXGEN;
  264. if (!strcmp(vendor, "CentaurHauls")) return VENDOR_CENTAUR;
  265. if (!strcmp(vendor, " Shanghai ")) return VENDOR_ZHAOXIN;
  266. if (!strcmp(vendor, "RiseRiseRise")) return VENDOR_RISE;
  267. if (!strcmp(vendor, " SiS SiS SiS")) return VENDOR_SIS;
  268. if (!strcmp(vendor, "GenuineTMx86")) return VENDOR_TRANSMETA;
  269. if (!strcmp(vendor, "Geode by NSC")) return VENDOR_NSC;
  270. if (!strcmp(vendor, "HygonGenuine")) return VENDOR_HYGON;
  271. if ((eax == 0) || ((eax & 0x500) != 0)) return VENDOR_INTEL;
  272. return VENDOR_UNKNOWN;
  273. }
  274. int get_cputype(int gettype){
  275. int eax, ebx, ecx, edx;
  276. int extend_family, family;
  277. int extend_model, model;
  278. int type, stepping;
  279. int feature = 0;
  280. cpuid(1, &eax, &ebx, &ecx, &edx);
  281. switch (gettype) {
  282. case GET_EXFAMILY :
  283. return BITMASK(eax, 20, 0xff);
  284. case GET_EXMODEL :
  285. return BITMASK(eax, 16, 0x0f);
  286. case GET_TYPE :
  287. return BITMASK(eax, 12, 0x03);
  288. case GET_FAMILY :
  289. return BITMASK(eax, 8, 0x0f);
  290. case GET_MODEL :
  291. return BITMASK(eax, 4, 0x0f);
  292. case GET_APICID :
  293. return BITMASK(ebx, 24, 0x0f);
  294. case GET_LCOUNT :
  295. return BITMASK(ebx, 16, 0x0f);
  296. case GET_CHUNKS :
  297. return BITMASK(ebx, 8, 0x0f);
  298. case GET_STEPPING :
  299. return BITMASK(eax, 0, 0x0f);
  300. case GET_BLANDID :
  301. return BITMASK(ebx, 0, 0xff);
  302. case GET_NUMSHARE :
  303. if (have_cpuid() < 4) return 0;
  304. cpuid(4, &eax, &ebx, &ecx, &edx);
  305. return BITMASK(eax, 14, 0xfff);
  306. case GET_NUMCORES :
  307. if (have_cpuid() < 4) return 0;
  308. cpuid(4, &eax, &ebx, &ecx, &edx);
  309. return BITMASK(eax, 26, 0x3f);
  310. case GET_FEATURE :
  311. if ((edx & (1 << 3)) != 0) feature |= HAVE_PSE;
  312. if ((edx & (1 << 15)) != 0) feature |= HAVE_CMOV;
  313. if ((edx & (1 << 19)) != 0) feature |= HAVE_CFLUSH;
  314. if ((edx & (1 << 23)) != 0) feature |= HAVE_MMX;
  315. if ((edx & (1 << 25)) != 0) feature |= HAVE_SSE;
  316. if ((edx & (1 << 26)) != 0) feature |= HAVE_SSE2;
  317. if ((edx & (1 << 27)) != 0) {
  318. if (BITMASK(ebx, 16, 0x0f) > 0) feature |= HAVE_HIT;
  319. }
  320. if ((ecx & (1 << 0)) != 0) feature |= HAVE_SSE3;
  321. if ((ecx & (1 << 9)) != 0) feature |= HAVE_SSSE3;
  322. if ((ecx & (1 << 19)) != 0) feature |= HAVE_SSE4_1;
  323. if ((ecx & (1 << 20)) != 0) feature |= HAVE_SSE4_2;
  324. #ifndef NO_AVX
  325. if (support_avx()) feature |= HAVE_AVX;
  326. if (support_avx2()) feature |= HAVE_AVX2;
  327. if (support_avx512()) feature |= HAVE_AVX512VL;
  328. if (support_avx512_bf16()) feature |= HAVE_AVX512BF16;
  329. if (support_amx_bf16()) feature |= HAVE_AMXBF16;
  330. if ((ecx & (1 << 12)) != 0) feature |= HAVE_FMA3;
  331. #endif
  332. if (have_excpuid() >= 0x01) {
  333. cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
  334. if ((ecx & (1 << 6)) != 0) feature |= HAVE_SSE4A;
  335. if ((ecx & (1 << 7)) != 0) feature |= HAVE_MISALIGNSSE;
  336. #ifndef NO_AVX
  337. if ((ecx & (1 << 16)) != 0) feature |= HAVE_FMA4;
  338. #endif
  339. if ((edx & (1 << 30)) != 0) feature |= HAVE_3DNOWEX;
  340. if ((edx & (1 << 31)) != 0) feature |= HAVE_3DNOW;
  341. }
  342. if (have_excpuid() >= 0x1a) {
  343. cpuid(0x8000001a, &eax, &ebx, &ecx, &edx);
  344. if ((eax & (1 << 0)) != 0) feature |= HAVE_128BITFPU;
  345. if ((eax & (1 << 1)) != 0) feature |= HAVE_FASTMOVU;
  346. }
  347. }
  348. return feature;
  349. }
  350. int get_cacheinfo(int type, cache_info_t *cacheinfo){
  351. int eax, ebx, ecx, edx, cpuid_level;
  352. int info[15];
  353. int i;
  354. cache_info_t LC1, LD1, L2, L3,
  355. ITB, DTB, LITB, LDTB,
  356. L2ITB, L2DTB, L2LITB, L2LDTB;
  357. LC1.size = 0; LC1.associative = 0; LC1.linesize = 0; LC1.shared = 0;
  358. LD1.size = 0; LD1.associative = 0; LD1.linesize = 0; LD1.shared = 0;
  359. L2.size = 0; L2.associative = 0; L2.linesize = 0; L2.shared = 0;
  360. L3.size = 0; L3.associative = 0; L3.linesize = 0; L3.shared = 0;
  361. ITB.size = 0; ITB.associative = 0; ITB.linesize = 0; ITB.shared = 0;
  362. DTB.size = 0; DTB.associative = 0; DTB.linesize = 0; DTB.shared = 0;
  363. LITB.size = 0; LITB.associative = 0; LITB.linesize = 0; LITB.shared = 0;
  364. LDTB.size = 0; LDTB.associative = 0; LDTB.linesize = 0; LDTB.shared = 0;
  365. L2ITB.size = 0; L2ITB.associative = 0; L2ITB.linesize = 0; L2ITB.shared = 0;
  366. L2DTB.size = 0; L2DTB.associative = 0; L2DTB.linesize = 0; L2DTB.shared = 0;
  367. L2LITB.size = 0; L2LITB.associative = 0; L2LITB.linesize = 0; L2LITB.shared = 0;
  368. L2LDTB.size = 0; L2LDTB.associative = 0; L2LDTB.linesize = 0; L2LDTB.shared = 0;
  369. cpuid(0, &cpuid_level, &ebx, &ecx, &edx);
  370. if (cpuid_level > 1) {
  371. int numcalls =0 ;
  372. cpuid(2, &eax, &ebx, &ecx, &edx);
  373. numcalls = BITMASK(eax, 0, 0xff); //FIXME some systems may require repeated calls to read all entries
  374. info[ 0] = BITMASK(eax, 8, 0xff);
  375. info[ 1] = BITMASK(eax, 16, 0xff);
  376. info[ 2] = BITMASK(eax, 24, 0xff);
  377. info[ 3] = BITMASK(ebx, 0, 0xff);
  378. info[ 4] = BITMASK(ebx, 8, 0xff);
  379. info[ 5] = BITMASK(ebx, 16, 0xff);
  380. info[ 6] = BITMASK(ebx, 24, 0xff);
  381. info[ 7] = BITMASK(ecx, 0, 0xff);
  382. info[ 8] = BITMASK(ecx, 8, 0xff);
  383. info[ 9] = BITMASK(ecx, 16, 0xff);
  384. info[10] = BITMASK(ecx, 24, 0xff);
  385. info[11] = BITMASK(edx, 0, 0xff);
  386. info[12] = BITMASK(edx, 8, 0xff);
  387. info[13] = BITMASK(edx, 16, 0xff);
  388. info[14] = BITMASK(edx, 24, 0xff);
  389. for (i = 0; i < 15; i++){
  390. switch (info[i]){
  391. /* This table is from http://www.sandpile.org/ia32/cpuid.htm */
  392. case 0x01 :
  393. ITB.size = 4;
  394. ITB.associative = 4;
  395. ITB.linesize = 32;
  396. break;
  397. case 0x02 :
  398. LITB.size = 4096;
  399. LITB.associative = 0;
  400. LITB.linesize = 2;
  401. break;
  402. case 0x03 :
  403. DTB.size = 4;
  404. DTB.associative = 4;
  405. DTB.linesize = 64;
  406. break;
  407. case 0x04 :
  408. LDTB.size = 4096;
  409. LDTB.associative = 4;
  410. LDTB.linesize = 8;
  411. break;
  412. case 0x05 :
  413. LDTB.size = 4096;
  414. LDTB.associative = 4;
  415. LDTB.linesize = 32;
  416. break;
  417. case 0x06 :
  418. LC1.size = 8;
  419. LC1.associative = 4;
  420. LC1.linesize = 32;
  421. break;
  422. case 0x08 :
  423. LC1.size = 16;
  424. LC1.associative = 4;
  425. LC1.linesize = 32;
  426. break;
  427. case 0x09 :
  428. LC1.size = 32;
  429. LC1.associative = 4;
  430. LC1.linesize = 64;
  431. break;
  432. case 0x0a :
  433. LD1.size = 8;
  434. LD1.associative = 2;
  435. LD1.linesize = 32;
  436. break;
  437. case 0x0c :
  438. LD1.size = 16;
  439. LD1.associative = 4;
  440. LD1.linesize = 32;
  441. break;
  442. case 0x0d :
  443. LD1.size = 16;
  444. LD1.associative = 4;
  445. LD1.linesize = 64;
  446. break;
  447. case 0x0e :
  448. LD1.size = 24;
  449. LD1.associative = 6;
  450. LD1.linesize = 64;
  451. break;
  452. case 0x10 :
  453. LD1.size = 16;
  454. LD1.associative = 4;
  455. LD1.linesize = 32;
  456. break;
  457. case 0x15 :
  458. LC1.size = 16;
  459. LC1.associative = 4;
  460. LC1.linesize = 32;
  461. break;
  462. case 0x1a :
  463. L2.size = 96;
  464. L2.associative = 6;
  465. L2.linesize = 64;
  466. break;
  467. case 0x21 :
  468. L2.size = 256;
  469. L2.associative = 8;
  470. L2.linesize = 64;
  471. break;
  472. case 0x22 :
  473. L3.size = 512;
  474. L3.associative = 4;
  475. L3.linesize = 64;
  476. break;
  477. case 0x23 :
  478. L3.size = 1024;
  479. L3.associative = 8;
  480. L3.linesize = 64;
  481. break;
  482. case 0x25 :
  483. L3.size = 2048;
  484. L3.associative = 8;
  485. L3.linesize = 64;
  486. break;
  487. case 0x29 :
  488. L3.size = 4096;
  489. L3.associative = 8;
  490. L3.linesize = 64;
  491. break;
  492. case 0x2c :
  493. LD1.size = 32;
  494. LD1.associative = 8;
  495. LD1.linesize = 64;
  496. break;
  497. case 0x30 :
  498. LC1.size = 32;
  499. LC1.associative = 8;
  500. LC1.linesize = 64;
  501. break;
  502. case 0x39 :
  503. L2.size = 128;
  504. L2.associative = 4;
  505. L2.linesize = 64;
  506. break;
  507. case 0x3a :
  508. L2.size = 192;
  509. L2.associative = 6;
  510. L2.linesize = 64;
  511. break;
  512. case 0x3b :
  513. L2.size = 128;
  514. L2.associative = 2;
  515. L2.linesize = 64;
  516. break;
  517. case 0x3c :
  518. L2.size = 256;
  519. L2.associative = 4;
  520. L2.linesize = 64;
  521. break;
  522. case 0x3d :
  523. L2.size = 384;
  524. L2.associative = 6;
  525. L2.linesize = 64;
  526. break;
  527. case 0x3e :
  528. L2.size = 512;
  529. L2.associative = 4;
  530. L2.linesize = 64;
  531. break;
  532. case 0x41 :
  533. L2.size = 128;
  534. L2.associative = 4;
  535. L2.linesize = 32;
  536. break;
  537. case 0x42 :
  538. L2.size = 256;
  539. L2.associative = 4;
  540. L2.linesize = 32;
  541. break;
  542. case 0x43 :
  543. L2.size = 512;
  544. L2.associative = 4;
  545. L2.linesize = 32;
  546. break;
  547. case 0x44 :
  548. L2.size = 1024;
  549. L2.associative = 4;
  550. L2.linesize = 32;
  551. break;
  552. case 0x45 :
  553. L2.size = 2048;
  554. L2.associative = 4;
  555. L2.linesize = 32;
  556. break;
  557. case 0x46 :
  558. L3.size = 4096;
  559. L3.associative = 4;
  560. L3.linesize = 64;
  561. break;
  562. case 0x47 :
  563. L3.size = 8192;
  564. L3.associative = 8;
  565. L3.linesize = 64;
  566. break;
  567. case 0x48 :
  568. L2.size = 3184;
  569. L2.associative = 12;
  570. L2.linesize = 64;
  571. break;
  572. case 0x49 :
  573. if ((get_cputype(GET_FAMILY) == 0x0f) && (get_cputype(GET_MODEL) == 0x06)) {
  574. L3.size = 4096;
  575. L3.associative = 16;
  576. L3.linesize = 64;
  577. } else {
  578. L2.size = 4096;
  579. L2.associative = 16;
  580. L2.linesize = 64;
  581. }
  582. break;
  583. case 0x4a :
  584. L3.size = 6144;
  585. L3.associative = 12;
  586. L3.linesize = 64;
  587. break;
  588. case 0x4b :
  589. L3.size = 8192;
  590. L3.associative = 16;
  591. L3.linesize = 64;
  592. break;
  593. case 0x4c :
  594. L3.size = 12280;
  595. L3.associative = 12;
  596. L3.linesize = 64;
  597. break;
  598. case 0x4d :
  599. L3.size = 16384;
  600. L3.associative = 16;
  601. L3.linesize = 64;
  602. break;
  603. case 0x4e :
  604. L2.size = 6144;
  605. L2.associative = 24;
  606. L2.linesize = 64;
  607. break;
  608. case 0x4f :
  609. ITB.size = 4;
  610. ITB.associative = 0;
  611. ITB.linesize = 32;
  612. break;
  613. case 0x50 :
  614. ITB.size = 4;
  615. ITB.associative = 0;
  616. ITB.linesize = 64;
  617. LITB.size = 4096;
  618. LITB.associative = 0;
  619. LITB.linesize = 64;
  620. LITB.shared = 1;
  621. break;
  622. case 0x51 :
  623. ITB.size = 4;
  624. ITB.associative = 0;
  625. ITB.linesize = 128;
  626. LITB.size = 4096;
  627. LITB.associative = 0;
  628. LITB.linesize = 128;
  629. LITB.shared = 1;
  630. break;
  631. case 0x52 :
  632. ITB.size = 4;
  633. ITB.associative = 0;
  634. ITB.linesize = 256;
  635. LITB.size = 4096;
  636. LITB.associative = 0;
  637. LITB.linesize = 256;
  638. LITB.shared = 1;
  639. break;
  640. case 0x55 :
  641. LITB.size = 4096;
  642. LITB.associative = 0;
  643. LITB.linesize = 7;
  644. LITB.shared = 1;
  645. break;
  646. case 0x56 :
  647. LDTB.size = 4096;
  648. LDTB.associative = 4;
  649. LDTB.linesize = 16;
  650. break;
  651. case 0x57 :
  652. LDTB.size = 4096;
  653. LDTB.associative = 4;
  654. LDTB.linesize = 16;
  655. break;
  656. case 0x5b :
  657. DTB.size = 4;
  658. DTB.associative = 0;
  659. DTB.linesize = 64;
  660. LDTB.size = 4096;
  661. LDTB.associative = 0;
  662. LDTB.linesize = 64;
  663. LDTB.shared = 1;
  664. break;
  665. case 0x5c :
  666. DTB.size = 4;
  667. DTB.associative = 0;
  668. DTB.linesize = 128;
  669. LDTB.size = 4096;
  670. LDTB.associative = 0;
  671. LDTB.linesize = 128;
  672. LDTB.shared = 1;
  673. break;
  674. case 0x5d :
  675. DTB.size = 4;
  676. DTB.associative = 0;
  677. DTB.linesize = 256;
  678. LDTB.size = 4096;
  679. LDTB.associative = 0;
  680. LDTB.linesize = 256;
  681. LDTB.shared = 1;
  682. break;
  683. case 0x60 :
  684. LD1.size = 16;
  685. LD1.associative = 8;
  686. LD1.linesize = 64;
  687. break;
  688. case 0x63 :
  689. DTB.size = 2048;
  690. DTB.associative = 4;
  691. DTB.linesize = 32;
  692. LDTB.size = 4096;
  693. LDTB.associative= 4;
  694. LDTB.linesize = 32;
  695. break;
  696. case 0x66 :
  697. LD1.size = 8;
  698. LD1.associative = 4;
  699. LD1.linesize = 64;
  700. break;
  701. case 0x67 :
  702. LD1.size = 16;
  703. LD1.associative = 4;
  704. LD1.linesize = 64;
  705. break;
  706. case 0x68 :
  707. LD1.size = 32;
  708. LD1.associative = 4;
  709. LD1.linesize = 64;
  710. break;
  711. case 0x70 :
  712. LC1.size = 12;
  713. LC1.associative = 8;
  714. break;
  715. case 0x71 :
  716. LC1.size = 16;
  717. LC1.associative = 8;
  718. break;
  719. case 0x72 :
  720. LC1.size = 32;
  721. LC1.associative = 8;
  722. break;
  723. case 0x73 :
  724. LC1.size = 64;
  725. LC1.associative = 8;
  726. break;
  727. case 0x76 :
  728. ITB.size = 2048;
  729. ITB.associative = 0;
  730. ITB.linesize = 8;
  731. LITB.size = 4096;
  732. LITB.associative= 0;
  733. LITB.linesize = 8;
  734. break;
  735. case 0x77 :
  736. LC1.size = 16;
  737. LC1.associative = 4;
  738. LC1.linesize = 64;
  739. break;
  740. case 0x78 :
  741. L2.size = 1024;
  742. L2.associative = 4;
  743. L2.linesize = 64;
  744. break;
  745. case 0x79 :
  746. L2.size = 128;
  747. L2.associative = 8;
  748. L2.linesize = 64;
  749. break;
  750. case 0x7a :
  751. L2.size = 256;
  752. L2.associative = 8;
  753. L2.linesize = 64;
  754. break;
  755. case 0x7b :
  756. L2.size = 512;
  757. L2.associative = 8;
  758. L2.linesize = 64;
  759. break;
  760. case 0x7c :
  761. L2.size = 1024;
  762. L2.associative = 8;
  763. L2.linesize = 64;
  764. break;
  765. case 0x7d :
  766. L2.size = 2048;
  767. L2.associative = 8;
  768. L2.linesize = 64;
  769. break;
  770. case 0x7e :
  771. L2.size = 256;
  772. L2.associative = 8;
  773. L2.linesize = 128;
  774. break;
  775. case 0x7f :
  776. L2.size = 512;
  777. L2.associative = 2;
  778. L2.linesize = 64;
  779. break;
  780. case 0x81 :
  781. L2.size = 128;
  782. L2.associative = 8;
  783. L2.linesize = 32;
  784. break;
  785. case 0x82 :
  786. L2.size = 256;
  787. L2.associative = 8;
  788. L2.linesize = 32;
  789. break;
  790. case 0x83 :
  791. L2.size = 512;
  792. L2.associative = 8;
  793. L2.linesize = 32;
  794. break;
  795. case 0x84 :
  796. L2.size = 1024;
  797. L2.associative = 8;
  798. L2.linesize = 32;
  799. break;
  800. case 0x85 :
  801. L2.size = 2048;
  802. L2.associative = 8;
  803. L2.linesize = 32;
  804. break;
  805. case 0x86 :
  806. L2.size = 512;
  807. L2.associative = 4;
  808. L2.linesize = 64;
  809. break;
  810. case 0x87 :
  811. L2.size = 1024;
  812. L2.associative = 8;
  813. L2.linesize = 64;
  814. break;
  815. case 0x88 :
  816. L3.size = 2048;
  817. L3.associative = 4;
  818. L3.linesize = 64;
  819. break;
  820. case 0x89 :
  821. L3.size = 4096;
  822. L3.associative = 4;
  823. L3.linesize = 64;
  824. break;
  825. case 0x8a :
  826. L3.size = 8192;
  827. L3.associative = 4;
  828. L3.linesize = 64;
  829. break;
  830. case 0x8d :
  831. L3.size = 3096;
  832. L3.associative = 12;
  833. L3.linesize = 128;
  834. break;
  835. case 0x90 :
  836. ITB.size = 4;
  837. ITB.associative = 0;
  838. ITB.linesize = 64;
  839. break;
  840. case 0x96 :
  841. DTB.size = 4;
  842. DTB.associative = 0;
  843. DTB.linesize = 32;
  844. break;
  845. case 0x9b :
  846. L2DTB.size = 4;
  847. L2DTB.associative = 0;
  848. L2DTB.linesize = 96;
  849. break;
  850. case 0xb0 :
  851. ITB.size = 4;
  852. ITB.associative = 4;
  853. ITB.linesize = 128;
  854. break;
  855. case 0xb1 :
  856. LITB.size = 4096;
  857. LITB.associative = 4;
  858. LITB.linesize = 4;
  859. break;
  860. case 0xb2 :
  861. ITB.size = 4;
  862. ITB.associative = 4;
  863. ITB.linesize = 64;
  864. break;
  865. case 0xb3 :
  866. DTB.size = 4;
  867. DTB.associative = 4;
  868. DTB.linesize = 128;
  869. break;
  870. case 0xb4 :
  871. DTB.size = 4;
  872. DTB.associative = 4;
  873. DTB.linesize = 256;
  874. break;
  875. case 0xba :
  876. DTB.size = 4;
  877. DTB.associative = 4;
  878. DTB.linesize = 64;
  879. break;
  880. case 0xd0 :
  881. L3.size = 512;
  882. L3.associative = 4;
  883. L3.linesize = 64;
  884. break;
  885. case 0xd1 :
  886. L3.size = 1024;
  887. L3.associative = 4;
  888. L3.linesize = 64;
  889. break;
  890. case 0xd2 :
  891. L3.size = 2048;
  892. L3.associative = 4;
  893. L3.linesize = 64;
  894. break;
  895. case 0xd6 :
  896. L3.size = 1024;
  897. L3.associative = 8;
  898. L3.linesize = 64;
  899. break;
  900. case 0xd7 :
  901. L3.size = 2048;
  902. L3.associative = 8;
  903. L3.linesize = 64;
  904. break;
  905. case 0xd8 :
  906. L3.size = 4096;
  907. L3.associative = 8;
  908. L3.linesize = 64;
  909. break;
  910. case 0xdc :
  911. L3.size = 2048;
  912. L3.associative = 12;
  913. L3.linesize = 64;
  914. break;
  915. case 0xdd :
  916. L3.size = 4096;
  917. L3.associative = 12;
  918. L3.linesize = 64;
  919. break;
  920. case 0xde :
  921. L3.size = 8192;
  922. L3.associative = 12;
  923. L3.linesize = 64;
  924. break;
  925. case 0xe2 :
  926. L3.size = 2048;
  927. L3.associative = 16;
  928. L3.linesize = 64;
  929. break;
  930. case 0xe3 :
  931. L3.size = 4096;
  932. L3.associative = 16;
  933. L3.linesize = 64;
  934. break;
  935. case 0xe4 :
  936. L3.size = 8192;
  937. L3.associative = 16;
  938. L3.linesize = 64;
  939. break;
  940. }
  941. }
  942. }
  943. if (get_vendor() == VENDOR_INTEL) {
  944. if(LD1.size<=0 || LC1.size<=0){
  945. //If we didn't detect L1 correctly before,
  946. int count;
  947. for (count=0;count <4;count++) {
  948. cpuid_count(4, count, &eax, &ebx, &ecx, &edx);
  949. switch (eax &0x1f) {
  950. case 0:
  951. continue;
  952. case 1:
  953. case 3:
  954. {
  955. switch ((eax >>5) &0x07)
  956. {
  957. case 1:
  958. {
  959. // fprintf(stderr,"L1 data cache...\n");
  960. int sets = ecx+1;
  961. int lines = (ebx & 0x0fff) +1;
  962. ebx>>=12;
  963. int part = (ebx&0x03ff)+1;
  964. ebx >>=10;
  965. int assoc = (ebx&0x03ff)+1;
  966. LD1.size = (assoc*part*lines*sets)/1024;
  967. LD1.associative = assoc;
  968. LD1.linesize= lines;
  969. break;
  970. }
  971. default:
  972. break;
  973. }
  974. break;
  975. }
  976. case 2:
  977. {
  978. switch ((eax >>5) &0x07)
  979. {
  980. case 1:
  981. {
  982. // fprintf(stderr,"L1 instruction cache...\n");
  983. int sets = ecx+1;
  984. int lines = (ebx & 0x0fff) +1;
  985. ebx>>=12;
  986. int part = (ebx&0x03ff)+1;
  987. ebx >>=10;
  988. int assoc = (ebx&0x03ff)+1;
  989. LC1.size = (assoc*part*lines*sets)/1024;
  990. LC1.associative = assoc;
  991. LC1.linesize= lines;
  992. break;
  993. }
  994. default:
  995. break;
  996. }
  997. break;
  998. }
  999. default:
  1000. break;
  1001. }
  1002. }
  1003. }
  1004. cpuid(0x80000000, &cpuid_level, &ebx, &ecx, &edx);
  1005. if (cpuid_level >= 0x80000006) {
  1006. if(L2.size<=0){
  1007. //If we didn't detect L2 correctly before,
  1008. cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
  1009. L2.size = BITMASK(ecx, 16, 0xffff);
  1010. L2.associative = BITMASK(ecx, 12, 0x0f);
  1011. switch (L2.associative){
  1012. case 0x06:
  1013. L2.associative = 8;
  1014. break;
  1015. case 0x08:
  1016. L2.associative = 16;
  1017. break;
  1018. }
  1019. L2.linesize = BITMASK(ecx, 0, 0xff);
  1020. }
  1021. }
  1022. }
  1023. if ((get_vendor() == VENDOR_AMD) ||
  1024. (get_vendor() == VENDOR_HYGON) ||
  1025. (get_vendor() == VENDOR_CENTAUR) ||
  1026. (get_vendor() == VENDOR_ZHAOXIN)) {
  1027. cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
  1028. LDTB.size = 4096;
  1029. LDTB.associative = BITMASK(eax, 24, 0xff);
  1030. if (LDTB.associative == 0xff) LDTB.associative = 0;
  1031. LDTB.linesize = BITMASK(eax, 16, 0xff);
  1032. LITB.size = 4096;
  1033. LITB.associative = BITMASK(eax, 8, 0xff);
  1034. if (LITB.associative == 0xff) LITB.associative = 0;
  1035. LITB.linesize = BITMASK(eax, 0, 0xff);
  1036. DTB.size = 4;
  1037. DTB.associative = BITMASK(ebx, 24, 0xff);
  1038. if (DTB.associative == 0xff) DTB.associative = 0;
  1039. DTB.linesize = BITMASK(ebx, 16, 0xff);
  1040. ITB.size = 4;
  1041. ITB.associative = BITMASK(ebx, 8, 0xff);
  1042. if (ITB.associative == 0xff) ITB.associative = 0;
  1043. ITB.linesize = BITMASK(ebx, 0, 0xff);
  1044. LD1.size = BITMASK(ecx, 24, 0xff);
  1045. LD1.associative = BITMASK(ecx, 16, 0xff);
  1046. if (LD1.associative == 0xff) LD1.associative = 0;
  1047. LD1.linesize = BITMASK(ecx, 0, 0xff);
  1048. LC1.size = BITMASK(ecx, 24, 0xff);
  1049. LC1.associative = BITMASK(ecx, 16, 0xff);
  1050. if (LC1.associative == 0xff) LC1.associative = 0;
  1051. LC1.linesize = BITMASK(ecx, 0, 0xff);
  1052. cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
  1053. L2LDTB.size = 4096;
  1054. L2LDTB.associative = BITMASK(eax, 24, 0xff);
  1055. if (L2LDTB.associative == 0xff) L2LDTB.associative = 0;
  1056. L2LDTB.linesize = BITMASK(eax, 16, 0xff);
  1057. L2LITB.size = 4096;
  1058. L2LITB.associative = BITMASK(eax, 8, 0xff);
  1059. if (L2LITB.associative == 0xff) L2LITB.associative = 0;
  1060. L2LITB.linesize = BITMASK(eax, 0, 0xff);
  1061. L2DTB.size = 4;
  1062. L2DTB.associative = BITMASK(ebx, 24, 0xff);
  1063. if (L2DTB.associative == 0xff) L2DTB.associative = 0;
  1064. L2DTB.linesize = BITMASK(ebx, 16, 0xff);
  1065. L2ITB.size = 4;
  1066. L2ITB.associative = BITMASK(ebx, 8, 0xff);
  1067. if (L2ITB.associative == 0xff) L2ITB.associative = 0;
  1068. L2ITB.linesize = BITMASK(ebx, 0, 0xff);
  1069. if(L2.size <= 0){
  1070. //If we didn't detect L2 correctly before,
  1071. L2.size = BITMASK(ecx, 16, 0xffff);
  1072. L2.associative = BITMASK(ecx, 12, 0xf);
  1073. switch (L2.associative){
  1074. case 0x06:
  1075. L2.associative = 8;
  1076. break;
  1077. case 0x08:
  1078. L2.associative = 16;
  1079. break;
  1080. }
  1081. if (L2.associative == 0xff) L2.associative = 0;
  1082. L2.linesize = BITMASK(ecx, 0, 0xff);
  1083. }
  1084. L3.size = BITMASK(edx, 18, 0x3fff) * 512;
  1085. L3.associative = BITMASK(edx, 12, 0xf);
  1086. if (L3.associative == 0xff) L2.associative = 0;
  1087. L3.linesize = BITMASK(edx, 0, 0xff);
  1088. }
  1089. switch (type) {
  1090. case CACHE_INFO_L1_I :
  1091. *cacheinfo = LC1;
  1092. break;
  1093. case CACHE_INFO_L1_D :
  1094. *cacheinfo = LD1;
  1095. break;
  1096. case CACHE_INFO_L2 :
  1097. *cacheinfo = L2;
  1098. break;
  1099. case CACHE_INFO_L3 :
  1100. *cacheinfo = L3;
  1101. break;
  1102. case CACHE_INFO_L1_DTB :
  1103. *cacheinfo = DTB;
  1104. break;
  1105. case CACHE_INFO_L1_ITB :
  1106. *cacheinfo = ITB;
  1107. break;
  1108. case CACHE_INFO_L1_LDTB :
  1109. *cacheinfo = LDTB;
  1110. break;
  1111. case CACHE_INFO_L1_LITB :
  1112. *cacheinfo = LITB;
  1113. break;
  1114. case CACHE_INFO_L2_DTB :
  1115. *cacheinfo = L2DTB;
  1116. break;
  1117. case CACHE_INFO_L2_ITB :
  1118. *cacheinfo = L2ITB;
  1119. break;
  1120. case CACHE_INFO_L2_LDTB :
  1121. *cacheinfo = L2LDTB;
  1122. break;
  1123. case CACHE_INFO_L2_LITB :
  1124. *cacheinfo = L2LITB;
  1125. break;
  1126. }
  1127. return 0;
  1128. }
  1129. int get_cpuname(void){
  1130. int family, exfamily, model, vendor, exmodel, stepping;
  1131. if (!have_cpuid()) return CPUTYPE_80386;
  1132. family = get_cputype(GET_FAMILY);
  1133. exfamily = get_cputype(GET_EXFAMILY);
  1134. model = get_cputype(GET_MODEL);
  1135. exmodel = get_cputype(GET_EXMODEL);
  1136. stepping = get_cputype(GET_STEPPING);
  1137. vendor = get_vendor();
  1138. if (vendor == VENDOR_INTEL){
  1139. switch (family) {
  1140. case 0x4:
  1141. return CPUTYPE_80486;
  1142. case 0x5:
  1143. return CPUTYPE_PENTIUM;
  1144. case 0x6:
  1145. switch (exmodel) {
  1146. case 0:
  1147. switch (model) {
  1148. case 1:
  1149. case 3:
  1150. case 5:
  1151. case 6:
  1152. #if defined(__x86_64__) || defined(__amd64__)
  1153. return CPUTYPE_CORE2;
  1154. #else
  1155. return CPUTYPE_PENTIUM2;
  1156. #endif
  1157. case 7:
  1158. case 8:
  1159. case 10:
  1160. case 11:
  1161. return CPUTYPE_PENTIUM3;
  1162. case 9:
  1163. case 13:
  1164. case 14:
  1165. return CPUTYPE_PENTIUMM;
  1166. case 15:
  1167. return CPUTYPE_CORE2;
  1168. }
  1169. break;
  1170. case 1: // family 6 exmodel 1
  1171. switch (model) {
  1172. case 6:
  1173. return CPUTYPE_CORE2;
  1174. case 7:
  1175. return CPUTYPE_PENRYN;
  1176. case 10:
  1177. case 11:
  1178. case 14:
  1179. case 15:
  1180. return CPUTYPE_NEHALEM;
  1181. case 12:
  1182. return CPUTYPE_ATOM;
  1183. case 13:
  1184. return CPUTYPE_DUNNINGTON;
  1185. }
  1186. break;
  1187. case 2: // family 6 exmodel 2
  1188. switch (model) {
  1189. case 5:
  1190. //Intel Core (Clarkdale) / Core (Arrandale)
  1191. // Pentium (Clarkdale) / Pentium Mobile (Arrandale)
  1192. // Xeon (Clarkdale), 32nm
  1193. return CPUTYPE_NEHALEM;
  1194. case 10:
  1195. //Intel Core i5-2000 /i7-2000 (Sandy Bridge)
  1196. if(support_avx())
  1197. return CPUTYPE_SANDYBRIDGE;
  1198. else
  1199. return CPUTYPE_NEHALEM; //OS doesn't support AVX
  1200. case 12:
  1201. //Xeon Processor 5600 (Westmere-EP)
  1202. return CPUTYPE_NEHALEM;
  1203. case 13:
  1204. //Intel Core i7-3000 / Xeon E5 (Sandy Bridge)
  1205. if(support_avx())
  1206. return CPUTYPE_SANDYBRIDGE;
  1207. else
  1208. return CPUTYPE_NEHALEM;
  1209. case 14:
  1210. // Xeon E7540
  1211. case 15:
  1212. //Xeon Processor E7 (Westmere-EX)
  1213. return CPUTYPE_NEHALEM;
  1214. }
  1215. break;
  1216. case 3: // family 6 exmodel 3
  1217. switch (model) {
  1218. case 7:
  1219. // Bay Trail
  1220. return CPUTYPE_ATOM;
  1221. case 10:
  1222. case 14:
  1223. // Ivy Bridge
  1224. if(support_avx())
  1225. return CPUTYPE_SANDYBRIDGE;
  1226. else
  1227. return CPUTYPE_NEHALEM;
  1228. case 12:
  1229. case 15:
  1230. if(support_avx2())
  1231. return CPUTYPE_HASWELL;
  1232. if(support_avx())
  1233. return CPUTYPE_SANDYBRIDGE;
  1234. else
  1235. return CPUTYPE_NEHALEM;
  1236. case 13:
  1237. //Broadwell
  1238. if(support_avx2())
  1239. return CPUTYPE_HASWELL;
  1240. if(support_avx())
  1241. return CPUTYPE_SANDYBRIDGE;
  1242. else
  1243. return CPUTYPE_NEHALEM;
  1244. }
  1245. break;
  1246. case 4: // family 6 exmodel 4
  1247. switch (model) {
  1248. case 5:
  1249. case 6:
  1250. if(support_avx2())
  1251. return CPUTYPE_HASWELL;
  1252. if(support_avx())
  1253. return CPUTYPE_SANDYBRIDGE;
  1254. else
  1255. return CPUTYPE_NEHALEM;
  1256. case 7:
  1257. case 15:
  1258. //Broadwell
  1259. if(support_avx2())
  1260. return CPUTYPE_HASWELL;
  1261. if(support_avx())
  1262. return CPUTYPE_SANDYBRIDGE;
  1263. else
  1264. return CPUTYPE_NEHALEM;
  1265. case 14:
  1266. //Skylake
  1267. if(support_avx2())
  1268. return CPUTYPE_HASWELL;
  1269. if(support_avx())
  1270. return CPUTYPE_SANDYBRIDGE;
  1271. else
  1272. return CPUTYPE_NEHALEM;
  1273. case 12:
  1274. // Braswell
  1275. case 13:
  1276. // Avoton
  1277. return CPUTYPE_NEHALEM;
  1278. }
  1279. break;
  1280. case 5: // family 6 exmodel 5
  1281. switch (model) {
  1282. case 6:
  1283. //Broadwell
  1284. if(support_avx2())
  1285. return CPUTYPE_HASWELL;
  1286. if(support_avx())
  1287. return CPUTYPE_SANDYBRIDGE;
  1288. else
  1289. return CPUTYPE_NEHALEM;
  1290. case 5:
  1291. // Skylake X
  1292. if(support_avx512_bf16())
  1293. return CPUTYPE_COOPERLAKE;
  1294. if(support_avx512())
  1295. return CPUTYPE_SKYLAKEX;
  1296. if(support_avx2())
  1297. return CPUTYPE_HASWELL;
  1298. if(support_avx())
  1299. return CPUTYPE_SANDYBRIDGE;
  1300. else
  1301. return CPUTYPE_NEHALEM;
  1302. case 14:
  1303. // Skylake
  1304. if(support_avx2())
  1305. return CPUTYPE_HASWELL;
  1306. if(support_avx())
  1307. return CPUTYPE_SANDYBRIDGE;
  1308. else
  1309. return CPUTYPE_NEHALEM;
  1310. case 7:
  1311. // Xeon Phi Knights Landing
  1312. if(support_avx2())
  1313. return CPUTYPE_HASWELL;
  1314. if(support_avx())
  1315. return CPUTYPE_SANDYBRIDGE;
  1316. else
  1317. return CPUTYPE_NEHALEM;
  1318. case 12:
  1319. // Apollo Lake
  1320. case 15:
  1321. // Denverton
  1322. return CPUTYPE_NEHALEM;
  1323. }
  1324. break;
  1325. case 6: // family 6 exmodel 6
  1326. switch (model) {
  1327. case 6: // Cannon Lake
  1328. if(support_avx512())
  1329. return CPUTYPE_SKYLAKEX;
  1330. if(support_avx2())
  1331. return CPUTYPE_HASWELL;
  1332. if(support_avx())
  1333. return CPUTYPE_SANDYBRIDGE;
  1334. else
  1335. return CPUTYPE_NEHALEM;
  1336. case 10: // Ice Lake SP
  1337. if(support_avx512_bf16())
  1338. return CPUTYPE_COOPERLAKE;
  1339. if(support_avx512())
  1340. return CPUTYPE_SKYLAKEX;
  1341. if(support_avx2())
  1342. return CPUTYPE_HASWELL;
  1343. if(support_avx())
  1344. return CPUTYPE_SANDYBRIDGE;
  1345. else
  1346. return CPUTYPE_NEHALEM;
  1347. }
  1348. break;
  1349. case 7: // family 6 exmodel 7
  1350. switch (model) {
  1351. case 10: // Goldmont Plus
  1352. return CPUTYPE_NEHALEM;
  1353. case 14: // Ice Lake
  1354. if(support_avx512())
  1355. return CPUTYPE_SKYLAKEX;
  1356. if(support_avx2())
  1357. return CPUTYPE_HASWELL;
  1358. if(support_avx())
  1359. return CPUTYPE_SANDYBRIDGE;
  1360. else
  1361. return CPUTYPE_NEHALEM;
  1362. }
  1363. break;
  1364. case 9:
  1365. case 8:
  1366. switch (model) {
  1367. case 12: // Tiger Lake
  1368. case 13: // Tiger Lake (11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz)
  1369. if(support_avx512())
  1370. return CPUTYPE_SKYLAKEX;
  1371. if(support_avx2())
  1372. return CPUTYPE_HASWELL;
  1373. if(support_avx())
  1374. return CPUTYPE_SANDYBRIDGE;
  1375. else
  1376. return CPUTYPE_NEHALEM;
  1377. case 14: // Kaby Lake and refreshes
  1378. if(support_avx2())
  1379. return CPUTYPE_HASWELL;
  1380. if(support_avx())
  1381. return CPUTYPE_SANDYBRIDGE;
  1382. else
  1383. return CPUTYPE_NEHALEM;
  1384. }
  1385. case 10: //family 6 exmodel 10
  1386. switch (model) {
  1387. case 5: // Comet Lake H and S
  1388. case 6: // Comet Lake U
  1389. if(support_avx2())
  1390. return CPUTYPE_HASWELL;
  1391. if(support_avx())
  1392. return CPUTYPE_SANDYBRIDGE;
  1393. else
  1394. return CPUTYPE_NEHALEM;
  1395. case 7: // Rocket Lake
  1396. if(support_avx512())
  1397. return CPUTYPE_SKYLAKEX;
  1398. if(support_avx2())
  1399. return CPUTYPE_HASWELL;
  1400. if(support_avx())
  1401. return CPUTYPE_SANDYBRIDGE;
  1402. else
  1403. return CPUTYPE_NEHALEM;
  1404. }
  1405. break;
  1406. }
  1407. break;
  1408. case 0x7:
  1409. return CPUTYPE_ITANIUM;
  1410. case 0xf:
  1411. switch (exfamily) {
  1412. case 0 :
  1413. return CPUTYPE_PENTIUM4;
  1414. case 1 :
  1415. return CPUTYPE_ITANIUM;
  1416. }
  1417. break;
  1418. }
  1419. return CPUTYPE_INTEL_UNKNOWN;
  1420. }
  1421. if (vendor == VENDOR_AMD){
  1422. switch (family) {
  1423. case 0x4:
  1424. return CPUTYPE_AMD5X86;
  1425. case 0x5:
  1426. return CPUTYPE_AMDK6;
  1427. case 0x6:
  1428. #if defined(__x86_64__) || defined(__amd64__)
  1429. return CPUTYPE_BARCELONA;
  1430. #else
  1431. return CPUTYPE_ATHLON;
  1432. #endif
  1433. case 0xf:
  1434. switch (exfamily) {
  1435. case 0:
  1436. case 2:
  1437. return CPUTYPE_OPTERON;
  1438. case 1:
  1439. case 3:
  1440. // case 7:
  1441. // case 10:
  1442. return CPUTYPE_BARCELONA;
  1443. case 5:
  1444. case 7:
  1445. return CPUTYPE_BOBCAT;
  1446. case 6:
  1447. switch (model) {
  1448. case 1:
  1449. //AMD Bulldozer Opteron 6200 / Opteron 4200 / AMD FX-Series
  1450. if(support_avx())
  1451. return CPUTYPE_BULLDOZER;
  1452. else
  1453. return CPUTYPE_BARCELONA; //OS don't support AVX.
  1454. case 2: //AMD Piledriver
  1455. case 3: //AMD Richland
  1456. if(support_avx())
  1457. return CPUTYPE_PILEDRIVER;
  1458. else
  1459. return CPUTYPE_BARCELONA; //OS don't support AVX.
  1460. case 5: // New EXCAVATOR CPUS
  1461. if(support_avx())
  1462. return CPUTYPE_EXCAVATOR;
  1463. else
  1464. return CPUTYPE_BARCELONA; //OS don't support AVX.
  1465. case 0:
  1466. case 8:
  1467. switch(exmodel){
  1468. case 1: //AMD Trinity
  1469. if(support_avx())
  1470. return CPUTYPE_PILEDRIVER;
  1471. else
  1472. return CPUTYPE_BARCELONA; //OS don't support AVX.
  1473. case 3:
  1474. if(support_avx())
  1475. return CPUTYPE_STEAMROLLER;
  1476. else
  1477. return CPUTYPE_BARCELONA; //OS don't support AVX.
  1478. case 6:
  1479. if(support_avx())
  1480. return CPUTYPE_EXCAVATOR;
  1481. else
  1482. return CPUTYPE_BARCELONA; //OS don't support AVX.
  1483. }
  1484. break;
  1485. }
  1486. break;
  1487. case 8:
  1488. switch (model) {
  1489. case 1:
  1490. // AMD Ryzen
  1491. case 8:
  1492. // AMD Ryzen2
  1493. default:
  1494. // Matisse/Renoir and other recent Ryzen2
  1495. if(support_avx())
  1496. #ifndef NO_AVX2
  1497. return CPUTYPE_ZEN;
  1498. #else
  1499. return CPUTYPE_SANDYBRIDGE; // Zen is closer in architecture to Sandy Bridge than to Excavator
  1500. #endif
  1501. else
  1502. return CPUTYPE_BARCELONA;
  1503. }
  1504. break;
  1505. case 10: // Zen3
  1506. if(support_avx())
  1507. #ifndef NO_AVX2
  1508. return CPUTYPE_ZEN;
  1509. #else
  1510. return CPUTYPE_SANDYBRIDGE; // Zen is closer in architecture to Sandy Bridge than to Excavator
  1511. #endif
  1512. else
  1513. return CPUTYPE_BARCELONA;
  1514. }
  1515. break;
  1516. }
  1517. return CPUTYPE_AMD_UNKNOWN;
  1518. }
  1519. if (vendor == VENDOR_HYGON){
  1520. switch (family) {
  1521. case 0xf:
  1522. switch (exfamily) {
  1523. case 9:
  1524. //Hygon Dhyana
  1525. if(support_avx())
  1526. #ifndef NO_AVX2
  1527. return CPUTYPE_ZEN;
  1528. #else
  1529. return CPUTYPE_SANDYBRIDGE; // closer in architecture to Sandy Bridge than to Excavator
  1530. #endif
  1531. else
  1532. return CPUTYPE_BARCELONA;
  1533. }
  1534. break;
  1535. }
  1536. return CPUTYPE_HYGON_UNKNOWN;
  1537. }
  1538. if (vendor == VENDOR_CYRIX){
  1539. switch (family) {
  1540. case 0x4:
  1541. return CPUTYPE_CYRIX5X86;
  1542. case 0x5:
  1543. return CPUTYPE_CYRIXM1;
  1544. case 0x6:
  1545. return CPUTYPE_CYRIXM2;
  1546. }
  1547. return CPUTYPE_CYRIX_UNKNOWN;
  1548. }
  1549. if (vendor == VENDOR_NEXGEN){
  1550. switch (family) {
  1551. case 0x5:
  1552. return CPUTYPE_NEXGENNX586;
  1553. }
  1554. return CPUTYPE_NEXGEN_UNKNOWN;
  1555. }
  1556. if (vendor == VENDOR_CENTAUR){
  1557. switch (family) {
  1558. case 0x5:
  1559. return CPUTYPE_CENTAURC6;
  1560. case 0x6:
  1561. if (model == 0xf && stepping < 0xe)
  1562. return CPUTYPE_NANO;
  1563. return CPUTYPE_NEHALEM;
  1564. default:
  1565. if (family >= 0x7)
  1566. return CPUTYPE_NEHALEM;
  1567. else
  1568. return CPUTYPE_VIAC3;
  1569. }
  1570. }
  1571. if (vendor == VENDOR_ZHAOXIN){
  1572. return CPUTYPE_NEHALEM;
  1573. }
  1574. if (vendor == VENDOR_RISE){
  1575. switch (family) {
  1576. case 0x5:
  1577. return CPUTYPE_RISEMP6;
  1578. }
  1579. return CPUTYPE_RISE_UNKNOWN;
  1580. }
  1581. if (vendor == VENDOR_SIS){
  1582. switch (family) {
  1583. case 0x5:
  1584. return CPUTYPE_SYS55X;
  1585. }
  1586. return CPUTYPE_SIS_UNKNOWN;
  1587. }
  1588. if (vendor == VENDOR_TRANSMETA){
  1589. switch (family) {
  1590. case 0x5:
  1591. return CPUTYPE_CRUSOETM3X;
  1592. }
  1593. return CPUTYPE_TRANSMETA_UNKNOWN;
  1594. }
  1595. if (vendor == VENDOR_NSC){
  1596. switch (family) {
  1597. case 0x5:
  1598. return CPUTYPE_NSGEODE;
  1599. }
  1600. return CPUTYPE_NSC_UNKNOWN;
  1601. }
  1602. return CPUTYPE_UNKNOWN;
  1603. }
  1604. static char *cpuname[] = {
  1605. "UNKNOWN",
  1606. "INTEL_UNKNOWN",
  1607. "UMC_UNKNOWN",
  1608. "AMD_UNKNOWN",
  1609. "CYRIX_UNKNOWN",
  1610. "NEXGEN_UNKNOWN",
  1611. "CENTAUR_UNKNOWN",
  1612. "RISE_UNKNOWN",
  1613. "SIS_UNKNOWN",
  1614. "TRANSMETA_UNKNOWN",
  1615. "NSC_UNKNOWN",
  1616. "80386",
  1617. "80486",
  1618. "PENTIUM",
  1619. "PENTIUM2",
  1620. "PENTIUM3",
  1621. "PENTIUMM",
  1622. "PENTIUM4",
  1623. "CORE2",
  1624. "PENRYN",
  1625. "DUNNINGTON",
  1626. "NEHALEM",
  1627. "ATOM",
  1628. "ITANIUM",
  1629. "ITANIUM2",
  1630. "5X86",
  1631. "K6",
  1632. "ATHLON",
  1633. "DURON",
  1634. "OPTERON",
  1635. "BARCELONA",
  1636. "SHANGHAI",
  1637. "ISTANBUL",
  1638. "CYRIX5X86",
  1639. "CYRIXM1",
  1640. "CYRIXM2",
  1641. "NEXGENNX586",
  1642. "CENTAURC6",
  1643. "RISEMP6",
  1644. "SYS55X",
  1645. "TM3X00",
  1646. "NSGEODE",
  1647. "VIAC3",
  1648. "NANO",
  1649. "SANDYBRIDGE",
  1650. "BOBCAT",
  1651. "BULLDOZER",
  1652. "PILEDRIVER",
  1653. "HASWELL",
  1654. "STEAMROLLER",
  1655. "EXCAVATOR",
  1656. "ZEN",
  1657. "SKYLAKEX",
  1658. "DHYANA",
  1659. "COOPERLAKE"
  1660. };
  1661. static char *lowercpuname[] = {
  1662. "unknown",
  1663. "intel_unknown",
  1664. "umc_unknown",
  1665. "amd_unknown",
  1666. "cyrix_unknown",
  1667. "nexgen_unknown",
  1668. "centaur_unknown",
  1669. "rise_unknown",
  1670. "sis_unknown",
  1671. "transmeta_unknown",
  1672. "nsc_unknown",
  1673. "80386",
  1674. "80486",
  1675. "pentium",
  1676. "pentium2",
  1677. "pentium3",
  1678. "pentiumm",
  1679. "pentium4",
  1680. "core2",
  1681. "penryn",
  1682. "dunnington",
  1683. "nehalem",
  1684. "atom",
  1685. "itanium",
  1686. "itanium2",
  1687. "5x86",
  1688. "k6",
  1689. "athlon",
  1690. "duron",
  1691. "opteron",
  1692. "barcelona",
  1693. "shanghai",
  1694. "istanbul",
  1695. "cyrix5x86",
  1696. "cyrixm1",
  1697. "cyrixm2",
  1698. "nexgennx586",
  1699. "centaurc6",
  1700. "risemp6",
  1701. "sys55x",
  1702. "tms3x00",
  1703. "nsgeode",
  1704. "nano",
  1705. "sandybridge",
  1706. "bobcat",
  1707. "bulldozer",
  1708. "piledriver",
  1709. "haswell",
  1710. "steamroller",
  1711. "excavator",
  1712. "zen",
  1713. "skylakex",
  1714. "dhyana",
  1715. "cooperlake"
  1716. };
  1717. static char *corename[] = {
  1718. "UNKNOWN",
  1719. "80486",
  1720. "P5",
  1721. "P6",
  1722. "KATMAI",
  1723. "COPPERMINE",
  1724. "NORTHWOOD",
  1725. "PRESCOTT",
  1726. "BANIAS",
  1727. "ATHLON",
  1728. "OPTERON",
  1729. "BARCELONA",
  1730. "VIAC3",
  1731. "YONAH",
  1732. "CORE2",
  1733. "PENRYN",
  1734. "DUNNINGTON",
  1735. "NEHALEM",
  1736. "ATOM",
  1737. "NANO",
  1738. "SANDYBRIDGE",
  1739. "BOBCAT",
  1740. "BULLDOZER",
  1741. "PILEDRIVER",
  1742. "HASWELL",
  1743. "STEAMROLLER",
  1744. "EXCAVATOR",
  1745. "ZEN",
  1746. "SKYLAKEX",
  1747. "DHYANA",
  1748. "COOPERLAKE"
  1749. };
  1750. static char *corename_lower[] = {
  1751. "unknown",
  1752. "80486",
  1753. "p5",
  1754. "p6",
  1755. "katmai",
  1756. "coppermine",
  1757. "northwood",
  1758. "prescott",
  1759. "banias",
  1760. "athlon",
  1761. "opteron",
  1762. "barcelona",
  1763. "viac3",
  1764. "yonah",
  1765. "core2",
  1766. "penryn",
  1767. "dunnington",
  1768. "nehalem",
  1769. "atom",
  1770. "nano",
  1771. "sandybridge",
  1772. "bobcat",
  1773. "bulldozer",
  1774. "piledriver",
  1775. "haswell",
  1776. "steamroller",
  1777. "excavator",
  1778. "zen",
  1779. "skylakex",
  1780. "dhyana",
  1781. "cooperlake"
  1782. };
  1783. char *get_cpunamechar(void){
  1784. return cpuname[get_cpuname()];
  1785. }
  1786. char *get_lower_cpunamechar(void){
  1787. return lowercpuname[get_cpuname()];
  1788. }
  1789. int get_coretype(void){
  1790. int family, exfamily, model, exmodel, vendor, stepping;
  1791. if (!have_cpuid()) return CORE_80486;
  1792. family = get_cputype(GET_FAMILY);
  1793. exfamily = get_cputype(GET_EXFAMILY);
  1794. model = get_cputype(GET_MODEL);
  1795. exmodel = get_cputype(GET_EXMODEL);
  1796. stepping = get_cputype(GET_STEPPING);
  1797. vendor = get_vendor();
  1798. if (vendor == VENDOR_INTEL){
  1799. switch (family) {
  1800. case 4:
  1801. return CORE_80486;
  1802. case 5:
  1803. return CORE_P5;
  1804. case 6:
  1805. switch (exmodel) {
  1806. case 0:
  1807. switch (model) {
  1808. case 0:
  1809. case 1:
  1810. case 2:
  1811. case 3:
  1812. case 4:
  1813. case 5:
  1814. case 6:
  1815. #if defined(__x86_64__) || defined(__amd64__)
  1816. return CORE_CORE2;
  1817. #else
  1818. return CORE_P6;
  1819. #endif
  1820. case 7:
  1821. return CORE_KATMAI;
  1822. case 8:
  1823. case 10:
  1824. case 11:
  1825. return CORE_COPPERMINE;
  1826. case 9:
  1827. case 13:
  1828. case 14:
  1829. return CORE_BANIAS;
  1830. case 15:
  1831. return CORE_CORE2;
  1832. }
  1833. break;
  1834. case 1:
  1835. switch (model) {
  1836. case 6:
  1837. return CORE_CORE2;
  1838. case 7:
  1839. return CORE_PENRYN;
  1840. case 10:
  1841. case 11:
  1842. case 14:
  1843. case 15:
  1844. return CORE_NEHALEM;
  1845. case 12:
  1846. return CORE_ATOM;
  1847. case 13:
  1848. return CORE_DUNNINGTON;
  1849. }
  1850. break;
  1851. case 2:
  1852. switch (model) {
  1853. case 5:
  1854. //Intel Core (Clarkdale) / Core (Arrandale)
  1855. // Pentium (Clarkdale) / Pentium Mobile (Arrandale)
  1856. // Xeon (Clarkdale), 32nm
  1857. return CORE_NEHALEM;
  1858. case 10:
  1859. //Intel Core i5-2000 /i7-2000 (Sandy Bridge)
  1860. if(support_avx())
  1861. return CORE_SANDYBRIDGE;
  1862. else
  1863. return CORE_NEHALEM; //OS doesn't support AVX
  1864. case 12:
  1865. //Xeon Processor 5600 (Westmere-EP)
  1866. return CORE_NEHALEM;
  1867. case 13:
  1868. //Intel Core i7-3000 / Xeon E5 (Sandy Bridge)
  1869. if(support_avx())
  1870. return CORE_SANDYBRIDGE;
  1871. else
  1872. return CORE_NEHALEM; //OS doesn't support AVX
  1873. case 14:
  1874. //Xeon E7540
  1875. case 15:
  1876. //Xeon Processor E7 (Westmere-EX)
  1877. return CORE_NEHALEM;
  1878. }
  1879. break;
  1880. case 3:
  1881. switch (model) {
  1882. case 7:
  1883. return CORE_ATOM;
  1884. case 10:
  1885. case 14:
  1886. if(support_avx())
  1887. return CORE_SANDYBRIDGE;
  1888. else
  1889. return CORE_NEHALEM; //OS doesn't support AVX
  1890. case 12:
  1891. case 15:
  1892. if(support_avx())
  1893. #ifndef NO_AVX2
  1894. return CORE_HASWELL;
  1895. #else
  1896. return CORE_SANDYBRIDGE;
  1897. #endif
  1898. else
  1899. return CORE_NEHALEM;
  1900. case 13:
  1901. //broadwell
  1902. if(support_avx())
  1903. #ifndef NO_AVX2
  1904. return CORE_HASWELL;
  1905. #else
  1906. return CORE_SANDYBRIDGE;
  1907. #endif
  1908. else
  1909. return CORE_NEHALEM;
  1910. }
  1911. break;
  1912. case 4:
  1913. switch (model) {
  1914. case 5:
  1915. case 6:
  1916. if(support_avx())
  1917. #ifndef NO_AVX2
  1918. return CORE_HASWELL;
  1919. #else
  1920. return CORE_SANDYBRIDGE;
  1921. #endif
  1922. else
  1923. return CORE_NEHALEM;
  1924. case 7:
  1925. case 15:
  1926. //broadwell
  1927. if(support_avx())
  1928. #ifndef NO_AVX2
  1929. return CORE_HASWELL;
  1930. #else
  1931. return CORE_SANDYBRIDGE;
  1932. #endif
  1933. else
  1934. return CORE_NEHALEM;
  1935. case 14:
  1936. //Skylake
  1937. if(support_avx())
  1938. #ifndef NO_AVX2
  1939. return CORE_HASWELL;
  1940. #else
  1941. return CORE_SANDYBRIDGE;
  1942. #endif
  1943. else
  1944. return CORE_NEHALEM;
  1945. case 12:
  1946. // Braswell
  1947. case 13:
  1948. // Avoton
  1949. return CORE_NEHALEM;
  1950. }
  1951. break;
  1952. case 10:
  1953. switch (model) {
  1954. case 5: // Comet Lake H and S
  1955. case 6: // Comet Lake U
  1956. if(support_avx())
  1957. #ifndef NO_AVX2
  1958. return CORE_HASWELL;
  1959. #else
  1960. return CORE_SANDYBRIDGE;
  1961. #endif
  1962. else
  1963. return CORE_NEHALEM;
  1964. case 7:// Rocket Lake
  1965. #ifndef NO_AVX512
  1966. if(support_avx512())
  1967. return CORE_SKYLAKEX;
  1968. #endif
  1969. #ifndef NO_AVX2
  1970. if(support_avx2())
  1971. return CORE_HASWELL;
  1972. #endif
  1973. if(support_avx())
  1974. return CORE_SANDYBRIDGE;
  1975. else
  1976. return CORE_NEHALEM;
  1977. }
  1978. case 5:
  1979. switch (model) {
  1980. case 6:
  1981. //broadwell
  1982. if(support_avx())
  1983. #ifndef NO_AVX2
  1984. return CORE_HASWELL;
  1985. #else
  1986. return CORE_SANDYBRIDGE;
  1987. #endif
  1988. else
  1989. return CORE_NEHALEM;
  1990. case 5:
  1991. // Skylake X
  1992. #ifndef NO_AVX512
  1993. if(support_avx512_bf16())
  1994. return CORE_COOPERLAKE;
  1995. return CORE_SKYLAKEX;
  1996. #else
  1997. if(support_avx())
  1998. #ifndef NO_AVX2
  1999. return CORE_HASWELL;
  2000. #else
  2001. return CORE_SANDYBRIDGE;
  2002. #endif
  2003. else
  2004. return CORE_NEHALEM;
  2005. #endif
  2006. case 14:
  2007. // Skylake
  2008. if(support_avx())
  2009. #ifndef NO_AVX2
  2010. return CORE_HASWELL;
  2011. #else
  2012. return CORE_SANDYBRIDGE;
  2013. #endif
  2014. else
  2015. return CORE_NEHALEM;
  2016. case 7:
  2017. // Phi Knights Landing
  2018. if(support_avx())
  2019. #ifndef NO_AVX2
  2020. return CORE_HASWELL;
  2021. #else
  2022. return CORE_SANDYBRIDGE;
  2023. #endif
  2024. else
  2025. return CORE_NEHALEM;
  2026. case 12:
  2027. // Apollo Lake
  2028. return CORE_NEHALEM;
  2029. }
  2030. break;
  2031. case 6:
  2032. if (model == 6)
  2033. #ifndef NO_AVX512
  2034. return CORE_SKYLAKEX;
  2035. #else
  2036. if(support_avx())
  2037. #ifndef NO_AVX2
  2038. return CORE_HASWELL;
  2039. #else
  2040. return CORE_SANDYBRIDGE;
  2041. #endif
  2042. else
  2043. return CORE_NEHALEM;
  2044. #endif
  2045. if (model == 10)
  2046. #ifndef NO_AVX512
  2047. if(support_avx512_bf16())
  2048. return CORE_COOPERLAKE;
  2049. return CORE_SKYLAKEX;
  2050. #else
  2051. if(support_avx())
  2052. #ifndef NO_AVX2
  2053. return CORE_HASWELL;
  2054. #else
  2055. return CORE_SANDYBRIDGE;
  2056. #endif
  2057. else
  2058. return CORE_NEHALEM;
  2059. #endif
  2060. break;
  2061. case 7:
  2062. if (model == 10)
  2063. return CORE_NEHALEM;
  2064. if (model == 14)
  2065. #ifndef NO_AVX512
  2066. return CORE_SKYLAKEX;
  2067. #else
  2068. if(support_avx())
  2069. #ifndef NO_AVX2
  2070. return CORE_HASWELL;
  2071. #else
  2072. return CORE_SANDYBRIDGE;
  2073. #endif
  2074. else
  2075. return CORE_NEHALEM;
  2076. #endif
  2077. break;
  2078. case 9:
  2079. case 8:
  2080. if (model == 12 || model == 13) { // Tiger Lake
  2081. if(support_avx512())
  2082. return CORE_SKYLAKEX;
  2083. if(support_avx2())
  2084. return CORE_HASWELL;
  2085. if(support_avx())
  2086. return CORE_SANDYBRIDGE;
  2087. else
  2088. return CORE_NEHALEM;
  2089. }
  2090. if (model == 14) { // Kaby Lake
  2091. if(support_avx())
  2092. #ifndef NO_AVX2
  2093. return CORE_HASWELL;
  2094. #else
  2095. return CORE_SANDYBRIDGE;
  2096. #endif
  2097. else
  2098. return CORE_NEHALEM;
  2099. }
  2100. }
  2101. break;
  2102. case 15:
  2103. if (model <= 0x2) return CORE_NORTHWOOD;
  2104. else return CORE_PRESCOTT;
  2105. }
  2106. }
  2107. if (vendor == VENDOR_AMD){
  2108. if (family <= 0x5) return CORE_80486;
  2109. #if defined(__x86_64__) || defined(__amd64__)
  2110. if (family <= 0xe) return CORE_BARCELONA;
  2111. #else
  2112. if (family <= 0xe) return CORE_ATHLON;
  2113. #endif
  2114. if (family == 0xf){
  2115. if ((exfamily == 0) || (exfamily == 2)) return CORE_OPTERON;
  2116. else if (exfamily == 5) return CORE_BOBCAT;
  2117. else if (exfamily == 6) {
  2118. switch (model) {
  2119. case 1:
  2120. //AMD Bulldozer Opteron 6200 / Opteron 4200 / AMD FX-Series
  2121. if(support_avx())
  2122. return CORE_BULLDOZER;
  2123. else
  2124. return CORE_BARCELONA; //OS don't support AVX.
  2125. case 2: //AMD Piledriver
  2126. case 3: //AMD Richland
  2127. if(support_avx())
  2128. return CORE_PILEDRIVER;
  2129. else
  2130. return CORE_BARCELONA; //OS don't support AVX.
  2131. case 5: // New EXCAVATOR
  2132. if(support_avx())
  2133. return CORE_EXCAVATOR;
  2134. else
  2135. return CORE_BARCELONA; //OS don't support AVX.
  2136. case 0:
  2137. case 8:
  2138. switch(exmodel){
  2139. case 1: //AMD Trinity
  2140. if(support_avx())
  2141. return CORE_PILEDRIVER;
  2142. else
  2143. return CORE_BARCELONA; //OS don't support AVX.
  2144. case 3:
  2145. if(support_avx())
  2146. return CORE_STEAMROLLER;
  2147. else
  2148. return CORE_BARCELONA; //OS don't support AVX.
  2149. case 6:
  2150. if(support_avx())
  2151. return CORE_EXCAVATOR;
  2152. else
  2153. return CORE_BARCELONA; //OS don't support AVX.
  2154. }
  2155. break;
  2156. }
  2157. } else if (exfamily == 8 || exfamily == 10) {
  2158. switch (model) {
  2159. case 1:
  2160. // AMD Ryzen
  2161. case 8:
  2162. // Ryzen 2
  2163. default:
  2164. // Matisse,Renoir Ryzen2 models
  2165. if(support_avx())
  2166. #ifndef NO_AVX2
  2167. return CORE_ZEN;
  2168. #else
  2169. return CORE_SANDYBRIDGE; // Zen is closer in architecture to Sandy Bridge than to Excavator
  2170. #endif
  2171. else
  2172. return CORE_BARCELONA;
  2173. }
  2174. } else {
  2175. return CORE_BARCELONA;
  2176. }
  2177. }
  2178. }
  2179. if (vendor == VENDOR_HYGON){
  2180. if (family == 0xf){
  2181. if (exfamily == 9) {
  2182. if(support_avx())
  2183. #ifndef NO_AVX2
  2184. return CORE_ZEN;
  2185. #else
  2186. return CORE_SANDYBRIDGE; // closer in architecture to Sandy Bridge than to Excavator
  2187. #endif
  2188. else
  2189. return CORE_BARCELONA;
  2190. } else {
  2191. return CORE_BARCELONA;
  2192. }
  2193. }
  2194. }
  2195. if (vendor == VENDOR_CENTAUR) {
  2196. switch (family) {
  2197. case 0x6:
  2198. if (model == 0xf && stepping < 0xe)
  2199. return CORE_NANO;
  2200. return CORE_NEHALEM;
  2201. default:
  2202. if (family >= 0x7)
  2203. return CORE_NEHALEM;
  2204. else
  2205. return CORE_VIAC3;
  2206. }
  2207. }
  2208. if (vendor == VENDOR_ZHAOXIN) {
  2209. return CORE_NEHALEM;
  2210. }
  2211. return CORE_UNKNOWN;
  2212. }
  2213. void get_cpuconfig(void){
  2214. cache_info_t info;
  2215. int features;
  2216. printf("#define %s\n", cpuname[get_cpuname()]);
  2217. if (get_coretype() != CORE_P5) {
  2218. get_cacheinfo(CACHE_INFO_L1_I, &info);
  2219. if (info.size > 0) {
  2220. printf("#define L1_CODE_SIZE %d\n", info.size * 1024);
  2221. printf("#define L1_CODE_ASSOCIATIVE %d\n", info.associative);
  2222. printf("#define L1_CODE_LINESIZE %d\n", info.linesize);
  2223. }
  2224. get_cacheinfo(CACHE_INFO_L1_D, &info);
  2225. if (info.size > 0) {
  2226. printf("#define L1_DATA_SIZE %d\n", info.size * 1024);
  2227. printf("#define L1_DATA_ASSOCIATIVE %d\n", info.associative);
  2228. printf("#define L1_DATA_LINESIZE %d\n", info.linesize);
  2229. }
  2230. get_cacheinfo(CACHE_INFO_L2, &info);
  2231. if (info.size > 0) {
  2232. printf("#define L2_SIZE %d\n", info.size * 1024);
  2233. printf("#define L2_ASSOCIATIVE %d\n", info.associative);
  2234. printf("#define L2_LINESIZE %d\n", info.linesize);
  2235. } else {
  2236. //fall back for some virtual machines.
  2237. printf("#define L2_SIZE 1048576\n");
  2238. printf("#define L2_ASSOCIATIVE 6\n");
  2239. printf("#define L2_LINESIZE 64\n");
  2240. }
  2241. get_cacheinfo(CACHE_INFO_L3, &info);
  2242. if (info.size > 0) {
  2243. printf("#define L3_SIZE %d\n", info.size * 1024);
  2244. printf("#define L3_ASSOCIATIVE %d\n", info.associative);
  2245. printf("#define L3_LINESIZE %d\n", info.linesize);
  2246. }
  2247. get_cacheinfo(CACHE_INFO_L1_ITB, &info);
  2248. if (info.size > 0) {
  2249. printf("#define ITB_SIZE %d\n", info.size * 1024);
  2250. printf("#define ITB_ASSOCIATIVE %d\n", info.associative);
  2251. printf("#define ITB_ENTRIES %d\n", info.linesize);
  2252. }
  2253. get_cacheinfo(CACHE_INFO_L1_DTB, &info);
  2254. if (info.size > 0) {
  2255. printf("#define DTB_SIZE %d\n", info.size * 1024);
  2256. printf("#define DTB_ASSOCIATIVE %d\n", info.associative);
  2257. printf("#define DTB_DEFAULT_ENTRIES %d\n", info.linesize);
  2258. } else {
  2259. //fall back for some virtual machines.
  2260. printf("#define DTB_DEFAULT_ENTRIES 32\n");
  2261. }
  2262. features = get_cputype(GET_FEATURE);
  2263. if (features & HAVE_CMOV ) printf("#define HAVE_CMOV\n");
  2264. if (features & HAVE_MMX ) printf("#define HAVE_MMX\n");
  2265. if (features & HAVE_SSE ) printf("#define HAVE_SSE\n");
  2266. if (features & HAVE_SSE2 ) printf("#define HAVE_SSE2\n");
  2267. if (features & HAVE_SSE3 ) printf("#define HAVE_SSE3\n");
  2268. if (features & HAVE_SSSE3) printf("#define HAVE_SSSE3\n");
  2269. if (features & HAVE_SSE4_1) printf("#define HAVE_SSE4_1\n");
  2270. if (features & HAVE_SSE4_2) printf("#define HAVE_SSE4_2\n");
  2271. if (features & HAVE_SSE4A) printf("#define HAVE_SSE4A\n");
  2272. if (features & HAVE_SSE5 ) printf("#define HAVE_SSSE5\n");
  2273. if (features & HAVE_AVX ) printf("#define HAVE_AVX\n");
  2274. if (features & HAVE_AVX2 ) printf("#define HAVE_AVX2\n");
  2275. if (features & HAVE_AVX512VL ) printf("#define HAVE_AVX512VL\n");
  2276. if (features & HAVE_AVX512BF16 ) printf("#define HAVE_AVX512BF16\n");
  2277. if (features & HAVE_AMXBF16 ) printf("#define HAVE_AMXBF16\n");
  2278. if (features & HAVE_3DNOWEX) printf("#define HAVE_3DNOWEX\n");
  2279. if (features & HAVE_3DNOW) printf("#define HAVE_3DNOW\n");
  2280. if (features & HAVE_FMA4 ) printf("#define HAVE_FMA4\n");
  2281. if (features & HAVE_FMA3 ) printf("#define HAVE_FMA3\n");
  2282. if (features & HAVE_CFLUSH) printf("#define HAVE_CFLUSH\n");
  2283. if (features & HAVE_HIT) printf("#define HAVE_HIT 1\n");
  2284. if (features & HAVE_MISALIGNSSE) printf("#define HAVE_MISALIGNSSE\n");
  2285. if (features & HAVE_128BITFPU) printf("#define HAVE_128BITFPU\n");
  2286. if (features & HAVE_FASTMOVU) printf("#define HAVE_FASTMOVU\n");
  2287. printf("#define NUM_SHAREDCACHE %d\n", get_cputype(GET_NUMSHARE) + 1);
  2288. printf("#define NUM_CORES %d\n", get_cputype(GET_NUMCORES) + 1);
  2289. features = get_coretype();
  2290. if (features > 0) printf("#define CORE_%s\n", corename[features]);
  2291. } else {
  2292. printf("#define DTB_DEFAULT_ENTRIES 16\n");
  2293. printf("#define L1_CODE_SIZE 8192\n");
  2294. printf("#define L1_DATA_SIZE 8192\n");
  2295. printf("#define L2_SIZE 0\n");
  2296. }
  2297. }
  2298. void get_architecture(void){
  2299. #ifndef __64BIT__
  2300. printf("X86");
  2301. #else
  2302. printf("X86_64");
  2303. #endif
  2304. }
  2305. void get_subarchitecture(void){
  2306. printf("%s", get_cpunamechar());
  2307. }
  2308. void get_subdirname(void){
  2309. #ifndef __64BIT__
  2310. printf("x86");
  2311. #else
  2312. printf("x86_64");
  2313. #endif
  2314. }
  2315. char *get_corename(void){
  2316. return corename[get_coretype()];
  2317. }
  2318. void get_libname(void){
  2319. printf("%s", corename_lower[get_coretype()]);
  2320. }
  2321. /* This if for Makefile */
  2322. void get_sse(void){
  2323. int features;
  2324. features = get_cputype(GET_FEATURE);
  2325. if (features & HAVE_MMX ) printf("HAVE_MMX=1\n");
  2326. if (features & HAVE_SSE ) printf("HAVE_SSE=1\n");
  2327. if (features & HAVE_SSE2 ) printf("HAVE_SSE2=1\n");
  2328. if (features & HAVE_SSE3 ) printf("HAVE_SSE3=1\n");
  2329. if (features & HAVE_SSSE3) printf("HAVE_SSSE3=1\n");
  2330. if (features & HAVE_SSE4_1) printf("HAVE_SSE4_1=1\n");
  2331. if (features & HAVE_SSE4_2) printf("HAVE_SSE4_2=1\n");
  2332. if (features & HAVE_SSE4A) printf("HAVE_SSE4A=1\n");
  2333. if (features & HAVE_SSE5 ) printf("HAVE_SSSE5=1\n");
  2334. if (features & HAVE_AVX ) printf("HAVE_AVX=1\n");
  2335. if (features & HAVE_AVX2 ) printf("HAVE_AVX2=1\n");
  2336. if (features & HAVE_AVX512VL ) printf("HAVE_AVX512VL=1\n");
  2337. if (features & HAVE_AVX512BF16 ) printf("HAVE_AVX512BF16=1\n");
  2338. if (features & HAVE_AMXBF16 ) printf("HAVE_AMXBF16=1\n");
  2339. if (features & HAVE_3DNOWEX) printf("HAVE_3DNOWEX=1\n");
  2340. if (features & HAVE_3DNOW) printf("HAVE_3DNOW=1\n");
  2341. if (features & HAVE_FMA4 ) printf("HAVE_FMA4=1\n");
  2342. if (features & HAVE_FMA3 ) printf("HAVE_FMA3=1\n");
  2343. }