cpuid.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. /*
  2. * Copyright (c) 2013 Ahmed Samy <f.fallen45@gmail.com>
  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 deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * 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 FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. *
  22. * This file has been written with some help from wikipedia:
  23. * http://en.wikipedia.org/wiki/CPUID
  24. */
  25. /* Only compile this file if we're on a x86 machine. */
  26. #if defined(__i386__) || defined(__i386) || defined(__x86_64) \
  27. || defined(_M_AMD64) || defined(__M_X64)
  28. #include "cpuid.h"
  29. #include <string.h>
  30. #include <stdio.h>
  31. enum {
  32. CPUID_PROC_BRAND_STRING_INTERNAL0 = 0x80000003,
  33. CPUID_PROC_BRAND_STRING_INTERNAL1 = 0x80000004
  34. };
  35. #ifndef _MSC_VER
  36. static void get_cpuid(cpuid_t info, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
  37. {
  38. __asm__(
  39. "xchg %%ebx, %%edi\n\t" /* 32bit PIC: Don't clobber ebx. */
  40. "cpuid\n\t"
  41. "xchg %%ebx, %%edi\n\t"
  42. : "=a"(*eax), "=D"(*ebx), "=c"(*ecx), "=d"(*edx)
  43. : "0" (info)
  44. );
  45. }
  46. #else
  47. #include <intrin.h>
  48. static void get_cpuid(cpuid_t info, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
  49. {
  50. uint32_t registers[4];
  51. __cpuid(registers, info);
  52. *eax = registers[0];
  53. *ebx = registers[1];
  54. *ecx = registers[2];
  55. *edx = registers[3];
  56. }
  57. #endif
  58. bool cpuid_is_supported(void)
  59. {
  60. int ret = 0;
  61. #if defined(__GNUC__) || defined(__clang__)
  62. /* The following assembly code uses EAX as the return value,
  63. * but we store the value of EAX into ret since GCC uses EAX
  64. * as the return register for every C function. That's a double
  65. * operation, but there's no other way to do this unless doing this
  66. * function entirely in assembly.
  67. *
  68. * The following assembly code has been shamelessly stolen from:
  69. * http://wiki.osdev.org/CPUID
  70. * and converted to work with AT&T syntax.
  71. *
  72. * This check is to make sure that the compiler is actually compiling
  73. * for 64-bit.
  74. *
  75. * The compiler can be 32-bit and the system 64-bit so the
  76. * following would be true:
  77. * #if defined(__x86_64) ...
  78. */
  79. #if UINTPTR_MAX == 0xffffffffffffffff
  80. #define ASM_PUSHF "pushfq\n\t"
  81. #define ASM_POPF "popfq\n\t"
  82. #define ASM_PUSHEAX "pushq %%rax\n\t"
  83. #define ASM_POPEAX "popq %%rax\n\t"
  84. #define ASM_PUSHECX "pushq %%rcx\n\t"
  85. #elif UINTPTR_MAX == 0xffffffff
  86. #define ASM_PUSHF "pushfl\n\t"
  87. #define ASM_POPF "popfl\n\t"
  88. #define ASM_PUSHEAX "pushl %%eax\n\t"
  89. #define ASM_POPEAX "popl %%eax\n\t"
  90. #define ASM_PUSHECX "pushl %%ecx\n\t"
  91. #endif
  92. asm volatile(
  93. ASM_PUSHF
  94. ASM_POPEAX
  95. "movl %%eax, %%ecx\n\t"
  96. "xorl $0x200000, %%eax\n\t"
  97. ASM_PUSHEAX
  98. ASM_POPF
  99. ASM_PUSHF
  100. ASM_POPEAX
  101. "xorl %%ecx, %%eax\n\t"
  102. "shrl $21, %%eax\n\t"
  103. "andl $1, %%eax\n\t"
  104. ASM_PUSHECX
  105. ASM_POPF
  106. : "=a" (ret)
  107. );
  108. #undef ASM_PUSHF
  109. #undef ASM_POPF
  110. #undef ASM_PUSHEAX
  111. #undef ASM_POPEAX
  112. #undef ASM_PUSHECX
  113. #elif defined _MSC_VER
  114. __asm {
  115. pushfd
  116. pop eax
  117. mov ecx, eax
  118. xor eax, 0x200000
  119. push eax
  120. popfd
  121. pushfd
  122. pop eax
  123. xor eax, ecx
  124. shr eax, 21
  125. and eax, 1
  126. push ecx
  127. popfd
  128. mov eax, ret
  129. };
  130. #endif
  131. return !!ret;
  132. }
  133. bool cpuid_test_feature(cpuid_t feature)
  134. {
  135. if (feature > CPUID_VIRT_PHYS_ADDR_SIZES || feature < CPUID_EXTENDED_PROC_INFO_FEATURE_BITS)
  136. return false;
  137. return (feature <= cpuid_highest_ext_func_supported());
  138. }
  139. #if defined(__GNUC__) || defined(__clang__)
  140. static uint32_t fetch_ecx(uint32_t what)
  141. {
  142. static uint32_t ecx;
  143. if (ecx == 0) {
  144. asm volatile(
  145. "cpuid\n\t"
  146. : "=c" (ecx)
  147. : "a" (what)
  148. );
  149. }
  150. return ecx;
  151. }
  152. static uint32_t fetch_edx(uint32_t what)
  153. {
  154. static uint32_t edx;
  155. if (edx == 0) {
  156. asm volatile(
  157. "cpuid\n\t"
  158. : "=d" (edx)
  159. : "a" (what)
  160. );
  161. }
  162. return edx;
  163. }
  164. #elif defined(_MSC_VER)
  165. static uint32_t fetch_ecx(uint32_t what)
  166. {
  167. static uint32_t _ecx;
  168. if (_ecx == 0) {
  169. __asm {
  170. mov eax, what
  171. cpuid
  172. mov _ecx, ecx
  173. };
  174. }
  175. return _ecx;
  176. }
  177. static uint32_t fetch_edx(uint32_t what)
  178. {
  179. static uint32_t _edx;
  180. if (_edx == 0) {
  181. __asm {
  182. mov eax, what
  183. cpuid
  184. mov _edx, edx
  185. };
  186. }
  187. return _edx;
  188. }
  189. #endif
  190. #define DEFINE_FEATURE_FUNC(NAME, REGISTER, TYPE) \
  191. bool cpuid_has_##NAME(int feature) \
  192. { \
  193. static uint32_t REGISTER; \
  194. if (REGISTER == 0) \
  195. REGISTER = fetch_##REGISTER(TYPE); \
  196. return !!(REGISTER & feature); \
  197. }
  198. DEFINE_FEATURE_FUNC(ecxfeature, ecx, CPUID_PROCINFO_AND_FEATUREBITS)
  199. DEFINE_FEATURE_FUNC(edxfeature, edx, CPUID_PROCINFO_AND_FEATUREBITS)
  200. DEFINE_FEATURE_FUNC(ecxfeature_ext, ecx, CPUID_EXTENDED_PROC_INFO_FEATURE_BITS)
  201. DEFINE_FEATURE_FUNC(edxfeature_ext, edx, CPUID_EXTENDED_PROC_INFO_FEATURE_BITS)
  202. #undef DEFINE_FEATURE_FUNC
  203. cputype_t cpuid_get_cpu_type(void)
  204. {
  205. static cputype_t cputype;
  206. if (cputype == CT_NONE) {
  207. union {
  208. char buf[12];
  209. uint32_t bufu32[3];
  210. } u;
  211. uint32_t i;
  212. get_cpuid(CPUID_VENDORID, &i, &u.bufu32[0], &u.bufu32[2], &u.bufu32[1]);
  213. for (i = 0; i < sizeof(c_cpunames) / sizeof(c_cpunames[0]); ++i) {
  214. if (strncmp(c_cpunames[i], u.buf, 12) == 0) {
  215. cputype = (cputype_t)i;
  216. break;
  217. }
  218. }
  219. }
  220. return cputype;
  221. }
  222. uint32_t cpuid_highest_ext_func_supported(void)
  223. {
  224. static uint32_t highest;
  225. if (!highest) {
  226. #if defined(__GNUC__) || defined(__clang__)
  227. asm volatile(
  228. "cpuid\n\t"
  229. : "=a" (highest)
  230. : "a" (CPUID_HIGHEST_EXTENDED_FUNCTION_SUPPORTED)
  231. );
  232. #elif defined _MSC_VER
  233. __asm {
  234. mov eax, CPUID_HIGHEST_EXTENDED_FUNCTION_SUPPORTED
  235. cpuid
  236. mov highest, eax
  237. };
  238. #endif
  239. }
  240. return highest;
  241. }
  242. void cpuid(cpuid_t request, uint32_t *buf)
  243. {
  244. /* Sanity checks, make sure we're not trying to do something
  245. * invalid or we are trying to get information that isn't supported
  246. * by the CPU. */
  247. if (request > CPUID_VIRT_PHYS_ADDR_SIZES || (request > CPUID_HIGHEST_EXTENDED_FUNCTION_SUPPORTED
  248. && !cpuid_test_feature(request)))
  249. return;
  250. if (request == CPUID_PROC_BRAND_STRING) {
  251. static char cached[48] = { 0 };
  252. if (cached[0] == '\0') {
  253. get_cpuid(CPUID_PROC_BRAND_STRING, &buf[0], &buf[1], &buf[2], &buf[3] );
  254. get_cpuid(CPUID_PROC_BRAND_STRING_INTERNAL0, &buf[4], &buf[5], &buf[6], &buf[7] );
  255. get_cpuid(CPUID_PROC_BRAND_STRING_INTERNAL1, &buf[8], &buf[9], &buf[10], &buf[11]);
  256. memcpy(cached, buf, sizeof cached);
  257. } else
  258. buf = (uint32_t *)cached;
  259. return;
  260. } else if (request == CPUID_HIGHEST_EXTENDED_FUNCTION_SUPPORTED) {
  261. *buf = cpuid_highest_ext_func_supported();
  262. return;
  263. }
  264. uint32_t eax, ebx, ecx, edx;
  265. get_cpuid(request, &eax, &ebx, &ecx, &edx);
  266. switch (request) {
  267. case CPUID_VENDORID:
  268. buf[0] = ebx;
  269. buf[1] = edx;
  270. buf[2] = ecx;
  271. break;
  272. case CPUID_PROCINFO_AND_FEATUREBITS:
  273. buf[0] = (eax & 0x0F); /* Stepping */
  274. buf[1] = (eax >> 4) & 0x0F; /* Model */
  275. buf[2] = (eax >> 8) & 0x0F; /* Family */
  276. buf[3] = (eax >> 16) & 0x0F; /* Extended Model. */
  277. buf[4] = (eax >> 24) & 0x0F; /* Extended Family. */
  278. /* Additional Feature information. */
  279. buf[5] = ebx & 0xFF;
  280. buf[6] = (ebx >> 8) & 0xFF;
  281. buf[7] = (ebx >> 16) & 0xFF;
  282. buf[8] = ebx >> 24;
  283. break;
  284. case CPUID_CACHE_AND_TLBD_INFO:
  285. buf[0] = eax;
  286. buf[1] = ebx;
  287. buf[2] = ecx;
  288. buf[3] = edx;
  289. break;
  290. case CPUID_EXTENDED_PROC_INFO_FEATURE_BITS:
  291. buf[0] = edx;
  292. buf[1] = ecx;
  293. break;
  294. case CPUID_L1_CACHE_AND_TLB_IDS:
  295. buf[0] = eax & 0xFF;
  296. buf[1] = (eax >> 8) & 0xFF;
  297. buf[2] = (eax >> 16) & 0xFF;
  298. buf[3] = eax >> 24;
  299. buf[4] = ebx & 0xFF;
  300. buf[5] = (ebx >> 8) & 0xFF;
  301. buf[6] = (ebx >> 16) & 0xFF;
  302. buf[7] = ebx >> 24;
  303. buf[8] = ecx & 0xFF;
  304. buf[9] = (ecx >> 8) & 0xFF;
  305. buf[10] = (ecx >> 16) & 0xFF;
  306. buf[11] = ecx >> 24;
  307. buf[12] = edx & 0xFF;
  308. buf[13] = (edx >> 8) & 0xFF;
  309. buf[14] = (edx >> 16) & 0xFF;
  310. buf[15] = edx >> 24;
  311. break;
  312. case CPUID_EXTENDED_L2_CACHE_FEATURES:
  313. buf[0] = ecx & 0xFF; /* Line size. */
  314. buf[1] = (ecx >> 12) & 0xFF; /* Associativity. */
  315. buf[2] = ecx >> 16; /* Cache size. */
  316. break;
  317. case CPUID_ADV_POWER_MGT_INFO:
  318. *buf = edx;
  319. break;
  320. case CPUID_VIRT_PHYS_ADDR_SIZES:
  321. buf[0] = eax & 0xFF; /* physical. */
  322. buf[1] = (eax >> 8) & 0xFF; /* virtual. */
  323. break;
  324. default:
  325. *buf = 0xbaadf00d;
  326. break;
  327. }
  328. }
  329. bool cpuid_write_info(uint32_t info, uint32_t featureset, FILE *file)
  330. {
  331. char brand[48];
  332. cpuid(CPUID_PROC_BRAND_STRING, (uint32_t *)brand);
  333. fprintf(file, "-- CPU Information for: %s_%s --\n\n", cpuid_get_name(), brand);
  334. if (info & CPUID_HIGHEST_EXTENDED_FUNCTION_SUPPORTED)
  335. fprintf(file, "Highest extended function supported: %#010x\n\n", cpuid_highest_ext_func_supported());
  336. if (info & CPUID_EXTENDED_L2_CACHE_FEATURES) {
  337. uint32_t l2c[3];
  338. cpuid(CPUID_EXTENDED_L2_CACHE_FEATURES, l2c);
  339. fprintf(file, "-- Extended L2 Cache features --\nL2 Line size: %u bytes\nAssociativity: %02xh\nCache Size: %u KB\n\n",
  340. l2c[0], l2c[1], l2c[2]);
  341. }
  342. if (info & CPUID_VIRT_PHYS_ADDR_SIZES) {
  343. uint32_t phys_virt[2];
  344. cpuid(CPUID_VIRT_PHYS_ADDR_SIZES, phys_virt);
  345. fprintf(file, "-- Virtual and Physical address sizes --\n"
  346. "Physical address size: %d\nVirtual address size: %d\n\n", phys_virt[0], phys_virt[1]);
  347. }
  348. if (info & CPUID_PROCINFO_AND_FEATUREBITS) {
  349. uint32_t procinfo[9];
  350. cpuid(CPUID_PROCINFO_AND_FEATUREBITS, procinfo);
  351. fputs("-- Processor information and feature bits --\n", file );
  352. fprintf(file, "Stepping: %d\nModel: 0x%X\nFamily: %d\nExtended model: %d\nExtended family: %d\n",
  353. procinfo[0], procinfo[1], procinfo[2], procinfo[3], procinfo[4]);
  354. fprintf(file, "\nBrand Index: %d\nCL Flush Line Size: %d\nLogical Processors: %d\nInitial APICID: %d\n\n",
  355. procinfo[5], procinfo[6], procinfo[7], procinfo[8]);
  356. }
  357. if (featureset != 0)
  358. fputs("-- CPU FEATURES --\n\n", file);
  359. bool
  360. sse3 = cpuid_has_ecxfeature(CPUID_FEAT_ECX_SSE3),
  361. pclmul = cpuid_has_ecxfeature(CPUID_FEAT_ECX_PCLMUL),
  362. dtes64 = cpuid_has_ecxfeature(CPUID_FEAT_ECX_DTES64),
  363. monitor = cpuid_has_ecxfeature(CPUID_FEAT_ECX_MONITOR),
  364. ds_cpl = cpuid_has_ecxfeature(CPUID_FEAT_ECX_DS_CPL),
  365. vmx = cpuid_has_ecxfeature(CPUID_FEAT_ECX_VMX),
  366. smx = cpuid_has_ecxfeature(CPUID_FEAT_ECX_SMX),
  367. est = cpuid_has_ecxfeature(CPUID_FEAT_ECX_EST),
  368. tm2 = cpuid_has_ecxfeature(CPUID_FEAT_ECX_TM2),
  369. ssse3 = cpuid_has_ecxfeature(CPUID_FEAT_ECX_SSSE3),
  370. cid = cpuid_has_ecxfeature(CPUID_FEAT_ECX_CID),
  371. fma = cpuid_has_ecxfeature(CPUID_FEAT_ECX_FMA),
  372. cx16 = cpuid_has_ecxfeature(CPUID_FEAT_ECX_CX16),
  373. etprd = cpuid_has_ecxfeature(CPUID_FEAT_ECX_ETPRD),
  374. pdcm = cpuid_has_ecxfeature(CPUID_FEAT_ECX_PDCM),
  375. dca = cpuid_has_ecxfeature(CPUID_FEAT_ECX_DCA),
  376. sse4_1 = cpuid_has_ecxfeature(CPUID_FEAT_ECX_SSE4_1),
  377. sse4_2 = cpuid_has_ecxfeature(CPUID_FEAT_ECX_SSE4_2),
  378. x2_apic = cpuid_has_ecxfeature(CPUID_FEAT_ECX_x2APIC),
  379. movbe = cpuid_has_ecxfeature(CPUID_FEAT_ECX_MOVBE),
  380. popcnt = cpuid_has_ecxfeature(CPUID_FEAT_ECX_POPCNT),
  381. aes = cpuid_has_ecxfeature(CPUID_FEAT_ECX_AES),
  382. xsave = cpuid_has_ecxfeature(CPUID_FEAT_ECX_XSAVE),
  383. osxsave = cpuid_has_ecxfeature(CPUID_FEAT_ECX_OSXSAVE),
  384. avx = cpuid_has_ecxfeature(CPUID_FEAT_ECX_AVX);
  385. #define YON(v) (v) ? "Yes" : "No"
  386. if (featureset & CPUID_FEAT_ECX_ALL) {
  387. fputs("-- ECX Features --\n", file);
  388. fprintf(file, "SSE3: %s\n"
  389. "PCMUL: %s\n"
  390. "DTES64: %s\n"
  391. "MONITOR: %s\n"
  392. "DS_CPL: %s\n"
  393. "VMX: %s\n"
  394. "SMX: %s\n"
  395. "EST: %s\n"
  396. "TM2: %s\n"
  397. "SSSE3: %s\n"
  398. "CID: %s\n"
  399. "FMA: %s\n"
  400. "CX16: %s\n"
  401. "ETPRD: %s\n"
  402. "PDCM: %s\n"
  403. "DCA: %s\n"
  404. "SSE4_1: %s\n"
  405. "SSE$_2: %s\n"
  406. "X2_APIC: %s\n"
  407. "MOVBE: %s\n"
  408. "POPCNT: %s\n"
  409. "AES: %s\n"
  410. "XSAVE: %s\n"
  411. "OSXSAVE: %s\n"
  412. "AVS: %s\n\n",
  413. YON(sse3), YON(pclmul), YON(dtes64), YON(monitor), YON(ds_cpl),
  414. YON(vmx), YON(smx), YON(est), YON(tm2), YON(ssse3), YON(cid),
  415. YON(fma), YON(cx16), YON(etprd), YON(pdcm), YON(dca), YON(sse4_1),
  416. YON(sse4_2), YON(x2_apic), YON(movbe), YON(popcnt), YON(aes),
  417. YON(xsave), YON(osxsave), YON(avx)
  418. );
  419. } else {
  420. if (featureset & CPUID_FEAT_ECX_SSE3)
  421. fprintf(file, "SSE3: %s\n", YON(sse3));
  422. if (featureset & CPUID_FEAT_ECX_PCLMUL)
  423. fprintf(file, "PCLMUL: %s\n", YON(pclmul));
  424. if (featureset & CPUID_FEAT_ECX_DTES64)
  425. fprintf(file, "DTES64: %s\n", YON(dtes64));
  426. if (featureset & CPUID_FEAT_ECX_MONITOR)
  427. fprintf(file, "Monitor: %s\n", YON(monitor));
  428. if (featureset & CPUID_FEAT_ECX_DS_CPL)
  429. fprintf(file, "DS CPL: %s\n", YON(ds_cpl));
  430. if (featureset & CPUID_FEAT_ECX_VMX)
  431. fprintf(file, "VMX: %s\n", YON(vmx));
  432. if (featureset & CPUID_FEAT_ECX_SMX)
  433. fprintf(file, "SMX: %s\n", YON(smx));
  434. if (featureset & CPUID_FEAT_ECX_EST)
  435. fprintf(file, "EST: %s\n", YON(est));
  436. if (featureset & CPUID_FEAT_ECX_TM2)
  437. fprintf(file, "TM2: %s\n", YON(tm2));
  438. if (featureset & CPUID_FEAT_ECX_SSSE3)
  439. fprintf(file, "SSSE3: %s\n", YON(ssse3));
  440. if (featureset & CPUID_FEAT_ECX_CID)
  441. fprintf(file, "CID: %s\n", YON(cid));
  442. if (featureset & CPUID_FEAT_ECX_FMA)
  443. fprintf(file, "FMA: %s\n", YON(fma));
  444. if (featureset & CPUID_FEAT_ECX_CX16)
  445. fprintf(file, "CX16: %s\n", YON(cx16));
  446. if (featureset & CPUID_FEAT_ECX_ETPRD)
  447. fprintf(file, "ETPRD: %s\n", YON(etprd));
  448. if (featureset & CPUID_FEAT_ECX_PDCM)
  449. fprintf(file, "PDCM: %s\n", YON(pdcm));
  450. if (featureset & CPUID_FEAT_ECX_DCA)
  451. fprintf(file, "DCA: %s\n", YON(dca));
  452. if (featureset & CPUID_FEAT_ECX_SSE4_1)
  453. fprintf(file, "SSE4_1: %s\n", YON(sse4_1));
  454. if (featureset & CPUID_FEAT_ECX_SSE4_2)
  455. fprintf(file, "SSE4_2: %s\n", YON(sse4_2));
  456. if (featureset & CPUID_FEAT_ECX_x2APIC)
  457. fprintf(file, "x2APIC: %s\n", YON(x2_apic));
  458. if (featureset & CPUID_FEAT_ECX_MOVBE)
  459. fprintf(file, "MOVBE: %s\n", YON(movbe));
  460. if (featureset & CPUID_FEAT_ECX_POPCNT)
  461. fprintf(file, "POPCNT: %s\n", YON(popcnt));
  462. if (featureset & CPUID_FEAT_ECX_AES)
  463. fprintf(file, "AES: %s\n", YON(aes));
  464. if (featureset & CPUID_FEAT_ECX_XSAVE)
  465. fprintf(file, "XSAVE: %s\n", YON(xsave));
  466. if (featureset & CPUID_FEAT_ECX_OSXSAVE)
  467. fprintf(file, "OSXSAVE: %s\n", YON(osxsave));
  468. if (featureset & CPUID_FEAT_ECX_AVX)
  469. fprintf(file, "AVX: %s\n", YON(avx));
  470. }
  471. bool
  472. fpu = cpuid_has_edxfeature(CPUID_FEAT_EDX_FPU),
  473. vme = cpuid_has_edxfeature(CPUID_FEAT_EDX_VME),
  474. de = cpuid_has_edxfeature(CPUID_FEAT_EDX_DE),
  475. pse = cpuid_has_edxfeature(CPUID_FEAT_EDX_PSE),
  476. tsc = cpuid_has_edxfeature(CPUID_FEAT_EDX_TSC),
  477. msr = cpuid_has_edxfeature(CPUID_FEAT_EDX_MSR),
  478. pae = cpuid_has_edxfeature(CPUID_FEAT_EDX_PAE),
  479. mce = cpuid_has_edxfeature(CPUID_FEAT_EDX_MCE),
  480. cx8 = cpuid_has_edxfeature(CPUID_FEAT_EDX_CX8),
  481. apic = cpuid_has_edxfeature(CPUID_FEAT_EDX_APIC),
  482. sep = cpuid_has_edxfeature(CPUID_FEAT_EDX_SEP),
  483. mtrr = cpuid_has_edxfeature(CPUID_FEAT_EDX_MTRR),
  484. pge = cpuid_has_edxfeature(CPUID_FEAT_EDX_PGE),
  485. mca = cpuid_has_edxfeature(CPUID_FEAT_EDX_MCA),
  486. cmov = cpuid_has_edxfeature(CPUID_FEAT_EDX_CMOV),
  487. pat = cpuid_has_edxfeature(CPUID_FEAT_EDX_PAT),
  488. pse36 = cpuid_has_edxfeature(CPUID_FEAT_EDX_PSE36),
  489. psn = cpuid_has_edxfeature(CPUID_FEAT_EDX_PSN),
  490. clf = cpuid_has_edxfeature(CPUID_FEAT_EDX_CLF),
  491. dtes = cpuid_has_edxfeature(CPUID_FEAT_EDX_DTES),
  492. acpi = cpuid_has_edxfeature(CPUID_FEAT_EDX_ACPI),
  493. mmx = cpuid_has_edxfeature(CPUID_FEAT_EDX_MMX),
  494. fxsr = cpuid_has_edxfeature(CPUID_FEAT_EDX_FXSR),
  495. sse = cpuid_has_edxfeature(CPUID_FEAT_EDX_SSE),
  496. sse2 = cpuid_has_edxfeature(CPUID_FEAT_EDX_SSE2),
  497. ss = cpuid_has_edxfeature(CPUID_FEAT_EDX_SS),
  498. htt = cpuid_has_edxfeature(CPUID_FEAT_EDX_HTT),
  499. tm1 = cpuid_has_edxfeature(CPUID_FEAT_EDX_TM1),
  500. ia64 = cpuid_has_edxfeature(CPUID_FEAT_EDX_IA64),
  501. pbe = cpuid_has_edxfeature(CPUID_FEAT_EDX_PBE);
  502. if (featureset & CPUID_FEAT_EDX_ALL) {
  503. fputs("-- EDX FEATURES --\n", file);
  504. fprintf(file, "FPU: %s\n"
  505. "VME: %s\n"
  506. "DE: %s\n"
  507. "PSE: %s\n"
  508. "TSC: %s\n"
  509. "MSR: %s\n"
  510. "PAE: %s\n"
  511. "MCE: %s\n"
  512. "CX8: %s\n"
  513. "APIC: %s\n"
  514. "SEP: %s\n"
  515. "MTRR: %s\n"
  516. "PGE: %s\n"
  517. "MCA: %s\n"
  518. "CMOV: %s\n"
  519. "PAT: %s\n"
  520. "PSE36: %s\n"
  521. "PSN: %s\n"
  522. "CLF: %s\n"
  523. "DTES: %s\n"
  524. "ACPI: %s\n"
  525. "MMX: %s\n"
  526. "FXSR: %s\n"
  527. "SSE: %s\n"
  528. "SSE2: %s\n"
  529. "SS: %s\n"
  530. "HTT: %s\n"
  531. "TM1: %s\n"
  532. "IA64: %s\n"
  533. "PBE: %s\n\n",
  534. YON(fpu), YON(vme), YON(de), YON(pse), YON(tsc), YON(msr),
  535. YON(pae), YON(mce), YON(cx8), YON(apic), YON(sep), YON(mtrr),
  536. YON(pge), YON(mca), YON(cmov), YON(pat), YON(pse36), YON(psn),
  537. YON(clf), YON(dtes), YON(acpi), YON(mmx), YON(fxsr), YON(sse),
  538. YON(sse2), YON(ss), YON(htt), YON(tm1), YON(ia64), YON(pbe)
  539. );
  540. } else {
  541. if (featureset & CPUID_FEAT_EDX_FPU)
  542. fprintf(file, "FPU: %s\n", YON(fpu));
  543. if (featureset & CPUID_FEAT_EDX_VME)
  544. fprintf(file, "VME: %s\n", YON(vme));
  545. if (featureset & CPUID_FEAT_EDX_DE)
  546. fprintf(file, "DE: %s\n", YON(de));
  547. if (featureset & CPUID_FEAT_EDX_PSE)
  548. fprintf(file, "PSE: %s\n", YON(pse));
  549. if (featureset & CPUID_FEAT_EDX_TSC)
  550. fprintf(file, "TSC: %s\n", YON(tsc));
  551. if (featureset & CPUID_FEAT_EDX_MSR)
  552. fprintf(file, "MSR: %s\n", YON(msr));
  553. if (featureset & CPUID_FEAT_EDX_PAE)
  554. fprintf(file, "PAE: %s\n", YON(pae));
  555. if (featureset & CPUID_FEAT_EDX_MCE)
  556. fprintf(file, "MCE: %s\n", YON(mce));
  557. if (featureset & CPUID_FEAT_EDX_CX8)
  558. fprintf(file, "CX8: %s\n", YON(cx8));
  559. if (featureset & CPUID_FEAT_EDX_APIC)
  560. fprintf(file, "APIC: %s\n", YON(apic));
  561. if (featureset & CPUID_FEAT_EDX_SEP)
  562. fprintf(file, "SEP: %s\n", YON(sep));
  563. if (featureset & CPUID_FEAT_EDX_MTRR)
  564. fprintf(file, "MTRR: %s\n", YON(mtrr));
  565. if (featureset & CPUID_FEAT_EDX_PGE)
  566. fprintf(file, "PGE: %s\n", YON(pge));
  567. if (featureset & CPUID_FEAT_EDX_MCA)
  568. fprintf(file, "MCA: %s\n", YON(mca));
  569. if (featureset & CPUID_FEAT_EDX_CMOV)
  570. fprintf(file, "CMOV: %s\n", YON(cmov));
  571. if (featureset & CPUID_FEAT_EDX_PAT)
  572. fprintf(file, "PAT: %s\n", YON(pat));
  573. if (featureset & CPUID_FEAT_EDX_PSE36)
  574. fprintf(file, "PSE36: %s\n", YON(pse36));
  575. if (featureset & CPUID_FEAT_EDX_PSN)
  576. fprintf(file, "PSN: %s\n", YON(psn));
  577. if (featureset & CPUID_FEAT_EDX_CLF)
  578. fprintf(file, "CLF: %s\n", YON(clf));
  579. if (featureset & CPUID_FEAT_EDX_DTES)
  580. fprintf(file, "DTES:%s\n", YON(dtes));
  581. if (featureset & CPUID_FEAT_EDX_ACPI)
  582. fprintf(file, "ACPI: %s\n", YON(acpi));
  583. if (featureset & CPUID_FEAT_EDX_MMX)
  584. fprintf(file, "MMX: %s\n", YON(mmx));
  585. if (featureset & CPUID_FEAT_EDX_FXSR)
  586. fprintf(file, "FXSR: %s\n", YON(fxsr));
  587. if (featureset & CPUID_FEAT_EDX_SSE)
  588. fprintf(file, "SSE: %s\n", YON(sse));
  589. if (featureset & CPUID_FEAT_EDX_SSE2)
  590. fprintf(file, "SSE2: %s\n", YON(sse2));
  591. if (featureset & CPUID_FEAT_EDX_SS)
  592. fprintf(file, "SS: %s\n", YON(ss));
  593. if (featureset & CPUID_FEAT_EDX_HTT)
  594. fprintf(file, "HTT: %s\n", YON(htt));
  595. if (featureset & CPUID_FEAT_EDX_TM1)
  596. fprintf(file, "TM1: %s\n", YON(tm1));
  597. if (featureset & CPUID_FEAT_EDX_IA64)
  598. fprintf(file, "IA64: %s\n", YON(ia64));
  599. if (featureset & CPUID_FEAT_EDX_PBE)
  600. fprintf(file, "PBE: %s\n", YON(pbe));
  601. }
  602. #undef YON
  603. return true;
  604. }
  605. #endif