1 /*
2 ** cpuid dumps CPUID information for each CPU.
3 ** Copyright 2003,2004,2005,2006,2010,2011,2012,2013,2014,2015,2016,2017,2018,
4 ** 2020,2021 by Todd Allen.
5 **
6 ** This program is free software; you can redistribute it and/or
7 ** modify it under the terms of the GNU General Public License
8 ** as published by the Free Software Foundation; either version 2
9 ** of the License, or (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software Foundation, Inc.,
18 ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 // MSR_CPUID_table* is a table that appears in Intel document 325462, "Intel 64
22 // and IA-32 Architectures Software Developer's Manual Combined Volumes: 1, 2A,
23 // 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4" (the name changes from version to version
24 // as more volumes are added). The table moves around from version to version,
25 // but in version 071US, was in "Volume 4: Model-Specific Registers", Table 2-1:
26 // "CPUID Signature Values of DisplayFamily_DisplayModel".
27
28 // MRG* is a table that forms the bulk of Intel Microcode Revision Guidance (or
29 // Microcode Update Guidance). Its purpose is not to list CPUID values, but
30 // it does so, and sometimes lists values that appear nowhere else.
31
32 // LX* indicates features that I have seen no documentation for, but which are
33 // used by the Linux kernel (which is good evidence that they're correct).
34 // The "hook" to find these generally is an X86_FEATURE_* flag in:
35 // arch/x86/include/asm/cpufeatures.h
36 // For (synth) and (uarch synth) decoding, it often indicates
37 // family/model/stepping values which are documented nowhere else. These
38 // usually can be found in:
39 // arch/x86/include/asm/intel-family.h
40
41 // Coreboot* indicates (synth) or (uarch synth) decoding for which I have seen
42 // no documentation, but which is used by coreboot, BIOS replacement software.
43 // The core information is in:
44 // src/include/cpu/intel/cpu_ids.h
45 // src/soc/intel/common/block/include/intelblocks/mp_init.h
46 // src/soc/intel/*/include/soc/cpu.h (old)
47 // And strings, for the less obvious cases, are in:
48 // src/soc/intel/*/bootblock/report_platform.c
49
50 // Xen* indicates features that I have seen no documentation for, but which are
51 // used by the Xen hypervisor. They are listed in:
52 // xen/include/public/arch-x86/cpuid.h
53 // tools/libxl/libxl_cpuid.c (old)
54
55 // Qemu* indicates features that I have seen no documentation for, but which are
56 // used by the Qemu hypervisor. They are listed in:
57 // target/i386/cpu.c
58
59 // SKC* indicates features that I have seen no (or incomplete) documentation
60 // for, but which were sent to me in patch form by Smita Koralahalli
61 // Channabasappa of AMD.
62
63 #ifdef __linux__
64 #define USE_CPUID_MODULE
65 #define USE_KERNEL_SCHED_SETAFFINITY
66 #endif
67
68 #if defined(__sun)
69 #define USE_PROCESSOR_BIND
70 #endif
71
72 #if __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ >= 40300
73 #define USE_CPUID_COUNT
74 #endif
75
76 #define CPUID_MAJOR 0
77
78 #if defined(__GNUC__)
79 #define UNUSED __attribute((unused))
80 #else
81 #define UNUSED
82 #endif
83
84 #define _GNU_SOURCE
85 #define _LARGEFILE64_SOURCE
86 #include <unistd.h>
87 #include <sys/types.h>
88
89 #ifdef __CYGWIN__
90 #define __LARGE64_FILES
91 typedef off_t off64_t;
92 #define lseek64 lseek
93 #endif
94
95 #include <stdio.h>
96 #include <sys/stat.h>
97 #include <fcntl.h>
98 #include <errno.h>
99 #include <stdlib.h>
100 #include <string.h>
101 #include <ctype.h>
102 #include <regex.h>
103 #include <getopt.h>
104
105 #ifdef USE_CPUID_MODULE
106 #include <linux/major.h>
107 #endif
108
109 #ifdef USE_CPUID_COUNT
110 #include <cpuid.h>
111 #endif
112
113 #if defined(USE_KERNEL_SCHED_SETAFFINITY)
114 #include <sys/sysmacros.h>
115 #include <sys/syscall.h>
116 #elif defined(USE_PROCESSOR_BIND)
117 #include <sys/processor.h>
118 #include <sys/procset.h>
119 #include <strings.h>
120 #include <pthread.h>
121 #else
122 #ifdef __FreeBSD__
123 #include <sys/cpuset.h>
124 #endif
125 #include <sched.h>
126 #endif
127
128 typedef int boolean;
129 #define TRUE 1
130 #define FALSE 0
131
132 typedef char* string;
133 typedef const char* cstring;
134 typedef const char* const ccstring;
135 #define SAME 0
136
137 #define STR(x) #x
138 #define XSTR(x) STR(x)
139
140 #ifndef MAX
141 #define MAX(l,r) ((l) > (r) ? (l) : (r))
142 #endif
143
144 #define LENGTH(array) (sizeof(array) / sizeof(array[0]))
145
146 #define BPI 32
147 #define POWER2(power) \
148 (1 << (power))
149 #define RIGHTMASK(width) \
150 (((width) >= BPI) ? ~0 : POWER2(width)-1)
151 #define BIT_EXTRACT_LE(value, start, after) \
152 (((value) & RIGHTMASK(after)) >> start)
153
154 #define WORD_EAX 0
155 #define WORD_EBX 1
156 #define WORD_ECX 2
157 #define WORD_EDX 3
158
159 #define WORD_NUM 4
160
161 const char* program = NULL;
162
strregexp(const char * haystack,const char * needle)163 static boolean strregexp(const char* haystack,
164 const char* needle)
165 {
166 regex_t re;
167 int status;
168 status = regcomp(&re, needle, REG_NOSUB);
169 if (status != 0) {
170 size_t size = regerror(status, &re, NULL, 0);
171 char* buffer = malloc(size + 1);
172 if (buffer == NULL || size + 1 == 0) {
173 fprintf(stderr, "%s: out of memory\n", program);
174 exit(1);
175 }
176 regerror(status, &re, buffer, size);
177 fprintf(stderr, "%s: cannot regcomp \"%s\"; error = %s\n",
178 program, needle, buffer);
179 exit(1);
180 }
181 status = regexec(&re, haystack, 0, NULL, 0);
182 if (status != 0 && status != REG_NOMATCH) {
183 size_t size = regerror(status, &re, NULL, 0);
184 char* buffer = malloc(size + 1);
185 if (buffer == NULL || size + 1 == 0) {
186 fprintf(stderr, "%s: out of memory\n", program);
187 exit(1);
188 }
189 regerror(status, &re, buffer, size);
190 fprintf(stderr, "%s: cannot regexec string \"%s\" with regexp \"%s\";"
191 " error = %s\n",
192 program, haystack, needle, buffer);
193 exit(1);
194 }
195 regfree(&re);
196
197 return (status == 0);
198 }
199
200 typedef struct {
201 ccstring name;
202 unsigned int low_bit;
203 unsigned int high_bit;
204 ccstring* images;
205 } named_item;
206
207 #define NIL_IMAGES (ccstring*)NULL
208 #define MINUS1_IMAGES (ccstring*)1
209 #define X2_IMAGES (ccstring*)2
210
211 static unsigned int
get_max_len(named_item names[],unsigned int length)212 get_max_len (named_item names[],
213 unsigned int length)
214 {
215 unsigned int result = 0;
216 unsigned int i;
217
218 for (i = 0; i < length; i++) {
219 result = MAX(result, strlen(names[i].name));
220 }
221
222 return result;
223 }
224
225 static void
print_names(unsigned int value,named_item names[],unsigned int length,unsigned int max_len)226 print_names(unsigned int value,
227 named_item names[],
228 unsigned int length,
229 unsigned int max_len)
230 {
231 unsigned int i;
232
233 if (max_len == 0) {
234 max_len = get_max_len(names, length);
235 }
236
237 for (i = 0; i < length; i++) {
238 unsigned int field = BIT_EXTRACT_LE(value,
239 names[i].low_bit,
240 names[i].high_bit + 1);
241 if (names[i].images == X2_IMAGES) {
242 printf(" %-*s = %.1f\n",
243 max_len,
244 names[i].name,
245 (double)field / 2.0);
246 } else if (names[i].images == MINUS1_IMAGES) {
247 printf(" %-*s = 0x%0llx (%llu)\n",
248 max_len,
249 names[i].name,
250 (unsigned long long)field + 1ULL,
251 (unsigned long long)field + 1ULL);
252 } else if (names[i].images == NIL_IMAGES
253 || names[i].images[field] == NULL) {
254 printf(" %-*s = 0x%0x (%u)\n",
255 max_len,
256 names[i].name,
257 field,
258 field);
259 } else {
260 printf(" %-*s = %s\n",
261 max_len,
262 names[i].name,
263 names[i].images[field]);
264 }
265 }
266 }
267
268 static ccstring bools[] = { "false",
269 "true" };
270
271 typedef enum {
272 VENDOR_UNKNOWN,
273 VENDOR_INTEL,
274 VENDOR_AMD,
275 VENDOR_CYRIX,
276 VENDOR_VIA,
277 VENDOR_TRANSMETA,
278 VENDOR_UMC,
279 VENDOR_NEXGEN,
280 VENDOR_RISE,
281 VENDOR_SIS,
282 VENDOR_NSC,
283 VENDOR_VORTEX,
284 VENDOR_RDC,
285 VENDOR_HYGON,
286 VENDOR_ZHAOXIN,
287 } vendor_t;
288
289 typedef enum {
290 HYPERVISOR_UNKNOWN,
291 HYPERVISOR_VMWARE,
292 HYPERVISOR_XEN,
293 HYPERVISOR_KVM,
294 HYPERVISOR_MICROSOFT,
295 HYPERVISOR_ACRN,
296 } hypervisor_t;
297
298 #define __F(v) ((v) & 0x0ff00f00)
299 #define __M(v) ((v) & 0x000f00f0)
300 #define __FM(v) ((v) & 0x0fff0ff0)
301 #define __FMS(v) ((v) & 0x0fff0fff)
302
303 #define __TF(v) ((v) & 0x0ff03f00)
304 #define __TFM(v) ((v) & 0x0fff3ff0)
305 #define __TFMS(v) ((v) & 0x0fff3fff)
306
307 #define _T(v) ((v) << 12)
308 #define _F(v) ((v) << 8)
309 #define _M(v) ((v) << 4)
310 #define _S(v) (v)
311 #define _XF(v) ((v) << 20)
312 #define _XM(v) ((v) << 16)
313
314 #define __B(v) ((v) & 0x000000ff)
315 #define _B(v) (v)
316
317 #define _FM(xf,f,xm,m) (_XF(xf) + _F(f) + _XM(xm) + _M(m))
318 #define _FMS(xf,f,xm,m,s) (_XF(xf) + _F(f) + _XM(xm) + _M(m) + _S(s))
319
320 #define START \
321 if (0)
322 #define F(xf,f,...) \
323 else if (__F(val) == _XF(xf) +_F(f) ) ACT(__VA_ARGS__)
324 #define FM(xf,f,xm,m,...) \
325 else if (__FM(val) == _XF(xf)+_XM(xm)+_F(f)+_M(m) ) ACT(__VA_ARGS__)
326 #define FMS(xf,f,xm,m,s,...) \
327 else if (__FMS(val) == _XF(xf)+_XM(xm)+_F(f)+_M(m)+_S(s) ) ACT(__VA_ARGS__)
328 #define TF(t,xf,f,...) \
329 else if (__TF(val) == _T(t)+_XF(xf) +_F(f) ) ACT(__VA_ARGS__)
330 #define TFM(t,xf,f,xm,m,...) \
331 else if (__TFM(val) == _T(t)+_XF(xf)+_XM(xm)+_F(f)+_M(m) ) ACT(__VA_ARGS__)
332 #define TFMS(t,xf,f,xm,m,s,...) \
333 else if (__TFMS(val) == _T(t)+_XF(xf)+_XM(xm)+_F(f)+_M(m)+_S(s) ) ACT(__VA_ARGS__)
334 #define FQ(xf,f,q,...) \
335 else if (__F(val) == _XF(xf) +_F(f) && (stash) && (q)) ACT(__VA_ARGS__)
336 #define FMQ(xf,f,xm,m,q,...) \
337 else if (__FM(val) == _XF(xf)+_XM(xm)+_F(f)+_M(m) && (stash) && (q)) ACT(__VA_ARGS__)
338 #define FMSQ(xf,f,xm,m,s,q,...) \
339 else if (__FMS(val) == _XF(xf)+_XM(xm)+_F(f)+_M(m)+_S(s) && (stash) && (q)) ACT(__VA_ARGS__)
340 #define DEFAULT(...) \
341 else ACT(__VA_ARGS__)
342 #define FALLBACK(...) \
343 else __VA_ARGS__
344
345 typedef struct {
346 vendor_t vendor;
347 boolean saw_4;
348 boolean saw_b;
349 boolean saw_1f;
350 unsigned int val_0_eax;
351 unsigned int val_1_eax;
352 unsigned int val_1_ebx;
353 unsigned int val_1_ecx;
354 unsigned int val_1_edx;
355 unsigned int val_4_eax;
356 unsigned int val_b_eax[2];
357 unsigned int val_b_ebx[2];
358 unsigned int val_1f_eax[6];
359 unsigned int val_1f_ebx[6];
360 unsigned int val_1f_ecx[6];
361 unsigned int val_80000001_eax;
362 unsigned int val_80000001_ebx;
363 unsigned int val_80000001_ecx;
364 unsigned int val_80000001_edx;
365 unsigned int val_80000008_ecx;
366 unsigned int val_8000001e_ebx;
367 unsigned int transmeta_proc_rev;
368 char brand[48+1];
369 char transmeta_info[64+1];
370 char override_brand[48*2+1];
371 char soc_brand[48+1];
372 hypervisor_t hypervisor;
373
374 struct mp {
375 const char* method;
376 unsigned int cores;
377 unsigned int hyperthreads;
378 } mp;
379
380 struct br {
381 boolean mobile;
382
383 struct /* Intel */ {
384 boolean celeron;
385 boolean core;
386 boolean pentium;
387 boolean atom;
388 boolean xeon_mp;
389 boolean xeon;
390 boolean pentium_m;
391 boolean pentium_d;
392 boolean extreme;
393 boolean generic;
394 boolean scalable;
395 boolean u_line;
396 boolean y_line;
397 boolean g_line;
398 boolean i_8000;
399 boolean i_10000;
400 boolean cc150;
401 };
402 struct /* AMD */ {
403 boolean athlon_lv;
404 boolean athlon_xp;
405 boolean duron;
406 boolean athlon;
407 boolean sempron;
408 boolean phenom;
409 boolean series;
410 boolean a_series;
411 boolean c_series;
412 boolean e_series;
413 boolean g_series;
414 boolean r_series;
415 boolean z_series;
416 boolean geode;
417 boolean turion;
418 boolean neo;
419 boolean athlon_fx;
420 boolean athlon_mp;
421 boolean duron_mp;
422 boolean opteron;
423 boolean fx;
424 boolean firepro;
425 boolean ultra;
426 boolean t_suffix;
427 boolean ryzen;
428 boolean epyc;
429 boolean epyc_3000;
430 boolean montage;
431
432 boolean embedded;
433 int cores;
434 };
435 struct /* Cyrix */ {
436 boolean mediagx;
437 };
438 struct /* VIA */ {
439 boolean c7;
440 boolean c7m;
441 boolean c7d;
442 boolean eden;
443 boolean zhaoxin;
444 };
445 } br;
446 struct bri {
447 boolean desktop_pentium;
448 boolean desktop_celeron;
449 boolean mobile_pentium;
450 boolean mobile_pentium_m;
451 boolean mobile_celeron;
452 boolean xeon_mp;
453 boolean xeon;
454 } bri;
455
456 /* ==============implications============== */
457 /* PII (F6, M5) PIII (F6, M7) */
458 /* ---------------------- --------------- */
459 boolean L2_4w_1Mor2M; /* Xeon Xeon */
460 boolean L2_4w_512K; /* normal, Mobile or Xeon normal or Xeon */
461 boolean L2_4w_256K; /* Mobile - */
462 boolean L2_8w_1Mor2M; /* - Xeon */
463 boolean L2_8w_512K; /* - normal */
464 boolean L2_8w_256K; /* - normal or Xeon */
465 /* none */ /* Celeron - */
466
467 boolean L2_2M; /* Nocona lacks, Irwindale has */
468 /* Conroe has more, Allendale has this */
469 boolean L2_6M; /* Yorkfield C1/E0 has this, M1/R0 has less */
470 boolean L3; /* Cranford lacks, Potomac has */
471
472 boolean L2_256K; /* Barton has more, Thorton has this */
473 boolean L2_512K; /* Toledo has more, Manchester E6 has this */
474 } code_stash_t;
475
476 #define NIL_STASH { VENDOR_UNKNOWN, \
477 FALSE, FALSE, FALSE, \
478 0, 0, 0, 0, 0, 0, \
479 { 0, 0 }, \
480 { 0, 0 }, \
481 { 0, 0, 0, 0, 0, 0 }, \
482 { 0, 0, 0, 0, 0, 0 }, \
483 { 0, 0, 0, 0, 0, 0 }, \
484 0, 0, 0, 0, 0, 0, 0, \
485 "", "", "", "", \
486 HYPERVISOR_UNKNOWN, \
487 { NULL, -1, -1 }, \
488 { FALSE, \
489 { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, \
490 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, \
491 FALSE, FALSE, FALSE }, \
492 { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, \
493 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, \
494 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, \
495 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, \
496 FALSE, 0 }, \
497 { FALSE }, \
498 { FALSE, FALSE, FALSE, FALSE, FALSE } }, \
499 { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, \
500 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, \
501 FALSE, FALSE, FALSE, \
502 FALSE, FALSE }
503
504 static void
decode_amd_model(const code_stash_t * stash,const char ** brand_pre,const char ** brand_post,char * proc)505 decode_amd_model(const code_stash_t* stash,
506 const char** brand_pre,
507 const char** brand_post,
508 char* proc)
509 {
510 *brand_pre = NULL;
511 *brand_post = NULL;
512 *proc = '\0';
513
514 if (stash == NULL) return;
515
516 if (__F(stash->val_1_eax) == _XF(0) + _F(15)
517 && __M(stash->val_1_eax) < _XM(4) + _M(0)) {
518 /*
519 ** Algorithm from:
520 ** Revision Guide for AMD Athlon 64 and AMD Opteron Processors
521 ** (25759 Rev 3.79), Constructing the Processor Name String.
522 ** But using only the Processor numbers.
523 */
524 unsigned int bti;
525 unsigned int NN;
526
527 if (__B(stash->val_1_ebx) != 0) {
528 bti = BIT_EXTRACT_LE(__B(stash->val_1_ebx), 5, 8) << 2;
529 NN = BIT_EXTRACT_LE(__B(stash->val_1_ebx), 0, 5);
530 } else if (BIT_EXTRACT_LE(stash->val_80000001_ebx, 0, 12) != 0) {
531 bti = BIT_EXTRACT_LE(stash->val_80000001_ebx, 6, 12);
532 NN = BIT_EXTRACT_LE(stash->val_80000001_ebx, 0, 6);
533 } else {
534 return;
535 }
536
537 #define XX (22 + NN)
538 #define YY (38 + 2*NN)
539 #define ZZ (24 + NN)
540 #define TT (24 + NN)
541 #define RR (45 + 5*NN)
542 #define EE ( 9 + NN)
543
544 switch (bti) {
545 case 0x04:
546 *brand_pre = "AMD Athlon(tm) 64";
547 sprintf(proc, "Processor %02d00+", XX);
548 break;
549 case 0x05:
550 *brand_pre = "AMD Athlon(tm) 64 X2 Dual Core";
551 sprintf(proc, "Processor %02d00+", XX);
552 break;
553 case 0x06:
554 *brand_pre = "AMD Athlon(tm) 64";
555 sprintf(proc, "FX-%02d", ZZ);
556 *brand_post = "Dual Core";
557 break;
558 case 0x08:
559 *brand_pre = "AMD Athlon(tm) 64";
560 sprintf(proc, "Processor %02d00+", XX);
561 break;
562 case 0x09:
563 *brand_pre = "AMD Athlon(tm) 64";
564 sprintf(proc, "Processor %02d00+", XX);
565 break;
566 case 0x0a:
567 *brand_pre = "AMD Turion(tm) Mobile Technology";
568 sprintf(proc, "ML-%02d", XX);
569 break;
570 case 0x0b:
571 *brand_pre = "AMD Turion(tm) Mobile Technology";
572 sprintf(proc, "MT-%02d", XX);
573 break;
574 case 0x0c:
575 case 0x0d:
576 *brand_pre = "AMD Opteron(tm)";
577 sprintf(proc, "Processor 1%02d", YY);
578 break;
579 case 0x0e:
580 *brand_pre = "AMD Opteron(tm)";
581 sprintf(proc, "Processor 1%02d HE", YY);
582 break;
583 case 0x0f:
584 *brand_pre = "AMD Opteron(tm)";
585 sprintf(proc, "Processor 1%02d EE", YY);
586 break;
587 case 0x10:
588 case 0x11:
589 *brand_pre = "AMD Opteron(tm)";
590 sprintf(proc, "Processor 2%02d", YY);
591 break;
592 case 0x12:
593 *brand_pre = "AMD Opteron(tm)";
594 sprintf(proc, "Processor 2%02d HE", YY);
595 break;
596 case 0x13:
597 *brand_pre = "AMD Opteron(tm)";
598 sprintf(proc, "Processor 2%02d EE", YY);
599 break;
600 case 0x14:
601 case 0x15:
602 *brand_pre = "AMD Opteron(tm)";
603 sprintf(proc, "Processor 8%02d", YY);
604 break;
605 case 0x16:
606 *brand_pre = "AMD Opteron(tm)";
607 sprintf(proc, "Processor 8%02d HE", YY);
608 break;
609 case 0x17:
610 *brand_pre = "AMD Opteron(tm)";
611 sprintf(proc, "Processor 8%02d EE", YY);
612 break;
613 case 0x18:
614 *brand_pre = "AMD Athlon(tm) 64";
615 sprintf(proc, "Processor %02d00+", EE);
616 break;
617 case 0x1d:
618 *brand_pre = "Mobile AMD Athlon(tm) XP-M";
619 sprintf(proc, "Processor %02d00+", XX);
620 break;
621 case 0x1e:
622 *brand_pre = "Mobile AMD Athlon(tm) XP-M";
623 sprintf(proc, "Processor %02d00+", XX);
624 break;
625 case 0x20:
626 *brand_pre = "AMD Athlon(tm) XP";
627 sprintf(proc, "Processor %02d00+", XX);
628 break;
629 case 0x21:
630 case 0x23:
631 *brand_pre = "Mobile AMD Sempron(tm)";
632 sprintf(proc, "Processor %02d00+", TT);
633 break;
634 case 0x22:
635 case 0x26:
636 *brand_pre = "AMD Sempron(tm)";
637 sprintf(proc, "Processor %02d00+", TT);
638 break;
639 case 0x24:
640 *brand_pre = "AMD Athlon(tm) 64";
641 sprintf(proc, "FX-%02d", ZZ);
642 break;
643 case 0x29:
644 *brand_pre = "Dual Core AMD Opteron(tm)";
645 sprintf(proc, "Processor 1%02d SE", RR);
646 break;
647 case 0x2a:
648 *brand_pre = "Dual Core AMD Opteron(tm)";
649 sprintf(proc, "Processor 2%02d SE", RR);
650 break;
651 case 0x2b:
652 *brand_pre = "Dual Core AMD Opteron(tm)";
653 sprintf(proc, "Processor 8%02d SE", RR);
654 break;
655 case 0x2c:
656 case 0x2d:
657 case 0x38:
658 case 0x3b:
659 *brand_pre = "Dual Core AMD Opteron(tm)";
660 sprintf(proc, "Processor 1%02d", RR);
661 break;
662 case 0x30:
663 case 0x31:
664 case 0x39:
665 case 0x3c:
666 *brand_pre = "Dual Core AMD Opteron(tm)";
667 sprintf(proc, "Processor 2%02d", RR);
668 break;
669 case 0x34:
670 case 0x35:
671 case 0x3a:
672 case 0x3d:
673 *brand_pre = "Dual Core AMD Opteron(tm)";
674 sprintf(proc, "Processor 8%02d", RR);
675 break;
676 case 0x2e:
677 *brand_pre = "Dual Core AMD Opteron(tm)";
678 sprintf(proc, "Processor 1%02d HE", RR);
679 break;
680 case 0x2f:
681 *brand_pre = "Dual Core AMD Opteron(tm)";
682 sprintf(proc, "Processor 1%02d EE", RR);
683 break;
684 case 0x32:
685 *brand_pre = "Dual Core AMD Opteron(tm)";
686 sprintf(proc, "Processor 2%02d HE", RR);
687 break;
688 case 0x33:
689 *brand_pre = "Dual Core AMD Opteron(tm)";
690 sprintf(proc, "Processor 2%02d EE", RR);
691 break;
692 case 0x36:
693 *brand_pre = "Dual Core AMD Opteron(tm)";
694 sprintf(proc, "Processor 8%02d HE", RR);
695 break;
696 case 0x37:
697 *brand_pre = "Dual Core AMD Opteron(tm)";
698 sprintf(proc, "Processor 8%02d EE", RR);
699 break;
700 }
701
702 #undef XX
703 #undef YY
704 #undef ZZ
705 #undef TT
706 #undef RR
707 #undef EE
708 } else if (__F(stash->val_1_eax) == _XF(0) + _F(15)
709 && __M(stash->val_1_eax) >= _XM(4) + _M(0)) {
710 /*
711 ** Algorithm from:
712 ** Revision Guide for AMD NPT Family 0Fh Processors (33610 Rev 3.46),
713 ** Constructing the Processor Name String.
714 ** But using only the Processor numbers.
715 */
716 unsigned int bti;
717 unsigned int pwrlmt;
718 unsigned int NN;
719 unsigned int pkgtype;
720 unsigned int cmpcap;
721
722 pwrlmt = ((BIT_EXTRACT_LE(stash->val_80000001_ebx, 6, 9) << 1)
723 + BIT_EXTRACT_LE(stash->val_80000001_ebx, 14, 15));
724 bti = BIT_EXTRACT_LE(stash->val_80000001_ebx, 9, 14);
725 NN = ((BIT_EXTRACT_LE(stash->val_80000001_ebx, 15, 16) << 5)
726 + BIT_EXTRACT_LE(stash->val_80000001_ebx, 0, 5));
727 pkgtype = BIT_EXTRACT_LE(stash->val_80000001_eax, 4, 6);
728 cmpcap = ((BIT_EXTRACT_LE(stash->val_80000008_ecx, 0, 8) > 0)
729 ? 0x1 : 0x0);
730
731 #define RR (NN - 1)
732 #define PP (26 + NN)
733 #define TT (15 + cmpcap*10 + NN)
734 #define ZZ (57 + NN)
735 #define YY (29 + NN)
736
737 #define PKGTYPE(pkgtype) ((pkgtype) << 11)
738 #define CMPCAP(cmpcap) ((cmpcap) << 9)
739 #define BTI(bti) ((bti) << 4)
740 #define PWRLMT(pwrlmt) (pwrlmt)
741
742 switch (PKGTYPE(pkgtype) + CMPCAP(cmpcap) + BTI(bti) + PWRLMT(pwrlmt)) {
743 /* Table 7: Name String Table for F (1207) and Fr3 (1207) Processors */
744 case PKGTYPE(1) + CMPCAP(0) + BTI(1) + PWRLMT(2):
745 *brand_pre = "AMD Opteron(tm)";
746 sprintf(proc, "Processor 22%02d EE", RR);
747 break;
748 case PKGTYPE(1) + CMPCAP(1) + BTI(1) + PWRLMT(2):
749 *brand_pre = "Dual-Core AMD Opteron(tm)";
750 sprintf(proc, "Processor 22%02d EE", RR);
751 break;
752 case PKGTYPE(1) + CMPCAP(1) + BTI(0) + PWRLMT(2) :
753 *brand_pre = "Dual-Core AMD Opteron(tm)";
754 sprintf(proc, "Processor 12%02d EE", RR);
755 break;
756 case PKGTYPE(1) + CMPCAP(1) + BTI(0) + PWRLMT(6):
757 *brand_pre = "Dual-Core AMD Opteron(tm)";
758 sprintf(proc, "Processor 12%02d HE", RR);
759 break;
760 case PKGTYPE(1) + CMPCAP(1) + BTI(1) + PWRLMT(6):
761 *brand_pre = "Dual-Core AMD Opteron(tm)";
762 sprintf(proc, "Processor 22%02d HE", RR);
763 break;
764 case PKGTYPE(1) + CMPCAP(1) + BTI(1) + PWRLMT(10):
765 *brand_pre = "Dual-Core AMD Opteron(tm)";
766 sprintf(proc, "Processor 22%02d", RR);
767 break;
768 case PKGTYPE(1) + CMPCAP(1) + BTI(1) + PWRLMT(12):
769 *brand_pre = "Dual-Core AMD Opteron(tm)";
770 sprintf(proc, "Processor 22%02d SE", RR);
771 break;
772 case PKGTYPE(1) + CMPCAP(1) + BTI(4) + PWRLMT(2):
773 *brand_pre = "Dual-Core AMD Opteron(tm)";
774 sprintf(proc, "Processor 82%02d EE", RR);
775 break;
776 case PKGTYPE(1) + CMPCAP(1) + BTI(4) + PWRLMT(6):
777 *brand_pre = "Dual-Core AMD Opteron(tm)";
778 sprintf(proc, "Processor 82%02d HE", RR);
779 break;
780 case PKGTYPE(1) + CMPCAP(1) + BTI(4) + PWRLMT(10):
781 *brand_pre = "Dual-Core AMD Opteron(tm)";
782 sprintf(proc, "Processor 82%02d", RR);
783 break;
784 case PKGTYPE(1) + CMPCAP(1) + BTI(4) + PWRLMT(12):
785 *brand_pre = "Dual-Core AMD Opteron(tm)";
786 sprintf(proc, "Processor 82%02d SE", RR);
787 break;
788 case PKGTYPE(1) + CMPCAP(1) + BTI(6) + PWRLMT(14):
789 *brand_pre = "AMD Athlon(tm) 64";
790 sprintf(proc, "FX-%02d", ZZ);
791 break;
792 /* Table 8: Name String Table for AM2 and ASB1 Processors */
793 case PKGTYPE(3) + CMPCAP(0) + BTI(1) + PWRLMT(5):
794 *brand_pre = "AMD Sempron(tm)";
795 sprintf(proc, "Processor LE-1%02d0", RR);
796 break;
797 case PKGTYPE(3) + CMPCAP(0) + BTI(2) + PWRLMT(6):
798 *brand_pre = "AMD Athlon(tm)";
799 sprintf(proc, "Processor LE-1%02d0", ZZ);
800 break;
801 case PKGTYPE(3) + CMPCAP(0) + BTI(3) + PWRLMT(6):
802 *brand_pre = "AMD Athlon(tm)";
803 sprintf(proc, "Processor 1%02d0B", ZZ);
804 break;
805 case PKGTYPE(3) + CMPCAP(0) + BTI(4) + PWRLMT(1):
806 case PKGTYPE(3) + CMPCAP(0) + BTI(4) + PWRLMT(2):
807 case PKGTYPE(3) + CMPCAP(0) + BTI(4) + PWRLMT(3):
808 case PKGTYPE(3) + CMPCAP(0) + BTI(4) + PWRLMT(4):
809 case PKGTYPE(3) + CMPCAP(0) + BTI(4) + PWRLMT(5):
810 case PKGTYPE(3) + CMPCAP(0) + BTI(4) + PWRLMT(8):
811 *brand_pre = "AMD Athlon(tm) 64";
812 sprintf(proc, "Processor %02d00+", TT);
813 break;
814 case PKGTYPE(3) + CMPCAP(0) + BTI(5) + PWRLMT(2):
815 *brand_pre = "AMD Sempron(tm)";
816 sprintf(proc, "Processor %02d50p", RR);
817 break;
818 case PKGTYPE(3) + CMPCAP(0) + BTI(6) + PWRLMT(4):
819 case PKGTYPE(3) + CMPCAP(0) + BTI(6) + PWRLMT(8):
820 *brand_pre = "AMD Sempron(tm)";
821 sprintf(proc, "Processor %02d00+", TT);
822 break;
823 case PKGTYPE(3) + CMPCAP(0) + BTI(7) + PWRLMT(1):
824 case PKGTYPE(3) + CMPCAP(0) + BTI(7) + PWRLMT(2):
825 *brand_pre = "AMD Sempron(tm)";
826 sprintf(proc, "Processor %02d0U", TT);
827 break;
828 case PKGTYPE(3) + CMPCAP(0) + BTI(8) + PWRLMT(2):
829 case PKGTYPE(3) + CMPCAP(0) + BTI(8) + PWRLMT(3):
830 *brand_pre = "AMD Athlon(tm)";
831 sprintf(proc, "Processor %02d50e", TT);
832 break;
833 case PKGTYPE(3) + CMPCAP(0) + BTI(9) + PWRLMT(2):
834 *brand_pre = "AMD Athlon(tm) Neo";
835 sprintf(proc, "Processor MV-%02d", TT);
836 break;
837 case PKGTYPE(3) + CMPCAP(0) + BTI(12) + PWRLMT(2):
838 *brand_pre = "AMD Sempron(tm)";
839 sprintf(proc, "Processor 2%02dU", RR);
840 break;
841 case PKGTYPE(3) + CMPCAP(1) + BTI(1) + PWRLMT(6):
842 *brand_pre = "Dual-Core AMD Opteron(tm)";
843 sprintf(proc, "Processor 12%02d HE", RR);
844 break;
845 case PKGTYPE(3) + CMPCAP(1) + BTI(1) + PWRLMT(10):
846 *brand_pre = "Dual-Core AMD Opteron(tm)";
847 sprintf(proc, "Processor 12%02d", RR);
848 break;
849 case PKGTYPE(3) + CMPCAP(1) + BTI(1) + PWRLMT(12):
850 *brand_pre = "Dual-Core AMD Opteron(tm)";
851 sprintf(proc, "Processor 12%02d SE", RR);
852 break;
853 case PKGTYPE(3) + CMPCAP(1) + BTI(3) + PWRLMT(3):
854 *brand_pre = "AMD Athlon(tm) X2 Dual Core";
855 sprintf(proc, "Processor BE-2%02d0", TT);
856 break;
857 case PKGTYPE(3) + CMPCAP(1) + BTI(4) + PWRLMT(1):
858 case PKGTYPE(3) + CMPCAP(1) + BTI(4) + PWRLMT(2):
859 case PKGTYPE(3) + CMPCAP(1) + BTI(4) + PWRLMT(6):
860 case PKGTYPE(3) + CMPCAP(1) + BTI(4) + PWRLMT(8):
861 case PKGTYPE(3) + CMPCAP(1) + BTI(4) + PWRLMT(12):
862 *brand_pre = "AMD Athlon(tm) 64 X2 Dual Core";
863 sprintf(proc, "Processor %02d00+", TT);
864 break;
865 case PKGTYPE(3) + CMPCAP(1) + BTI(5) + PWRLMT(12):
866 *brand_pre = "AMD Athlon(tm) 64";
867 sprintf(proc, "FX-%02d", ZZ);
868 *brand_post = "Dual Core";
869 break;
870 case PKGTYPE(3) + CMPCAP(1) + BTI(6) + PWRLMT(6):
871 *brand_pre = "AMD Sempron(tm) Dual Core";
872 sprintf(proc, "Processor %02d00", RR);
873 break;
874 case PKGTYPE(3) + CMPCAP(1) + BTI(7) + PWRLMT(3):
875 *brand_pre = "AMD Athlon(tm) Dual Core";
876 sprintf(proc, "Processor %02d50e", TT);
877 break;
878 case PKGTYPE(3) + CMPCAP(1) + BTI(7) + PWRLMT(6):
879 case PKGTYPE(3) + CMPCAP(1) + BTI(7) + PWRLMT(7):
880 *brand_pre = "AMD Athlon(tm) Dual Core";
881 sprintf(proc, "Processor %02d00B", TT);
882 break;
883 case PKGTYPE(3) + CMPCAP(1) + BTI(8) + PWRLMT(3):
884 *brand_pre = "AMD Athlon(tm) Dual Core";
885 sprintf(proc, "Processor %02d50B", TT);
886 break;
887 case PKGTYPE(3) + CMPCAP(1) + BTI(9) + PWRLMT(1):
888 *brand_pre = "AMD Athlon(tm) X2 Dual Core";
889 sprintf(proc, "Processor %02d50e", TT);
890 break;
891 case PKGTYPE(3) + CMPCAP(1) + BTI(10) + PWRLMT(1):
892 case PKGTYPE(3) + CMPCAP(1) + BTI(10) + PWRLMT(2):
893 *brand_pre = "AMD Athlon(tm) Neo X2 Dual Core";
894 sprintf(proc, "Processor %02d50e", TT);
895 break;
896 case PKGTYPE(3) + CMPCAP(1) + BTI(11) + PWRLMT(0):
897 *brand_pre = "AMD Turion(tm) Neo X2 Dual Core";
898 sprintf(proc, "Processor L6%02d", RR);
899 break;
900 case PKGTYPE(3) + CMPCAP(1) + BTI(12) + PWRLMT(0):
901 *brand_pre = "AMD Turion(tm) Neo X2 Dual Core";
902 sprintf(proc, "Processor L3%02d", RR);
903 break;
904 /* Table 9: Name String Table for S1g1 Processors */
905 case PKGTYPE(0) + CMPCAP(0) + BTI(1) + PWRLMT(2):
906 *brand_pre = "AMD Athlon(tm) 64";
907 sprintf(proc, "Processor %02d00+", TT);
908 break;
909 case PKGTYPE(0) + CMPCAP(0) + BTI(2) + PWRLMT(12):
910 *brand_pre = "AMD Turion(tm) 64 Mobile Technology";
911 sprintf(proc, "MK-%02d", YY);
912 break;
913 case PKGTYPE(0) + CMPCAP(0) + BTI(3) + PWRLMT(1):
914 *brand_pre = "Mobile AMD Sempron(tm)";
915 sprintf(proc, "Processor %02d00+", TT);
916 break;
917 case PKGTYPE(0) + CMPCAP(0) + BTI(3) + PWRLMT(6):
918 case PKGTYPE(0) + CMPCAP(0) + BTI(3) + PWRLMT(12):
919 *brand_pre = "Mobile AMD Sempron(tm)";
920 sprintf(proc, "Processor %02d00+", PP);
921 break;
922 case PKGTYPE(0) + CMPCAP(0) + BTI(4) + PWRLMT(2):
923 *brand_pre = "AMD Sempron(tm)";
924 sprintf(proc, "Processor %02d00+", TT);
925 break;
926 case PKGTYPE(0) + CMPCAP(0) + BTI(6) + PWRLMT(4):
927 case PKGTYPE(0) + CMPCAP(0) + BTI(6) + PWRLMT(6):
928 case PKGTYPE(0) + CMPCAP(0) + BTI(6) + PWRLMT(12):
929 *brand_pre = "AMD Athlon(tm)";
930 sprintf(proc, "Processor TF-%02d", TT);
931 break;
932 case PKGTYPE(0) + CMPCAP(0) + BTI(7) + PWRLMT(3):
933 *brand_pre = "AMD Athlon(tm)";
934 sprintf(proc, "Processor L1%02d", RR);
935 break;
936 case PKGTYPE(0) + CMPCAP(1) + BTI(1) + PWRLMT(12):
937 *brand_pre = "AMD Sempron(tm)";
938 sprintf(proc, "Processor TJ-%02d", YY);
939 break;
940 case PKGTYPE(0) + CMPCAP(1) + BTI(2) + PWRLMT(12):
941 *brand_pre = "AMD Turion(tm) 64 X2 Mobile Technology";
942 sprintf(proc, "Processor TL-%02d", YY);
943 break;
944 case PKGTYPE(0) + CMPCAP(1) + BTI(3) + PWRLMT(4):
945 case PKGTYPE(0) + CMPCAP(1) + BTI(3) + PWRLMT(12):
946 *brand_pre = "AMD Turion(tm) 64 X2 Dual-Core";
947 sprintf(proc, "Processor TK-%02d", YY);
948 break;
949 case PKGTYPE(0) + CMPCAP(1) + BTI(5) + PWRLMT(4):
950 *brand_pre = "AMD Turion(tm) 64 X2 Dual Core";
951 sprintf(proc, "Processor %02d00+", TT);
952 break;
953 case PKGTYPE(0) + CMPCAP(1) + BTI(6) + PWRLMT(2):
954 *brand_pre = "AMD Turion(tm) X2 Dual Core";
955 sprintf(proc, "Processor L3%02d", RR);
956 break;
957 case PKGTYPE(0) + CMPCAP(1) + BTI(7) + PWRLMT(4):
958 *brand_pre = "AMD Turion(tm) X2 Dual Core";
959 sprintf(proc, "Processor L5%02d", RR);
960 break;
961 }
962
963 #undef RR
964 #undef PP
965 #undef TT
966 #undef ZZ
967 #undef YY
968 } else if (__F(stash->val_1_eax) == _XF(1) + _F(15)
969 || __F(stash->val_1_eax) == _XF(2) + _F(15)
970 || __F(stash->val_1_eax) == _XF(3) + _F(15)
971 || __F(stash->val_1_eax) == _XF(5) + _F(15)) {
972 /*
973 ** Algorithm from:
974 ** AMD Revision Guide for AMD Family 10h Processors (41322 Rev 3.74)
975 ** AMD Revision Guide for AMD Family 11h Processors (41788 Rev 3.08)
976 ** AMD Revision Guide for AMD Family 12h Processors (44739 Rev 3.10)
977 ** AMD Revision Guide for AMD Family 14h Models 00h-0Fh Processors
978 ** (47534 Rev 3.00)
979 ** But using only the Processor numbers.
980 */
981 unsigned int str1;
982 unsigned int str2;
983 unsigned int pg;
984 unsigned int partialmodel;
985 unsigned int pkgtype;
986 unsigned int nc;
987 const char* s1;
988 const char* s2;
989
990 str2 = BIT_EXTRACT_LE(stash->val_80000001_ebx, 0, 4);
991 partialmodel = BIT_EXTRACT_LE(stash->val_80000001_ebx, 4, 11);
992 str1 = BIT_EXTRACT_LE(stash->val_80000001_ebx, 11, 15);
993 pg = BIT_EXTRACT_LE(stash->val_80000001_ebx, 15, 16);
994 pkgtype = BIT_EXTRACT_LE(stash->val_80000001_ebx, 28, 32);
995 nc = BIT_EXTRACT_LE(stash->val_80000008_ecx, 0, 8);
996
997 #define NC(nc) ((nc) << 9)
998 #define PG(pg) ((pg) << 8)
999 #define STR1(str1) ((str1) << 4)
1000 #define STR2(str2) (str2)
1001
1002 /*
1003 ** In every String2 Values table, there were special cases for
1004 ** pg == 0 && str2 == 15 which defined them as the empty string.
1005 ** But that produces the same result as an undefined string, so
1006 ** don't bother trying to handle them.
1007 */
1008 if (__F(stash->val_1_eax) == _XF(1) + _F(15)) {
1009 if (pkgtype >= 2) {
1010 partialmodel--;
1011 }
1012
1013 /* Family 10h tables */
1014 switch (pkgtype) {
1015 case 0:
1016 /* 41322 3.74: table 14: String1 Values for Fr2, Fr5, and Fr6 (1207) Processors */
1017 switch (PG(pg) + NC(nc) + STR1(str1)) {
1018 case PG(0) + NC(3) + STR1(0): *brand_pre = "Quad-Core AMD Opteron(tm)"; s1 = "Processor 83"; break;
1019 case PG(0) + NC(3) + STR1(1): *brand_pre = "Quad-Core AMD Opteron(tm)"; s1 = "Processor 23"; break;
1020 case PG(0) + NC(5) + STR1(0): *brand_pre = "Six-Core AMD Opteron(tm)"; s1 = "Processor 84"; break;
1021 case PG(0) + NC(5) + STR1(1): *brand_pre = "Six-Core AMD Opteron(tm)"; s1 = "Processor 24"; break;
1022 case PG(1) + NC(3) + STR1(1): *brand_pre = "Embedded AMD Opteron(tm)"; s1 = "Processor "; break;
1023 case PG(1) + NC(5) + STR1(1): *brand_pre = "Embedded AMD Opteron(tm)"; s1 = "Processor "; break;
1024 default: s1 = NULL; break;
1025 }
1026 /* 41322 3.74: table 15: String2 Values for Fr2, Fr5, and Fr6 (1207) Processors */
1027 switch (PG(pg) + NC(nc) + STR2(str2)) {
1028 case PG(0) + NC(3) + STR2(10): s2 = " SE"; break;
1029 case PG(0) + NC(3) + STR2(11): s2 = " HE"; break;
1030 case PG(0) + NC(3) + STR2(12): s2 = " EE"; break;
1031 case PG(0) + NC(5) + STR2(0): s2 = " SE"; break;
1032 case PG(0) + NC(5) + STR2(1): s2 = " HE"; break;
1033 case PG(0) + NC(5) + STR2(2): s2 = " EE"; break;
1034 case PG(1) + NC(3) + STR2(1): s2 = "GF HE"; break;
1035 case PG(1) + NC(3) + STR2(2): s2 = "HF HE"; break;
1036 case PG(1) + NC(3) + STR2(3): s2 = "VS"; break;
1037 case PG(1) + NC(3) + STR2(4): s2 = "QS HE"; break;
1038 case PG(1) + NC(3) + STR2(5): s2 = "NP HE"; break;
1039 case PG(1) + NC(3) + STR2(6): s2 = "KH HE"; break;
1040 case PG(1) + NC(3) + STR2(7): s2 = "KS HE"; break;
1041 case PG(1) + NC(5) + STR2(1): s2 = "QS"; break;
1042 case PG(1) + NC(5) + STR2(2): s2 = "KS HE"; break;
1043 default: s2 = NULL; break;
1044 }
1045 break;
1046 case 1:
1047 /* 41322 3.74: table 16: String1 Values for AM2r2 and AM3 Processors */
1048 switch (PG(pg) + NC(nc) + STR1(str1)) {
1049 case PG(0) + NC(0) + STR1(2): *brand_pre = "AMD Sempron(tm)"; s1 = "1"; break;
1050 /* This case obviously collides with one later */
1051 /* case PG(0) + NC(0) + STR1(3): *brand_pre = "AMD Athlon(tm) II"; s1 = "AMD Athlon(tm) II 1"; */
1052 case PG(0) + NC(0) + STR1(1): *brand_pre = "AMD Athlon(tm)"; s1 = ""; break;
1053 case PG(0) + NC(0) + STR1(3): *brand_pre = "AMD Athlon(tm) II X2"; s1 = "2"; break;
1054 case PG(0) + NC(0) + STR1(4): *brand_pre = "AMD Athlon(tm) II X2"; s1 = "B"; break;
1055 case PG(0) + NC(0) + STR1(5): *brand_pre = "AMD Athlon(tm) II X2"; s1 = ""; break;
1056 case PG(0) + NC(0) + STR1(7): *brand_pre = "AMD Phenom(tm) II X2"; s1 = "5"; break;
1057 case PG(0) + NC(0) + STR1(10): *brand_pre = "AMD Phenom(tm) II X2"; s1 = ""; break;
1058 case PG(0) + NC(0) + STR1(11): *brand_pre = "AMD Phenom(tm) II X2"; s1 = "B"; break;
1059 case PG(0) + NC(0) + STR1(12): *brand_pre = "AMD Sempron(tm) X2"; s1 = "1"; break;
1060 case PG(0) + NC(2) + STR1(0): *brand_pre = "AMD Phenom(tm)"; s1 = ""; break;
1061 case PG(0) + NC(2) + STR1(3): *brand_pre = "AMD Phenom(tm) II X3"; s1 = "B"; break;
1062 case PG(0) + NC(2) + STR1(4): *brand_pre = "AMD Phenom(tm) II X3"; s1 = ""; break;
1063 case PG(0) + NC(2) + STR1(7): *brand_pre = "AMD Phenom(tm) II X3"; s1 = "4"; break;
1064 case PG(0) + NC(2) + STR1(8): *brand_pre = "AMD Phenom(tm) II X3"; s1 = "7"; break;
1065 case PG(0) + NC(2) + STR1(10): *brand_pre = "AMD Phenom(tm) II X3"; s1 = ""; break;
1066 case PG(0) + NC(3) + STR1(0): *brand_pre = "Quad-Core AMD Opteron(tm)"; s1 = "Processor 13"; break;
1067 case PG(0) + NC(3) + STR1(2): *brand_pre = "AMD Phenom(tm)"; s1 = ""; break;
1068 case PG(0) + NC(3) + STR1(3): *brand_pre = "AMD Phenom(tm) II X4"; s1 = "9"; break;
1069 case PG(0) + NC(3) + STR1(4): *brand_pre = "AMD Phenom(tm) II X4"; s1 = "8"; break;
1070 case PG(0) + NC(3) + STR1(7): *brand_pre = "AMD Phenom(tm) II X4"; s1 = "B"; break;
1071 case PG(0) + NC(3) + STR1(8): *brand_pre = "AMD Phenom(tm) II X4"; s1 = ""; break;
1072 case PG(0) + NC(3) + STR1(10): *brand_pre = "AMD Athlon(tm) II X4"; s1 = "6"; break;
1073 case PG(0) + NC(3) + STR1(15): *brand_pre = "AMD Athlon(tm) II X4"; s1 = ""; break;
1074 case PG(0) + NC(5) + STR1(0): *brand_pre = "AMD Phenom(tm) II X6"; s1 = "1"; break;
1075 case PG(1) + NC(1) + STR1(1): *brand_pre = "AMD Athlon(tm) II XLT V"; s1 = ""; break;
1076 case PG(1) + NC(1) + STR1(2): *brand_pre = "AMD Athlon(tm) II XL V"; s1 = ""; break;
1077 case PG(1) + NC(3) + STR1(1): *brand_pre = "AMD Phenom(tm) II XLT Q"; s1 = ""; break;
1078 case PG(1) + NC(3) + STR1(2): *brand_pre = "AMD Phenom(tm) II X4"; s1 = "9"; break;
1079 case PG(1) + NC(3) + STR1(3): *brand_pre = "AMD Phenom(tm) II X4"; s1 = "8"; break;
1080 case PG(1) + NC(3) + STR1(4): *brand_pre = "AMD Phenom(tm) II X4"; s1 = "6"; break;
1081 default: s1 = NULL; break;
1082 }
1083 /* 41322 3.74: table 17: String2 Values for AM2r2 and AM3 Processors */
1084 switch (PG(pg) + NC(nc) + STR2(str2)) {
1085 case PG(0) + NC(0) + STR2(10): s2 = " Processor"; break;
1086 case PG(0) + NC(0) + STR2(11): s2 = "u Processor"; break;
1087 case PG(0) + NC(1) + STR2(3): s2 = "50 Dual-Core Processor"; break;
1088 case PG(0) + NC(1) + STR2(6): s2 = " Processor"; break;
1089 case PG(0) + NC(1) + STR2(7): s2 = "e Processor"; break;
1090 case PG(0) + NC(1) + STR2(9): s2 = "0 Processor"; break;
1091 case PG(0) + NC(1) + STR2(10): s2 = "0e Processor"; break;
1092 case PG(0) + NC(1) + STR2(11): s2 = "u Processor"; break;
1093 case PG(0) + NC(2) + STR2(0): s2 = "00 Triple-Core Processor"; break;
1094 case PG(0) + NC(2) + STR2(1): s2 = "00e Triple-Core Processor"; break;
1095 case PG(0) + NC(2) + STR2(2): s2 = "00B Triple-Core Processor"; break;
1096 case PG(0) + NC(2) + STR2(3): s2 = "50 Triple-Core Processor"; break;
1097 case PG(0) + NC(2) + STR2(4): s2 = "50e Triple-Core Processor"; break;
1098 case PG(0) + NC(2) + STR2(5): s2 = "50B Triple-Core Processor"; break;
1099 case PG(0) + NC(2) + STR2(6): s2 = " Processor"; break;
1100 case PG(0) + NC(2) + STR2(7): s2 = "e Processor"; break;
1101 case PG(0) + NC(2) + STR2(9): s2 = "0e Processor"; break;
1102 case PG(0) + NC(2) + STR2(10): s2 = "0 Processor"; break;
1103 case PG(0) + NC(3) + STR2(0): s2 = "00 Quad-Core Processor"; break;
1104 case PG(0) + NC(3) + STR2(1): s2 = "00e Quad-Core Processor"; break;
1105 case PG(0) + NC(3) + STR2(2): s2 = "00B Quad-Core Processor"; break;
1106 case PG(0) + NC(3) + STR2(3): s2 = "50 Quad-Core Processor"; break;
1107 case PG(0) + NC(3) + STR2(4): s2 = "50e Quad-Core Processor"; break;
1108 case PG(0) + NC(3) + STR2(5): s2 = "50B Quad-Core Processor"; break;
1109 case PG(0) + NC(3) + STR2(6): s2 = " Processor"; break;
1110 case PG(0) + NC(3) + STR2(7): s2 = "e Processor"; break;
1111 case PG(0) + NC(3) + STR2(9): s2 = "0e Processor"; break;
1112 case PG(0) + NC(3) + STR2(14): s2 = "0 Processor"; break;
1113 case PG(0) + NC(5) + STR2(0): s2 = "5T Processor"; break;
1114 case PG(0) + NC(5) + STR2(1): s2 = "0T Processor"; break;
1115 case PG(1) + NC(1) + STR2(1): s2 = "L Processor"; break;
1116 case PG(1) + NC(1) + STR2(2): s2 = "C Processor"; break;
1117 case PG(1) + NC(3) + STR2(1): s2 = "L Processor"; break;
1118 case PG(1) + NC(3) + STR2(4): s2 = "T Processor"; break;
1119 default: s2 = NULL; break;
1120 }
1121 break;
1122 case 2:
1123 /* 41322 3.74: table 18: String1 Values for S1g3 and S1g4 Processors */
1124 switch (PG(pg) + NC(nc) + STR1(str1)) {
1125 case PG(0) + NC(0) + STR1(0): *brand_pre = "AMD Sempron(tm)"; s1 = "M1"; break;
1126 case PG(0) + NC(0) + STR1(1): *brand_pre = "AMD"; s1 = "V"; break;
1127 case PG(0) + NC(1) + STR1(0): *brand_pre = "AMD Turion(tm) II Ultra Dual-Core Mobile"; s1 = "M6"; break;
1128 case PG(0) + NC(1) + STR1(1): *brand_pre = "AMD Turion(tm) II Dual-Core Mobile"; s1 = "M5"; break;
1129 case PG(0) + NC(1) + STR1(2): *brand_pre = "AMD Athlon(tm) II Dual-Core"; s1 = "M3"; break;
1130 case PG(0) + NC(1) + STR1(3): *brand_pre = "AMD Turion(tm) II"; s1 = "P"; break;
1131 case PG(0) + NC(1) + STR1(4): *brand_pre = "AMD Athlon(tm) II"; s1 = "P"; break;
1132 case PG(0) + NC(1) + STR1(5): *brand_pre = "AMD Phenom(tm) II"; s1 = "X"; break;
1133 case PG(0) + NC(1) + STR1(6): *brand_pre = "AMD Phenom(tm) II"; s1 = "N"; break;
1134 case PG(0) + NC(1) + STR1(7): *brand_pre = "AMD Turion(tm) II"; s1 = "N"; break;
1135 case PG(0) + NC(1) + STR1(8): *brand_pre = "AMD Athlon(tm) II"; s1 = "N"; break;
1136 case PG(0) + NC(2) + STR1(2): *brand_pre = "AMD Phenom(tm) II"; s1 = "P"; break;
1137 case PG(0) + NC(2) + STR1(3): *brand_pre = "AMD Phenom(tm) II"; s1 = "N"; break;
1138 case PG(0) + NC(3) + STR1(1): *brand_pre = "AMD Phenom(tm) II"; s1 = "P"; break;
1139 case PG(0) + NC(3) + STR1(2): *brand_pre = "AMD Phenom(tm) II"; s1 = "X"; break;
1140 case PG(0) + NC(3) + STR1(3): *brand_pre = "AMD Phenom(tm) II"; s1 = "N"; break;
1141 default: s1 = NULL; break;
1142 }
1143 /* 41322 3.74: table 19: String1 Values for S1g3 and S1g4 Processors */
1144 switch (PG(pg) + NC(nc) + STR2(str2)) {
1145 case PG(0) + NC(0) + STR2(1): s2 = "0 Processor"; break;
1146 case PG(0) + NC(1) + STR2(2): s2 = "0 Dual-Core Processor"; break;
1147 case PG(0) + NC(2) + STR2(2): s2 = "0 Triple-Core Processor"; break;
1148 case PG(0) + NC(3) + STR2(1): s2 = "0 Quad-Core Processor"; break;
1149 default: s2 = NULL; break;
1150 }
1151 break;
1152 case 3:
1153 /* 41322 3.74: table 20: String1 Values for G34r1 Processors */
1154 switch (PG(pg) + NC(nc) + STR1(str1)) {
1155 case PG(0) + NC(7) + STR1(0): *brand_pre = "AMD Opteron(tm)"; s1 = "Processor 61"; break;
1156 case PG(0) + NC(11) + STR1(0): *brand_pre = "AMD Opteron(tm)"; s1 = "Processor 61"; break;
1157 case PG(1) + NC(7) + STR1(1): *brand_pre = "Embedded AMD Opteron(tm)"; s1 = "Processor "; break;
1158 /* It sure is odd that there are no 0/7/1 or 0/11/1 cases here. */
1159 default: s1 = NULL; break;
1160 }
1161 /* 41322 3.74: table 21: String2 Values for G34r1 Processors */
1162 switch (PG(pg) + NC(nc) + STR2(str2)) {
1163 case PG(0) + NC(7) + STR1(0): s2 = " HE"; break;
1164 case PG(0) + NC(7) + STR1(1): s2 = " SE"; break;
1165 case PG(0) + NC(11) + STR1(0): s2 = " HE"; break;
1166 case PG(0) + NC(11) + STR1(1): s2 = " SE"; break;
1167 case PG(1) + NC(7) + STR1(1): s2 = "QS"; break;
1168 case PG(1) + NC(7) + STR1(2): s2 = "KS"; break;
1169 default: s2 = NULL; break;
1170 }
1171 break;
1172 case 4:
1173 /* 41322 3.74: table 22: String1 Values for ASB2 Processors */
1174 switch (PG(pg) + NC(nc) + STR1(str1)) {
1175 case PG(0) + NC(0) + STR1(1): *brand_pre = "AMD Athlon(tm) II Neo"; s1 = "K"; break;
1176 case PG(0) + NC(0) + STR1(2): *brand_pre = "AMD"; s1 = "V"; break;
1177 case PG(0) + NC(0) + STR1(3): *brand_pre = "AMD Athlon(tm) II Neo"; s1 = "R"; break;
1178 case PG(0) + NC(1) + STR1(1): *brand_pre = "AMD Turion(tm) II Neo"; s1 = "K"; break;
1179 case PG(0) + NC(1) + STR1(2): *brand_pre = "AMD Athlon(tm) II Neo"; s1 = "K"; break;
1180 case PG(0) + NC(1) + STR1(3): *brand_pre = "AMD"; s1 = "V"; break;
1181 case PG(0) + NC(1) + STR1(4): *brand_pre = "AMD Turion(tm) II Neo"; s1 = "N"; break;
1182 case PG(0) + NC(1) + STR1(5): *brand_pre = "AMD Athlon(tm) II Neo"; s1 = "N"; break;
1183 default: s1 = NULL; break;
1184 }
1185 /* 41322 3.74: table 23: String2 Values for ASB2 Processors */
1186 switch (PG(pg) + NC(nc) + STR2(str2)) {
1187 case PG(0) + NC(0) + STR1(1): s2 = "5 Processor"; break;
1188 case PG(0) + NC(0) + STR1(2): s2 = "L Processor"; break;
1189 case PG(0) + NC(1) + STR1(1): s2 = "5 Dual-Core Processor"; break;
1190 case PG(0) + NC(1) + STR1(2): s2 = "L Dual-Core Processor"; break;
1191 default: s2 = NULL; break;
1192 }
1193 break;
1194 case 5:
1195 /* 41322 3.74: table 24: String1 Values for C32r1 Processors */
1196 switch (PG(pg) + NC(nc) + STR1(str1)) {
1197 case PG(0) + NC(3) + STR1(0): *brand_pre = "AMD Opteron(tm)"; s1 = "41"; break;
1198 case PG(0) + NC(5) + STR1(0): *brand_pre = "AMD Opteron(tm)"; s1 = "41"; break;
1199 case PG(1) + NC(3) + STR1(1): *brand_pre = "Embedded AMD Opteron(tm)"; s1 = " "; break;
1200 case PG(1) + NC(5) + STR1(1): *brand_pre = "Embedded AMD Opteron(tm)"; s1 = " "; break;
1201 /* It sure is odd that there are no 0/3/1 or 0/5/1 cases here. */
1202 default: s1 = NULL; break;
1203 }
1204 /* 41322 3.74: table 25: String2 Values for C32r1 Processors */
1205 /* 41322 3.74: table 25 */
1206 switch (PG(pg) + NC(nc) + STR2(str2)) {
1207 case PG(0) + NC(3) + STR1(0): s2 = " HE"; break;
1208 case PG(0) + NC(3) + STR1(1): s2 = " EE"; break;
1209 case PG(0) + NC(5) + STR1(0): s2 = " HE"; break;
1210 case PG(0) + NC(5) + STR1(1): s2 = " EE"; break;
1211 case PG(1) + NC(3) + STR1(1): s2 = "QS HE"; break;
1212 case PG(1) + NC(3) + STR1(2): s2 = "LE HE"; break;
1213 case PG(1) + NC(3) + STR1(3): s2 = "CL EE"; break;
1214 case PG(1) + NC(5) + STR1(1): s2 = "KX HE"; break;
1215 case PG(1) + NC(5) + STR1(2): s2 = "GL EE"; break;
1216 default: s2 = NULL; break;
1217 }
1218 break;
1219 default:
1220 s1 = NULL;
1221 s2 = NULL;
1222 break;
1223 }
1224 } else if (__F(stash->val_1_eax) == _XF(2) + _F(15)) {
1225 /* Family 11h tables */
1226 switch (pkgtype) {
1227 case 2:
1228 /* 41788 3.08: table 3: String1 Values for S1g2 Processors */
1229 switch (PG(pg) + NC(nc) + STR1(str1)) {
1230 case PG(0) + NC(0) + STR1(0): *brand_pre = "AMD Sempron(tm)"; s1 = "SI-"; break;
1231 case PG(0) + NC(0) + STR1(1): *brand_pre = "AMD Athlon(tm)"; s1 = "QI-"; break;
1232 case PG(0) + NC(1) + STR1(0): *brand_pre = "AMD Turion(tm) X2 Ultra Dual-Core Mobile"; s1 = "ZM-"; break;
1233 case PG(0) + NC(1) + STR1(1): *brand_pre = "AMD Turion(tm) X2 Dual-Core Mobile"; s1 = "RM-"; break;
1234 case PG(0) + NC(1) + STR1(2): *brand_pre = "AMD Athlon(tm) X2 Dual-Core"; s1 = "QL-"; break;
1235 case PG(0) + NC(1) + STR1(3): *brand_pre = "AMD Sempron(tm) X2 Dual-Core"; s1 = "NI-"; break;
1236 default: s1 = NULL; break;
1237 }
1238 /* 41788 3.08: table 4: String2 Values for S1g2 Processors */
1239 switch (PG(pg) + NC(nc) + STR2(str2)) {
1240 case PG(0) + NC(0) + STR2(0): s2 = ""; break;
1241 case PG(0) + NC(1) + STR2(0): s2 = ""; break;
1242 default: s2 = NULL; break;
1243 }
1244 break;
1245 default:
1246 s1 = NULL;
1247 s2 = NULL;
1248 break;
1249 }
1250 } else if (__F(stash->val_1_eax) == _XF(3) + _F(15)) {
1251 partialmodel--;
1252
1253 /* Family 12h tables */
1254 switch (pkgtype) {
1255 case 1:
1256 /* 44739 3.10: table 6: String1 Values for FS1 Processors */
1257 switch (PG(pg) + NC(nc) + STR1(str1)) {
1258 case PG(0) + NC(1) + STR1(3): *brand_pre = "AMD"; s1 = "A4-33"; break;
1259 case PG(0) + NC(1) + STR1(5): *brand_pre = "AMD"; s1 = "E2-30"; break;
1260 case PG(0) + NC(3) + STR1(1): *brand_pre = "AMD"; s1 = "A8-35"; break;
1261 case PG(0) + NC(3) + STR1(3): *brand_pre = "AMD"; s1 = "A6-34"; break;
1262 default: s1 = NULL; break;
1263 }
1264 /* 44739 3.10: table 7: String2 Values for FS1 Processors */
1265 switch (PG(pg) + NC(nc) + STR2(str2)) {
1266 case PG(0) + NC(1) + STR2(1): s2 = "M"; break;
1267 case PG(0) + NC(1) + STR2(2): s2 = "MX"; break;
1268 case PG(0) + NC(3) + STR2(1): s2 = "M"; break;
1269 case PG(0) + NC(3) + STR2(2): s2 = "MX"; break;
1270 default: s2 = NULL; break;
1271 }
1272 break;
1273 case 2:
1274 /* 44739 3.10: table 8: String1 Values for FM1 Processors */
1275 switch (PG(pg) + NC(nc) + STR1(str1)) {
1276 case PG(0) + NC(1) + STR1(1): *brand_pre = "AMD"; s1 = "A4-33"; break;
1277 case PG(0) + NC(1) + STR1(2): *brand_pre = "AMD"; s1 = "E2-32"; break;
1278 case PG(0) + NC(1) + STR1(4): *brand_pre = "AMD Athlon(tm) II X2"; s1 = "2"; break;
1279 case PG(0) + NC(1) + STR1(5): *brand_pre = "AMD"; s1 = "A4-34"; break;
1280 case PG(0) + NC(1) + STR1(12): *brand_pre = "AMD Sempron(tm) X2"; s1 = "1"; break;
1281 case PG(0) + NC(2) + STR1(5): *brand_pre = "AMD"; s1 = "A6-35"; break;
1282 case PG(0) + NC(3) + STR1(5): *brand_pre = "AMD"; s1 = "A8-38"; break;
1283 case PG(0) + NC(3) + STR1(6): *brand_pre = "AMD"; s1 = "A6-36"; break;
1284 case PG(0) + NC(3) + STR1(13): *brand_pre = "AMD Athlon(tm) II X4"; s1 = "6"; break;
1285 default: s1 = NULL; break;
1286 }
1287 /* 44739 3.10: table 9: String2 Values for FM1 Processors */
1288 switch (PG(pg) + NC(nc) + STR2(str2)) {
1289 case PG(0) + NC(1) + STR2(1): s2 = " APU with Radeon(tm) HD Graphics"; break;
1290 case PG(0) + NC(1) + STR2(2): s2 = " Dual-Core Processor"; break;
1291 case PG(0) + NC(2) + STR2(1): s2 = " APU with Radeon(tm) HD Graphics"; break;
1292 case PG(0) + NC(3) + STR2(1): s2 = " APU with Radeon(tm) HD Graphics"; break;
1293 case PG(0) + NC(3) + STR2(3): s2 = " Quad-Core Processor"; break;
1294 default: s2 = NULL; break;
1295 }
1296 break;
1297 default:
1298 s1 = NULL;
1299 s2 = NULL;
1300 break;
1301 }
1302 } else if (__F(stash->val_1_eax) == _XF(5) + _F(15)) {
1303 partialmodel--;
1304
1305 /* Family 14h Models 00h-0Fh tables */
1306 switch (pkgtype) {
1307 case 0:
1308 /* 47534 3.00: table 4: String1 Values for FT1 Processors */
1309 switch (PG(pg) + NC(nc) + STR1(str1)) {
1310 case PG(0) + NC(0) + STR1(1): *brand_pre = "AMD"; s1 = "C-"; break;
1311 case PG(0) + NC(0) + STR1(2): *brand_pre = "AMD"; s1 = "E-"; break;
1312 case PG(0) + NC(0) + STR1(4): *brand_pre = "AMD"; s1 = "G-T"; break;
1313 case PG(0) + NC(1) + STR1(1): *brand_pre = "AMD"; s1 = "C-"; break;
1314 case PG(0) + NC(1) + STR1(2): *brand_pre = "AMD"; s1 = "E-"; break;
1315 case PG(0) + NC(1) + STR1(3): *brand_pre = "AMD"; s1 = "Z-"; break;
1316 case PG(0) + NC(1) + STR1(4): *brand_pre = "AMD"; s1 = "G-T"; break;
1317 case PG(0) + NC(1) + STR1(5): *brand_pre = "AMD"; s1 = "E1-1"; break;
1318 case PG(0) + NC(1) + STR1(6): *brand_pre = "AMD"; s1 = "E2-1"; break;
1319 case PG(0) + NC(1) + STR1(7): *brand_pre = "AMD"; s1 = "E2-2"; break;
1320 default: s1 = NULL; break;
1321 }
1322 /* 47534 3.00: table 5: String2 Values for FT1 Processors */
1323 switch (PG(pg) + NC(nc) + STR2(str2)) {
1324 case PG(0) + NC(0) + STR2(1): s2 = ""; break;
1325 case PG(0) + NC(0) + STR2(2): s2 = "0"; break;
1326 case PG(0) + NC(0) + STR2(3): s2 = "5"; break;
1327 case PG(0) + NC(0) + STR2(4): s2 = "0x"; break;
1328 case PG(0) + NC(0) + STR2(5): s2 = "5x"; break;
1329 case PG(0) + NC(0) + STR2(6): s2 = "x"; break;
1330 case PG(0) + NC(0) + STR2(7): s2 = "L"; break;
1331 case PG(0) + NC(0) + STR2(8): s2 = "N"; break;
1332 case PG(0) + NC(0) + STR2(9): s2 = "R"; break;
1333 case PG(0) + NC(0) + STR2(10): s2 = "0"; break;
1334 case PG(0) + NC(0) + STR2(11): s2 = "5"; break;
1335 case PG(0) + NC(0) + STR2(12): s2 = ""; break;
1336 case PG(0) + NC(0) + STR2(13): s2 = "0D"; break;
1337 case PG(0) + NC(1) + STR2(1): s2 = ""; break;
1338 case PG(0) + NC(1) + STR2(2): s2 = "0"; break;
1339 case PG(0) + NC(1) + STR2(3): s2 = "5"; break;
1340 case PG(0) + NC(1) + STR2(4): s2 = "0x"; break;
1341 case PG(0) + NC(1) + STR2(5): s2 = "5x"; break;
1342 case PG(0) + NC(1) + STR2(6): s2 = "x"; break;
1343 case PG(0) + NC(1) + STR2(7): s2 = "L"; break;
1344 case PG(0) + NC(1) + STR2(8): s2 = "N"; break;
1345 case PG(0) + NC(1) + STR2(9): s2 = "0"; break;
1346 case PG(0) + NC(1) + STR2(10): s2 = "5"; break;
1347 case PG(0) + NC(1) + STR2(11): s2 = ""; break;
1348 case PG(0) + NC(1) + STR2(12): s2 = "E"; break;
1349 case PG(0) + NC(1) + STR2(13): s2 = "0D"; break;
1350 default: s2 = NULL; break;
1351 }
1352 break;
1353 default:
1354 s1 = NULL;
1355 s2 = NULL;
1356 break;
1357 }
1358 } else {
1359 s1 = NULL;
1360 s2 = NULL;
1361 }
1362
1363 #undef NC
1364 #undef PG
1365 #undef STR1
1366 #undef STR2
1367
1368 if (s1 != NULL) {
1369 char* p = proc;
1370 p += sprintf(p, "%s%02d", s1, partialmodel);
1371 if (s2) sprintf(p, "%s", s2);
1372 }
1373 }
1374 }
1375
1376 static void
decode_override_brand(code_stash_t * stash)1377 decode_override_brand(code_stash_t* stash)
1378 {
1379 if ((stash->vendor == VENDOR_AMD
1380 || stash->vendor == VENDOR_HYGON)
1381 && strstr(stash->brand, "model unknown") != NULL) {
1382 /*
1383 ** AMD has this exotic architecture where the BIOS decodes the brand
1384 ** string from tables and feeds it back into the CPU via MSR's. If an old
1385 ** BIOS cannot understand a new CPU, it uses the string "model unknown".
1386 ** In this case, I use my own copies of tables to deduce the brand string
1387 ** and decode that.
1388 */
1389 const char* brand_pre;
1390 const char* brand_post;
1391 char proc[96];
1392 decode_amd_model(stash, &brand_pre, &brand_post, proc);
1393 if (brand_pre != NULL) {
1394 char* b = stash->override_brand;
1395 b += sprintf(b, "%s %s", brand_pre, proc);
1396 if (brand_post != NULL) sprintf(b, " %s", brand_post);
1397 }
1398 }
1399 }
1400
1401 static void
print_override_brand(code_stash_t * stash)1402 print_override_brand(code_stash_t* stash)
1403 {
1404 if (stash->override_brand[0] != '\0') {
1405 printf(" (override brand synth) = %s\n", stash->override_brand);
1406 }
1407 }
1408
1409 static void
stash_intel_cache(code_stash_t * stash,unsigned char value)1410 stash_intel_cache(code_stash_t* stash,
1411 unsigned char value)
1412 {
1413 switch (value) {
1414 case 0x42: stash->L2_4w_256K = TRUE; break;
1415 case 0x43: stash->L2_4w_512K = TRUE; break;
1416 case 0x44: stash->L2_4w_1Mor2M = TRUE; break;
1417 case 0x45: stash->L2_4w_1Mor2M = TRUE; break;
1418 case 0x80: stash->L2_8w_512K = TRUE; break;
1419 case 0x82: stash->L2_8w_256K = TRUE; break;
1420 case 0x83: stash->L2_8w_512K = TRUE; break;
1421 case 0x84: stash->L2_8w_1Mor2M = TRUE; break;
1422 case 0x85: stash->L2_8w_1Mor2M = TRUE; break;
1423 }
1424
1425 switch (value) {
1426 case 0x45:
1427 case 0x7d:
1428 case 0x85:
1429 stash->L2_2M = TRUE;
1430 break;
1431 }
1432
1433 switch (value) {
1434 case 0x4e:
1435 stash->L2_6M = TRUE;
1436 break;
1437 }
1438
1439 switch (value) {
1440 case 0x22:
1441 case 0x23:
1442 case 0x25:
1443 case 0x29:
1444 case 0x46:
1445 case 0x47:
1446 case 0x49:
1447 case 0x4a:
1448 case 0x4b:
1449 case 0x4c:
1450 case 0x4d:
1451 case 0x88:
1452 case 0x89:
1453 case 0x8a:
1454 case 0x8d:
1455 case 0xd0:
1456 case 0xd1:
1457 case 0xd2:
1458 case 0xd6:
1459 case 0xd7:
1460 case 0xd8:
1461 case 0xdc:
1462 case 0xdd:
1463 case 0xde:
1464 case 0xe2:
1465 case 0xe3:
1466 case 0xe4:
1467 case 0xea:
1468 case 0xeb:
1469 case 0xec:
1470 stash->L3 = TRUE;
1471 break;
1472 }
1473
1474 switch (value) {
1475 case 0x21:
1476 case 0x3c:
1477 case 0x42:
1478 case 0x7a:
1479 case 0x7e:
1480 case 0x82:
1481 stash->L2_256K = TRUE;
1482 break;
1483 }
1484
1485 switch (value) {
1486 case 0x3e:
1487 case 0x43:
1488 case 0x7b:
1489 case 0x7f:
1490 case 0x83:
1491 case 0x86:
1492 stash->L2_512K = TRUE;
1493 break;
1494 }
1495 }
1496
1497 static void
decode_brand_id_stash(code_stash_t * stash)1498 decode_brand_id_stash(code_stash_t* stash)
1499 {
1500 unsigned int val_1_eax = stash->val_1_eax;
1501 unsigned int val_1_ebx = stash->val_1_ebx;
1502
1503 switch (__B(val_1_ebx)) {
1504 case _B(0): break;
1505 case _B(1): stash->bri.desktop_celeron = TRUE; break;
1506 case _B(2): stash->bri.desktop_pentium = TRUE; break;
1507 case _B(3): if ( __FMS(val_1_eax) == _FMS(0,6, 0,11, 1)) {
1508 stash->bri.desktop_celeron = TRUE;
1509 } else {
1510 stash->bri.xeon = TRUE;
1511 }
1512 break;
1513 case _B(4): stash->bri.desktop_pentium = TRUE; break;
1514 case _B(6): stash->bri.desktop_pentium = TRUE; break;
1515 case _B(7): stash->bri.desktop_celeron = TRUE; break;
1516 case _B(8): stash->bri.desktop_pentium = TRUE; break;
1517 case _B(9): stash->bri.desktop_pentium = TRUE; break;
1518 case _B(10): stash->bri.desktop_celeron = TRUE; break;
1519 case _B(11): if (__FMS(val_1_eax) <= _FMS(0,15, 0,1, 2)) {
1520 stash->bri.xeon_mp = TRUE;
1521 } else {
1522 stash->bri.xeon = TRUE;
1523 }
1524 break;
1525 case _B(12): stash->bri.xeon_mp = TRUE; break;
1526 case _B(14): if (__FMS(val_1_eax) <= _FMS(0,15, 0,1, 3)) {
1527 stash->bri.xeon = TRUE;
1528 } else {
1529 stash->bri.mobile_pentium_m = TRUE;
1530 }
1531 break;
1532 case _B(15): if (__FM(val_1_eax) == _FM (0,15, 0,2)) {
1533 stash->bri.mobile_pentium_m = TRUE;
1534 } else {
1535 stash->bri.mobile_celeron = TRUE;
1536 }
1537 break;
1538 case _B(16): stash->bri.desktop_celeron = TRUE; break;
1539 case _B(17): stash->bri.mobile_pentium = TRUE; break;
1540 case _B(18): stash->bri.desktop_celeron = TRUE; break;
1541 case _B(19): stash->bri.mobile_celeron = TRUE; break;
1542 case _B(20): stash->bri.desktop_celeron = TRUE; break;
1543 case _B(21): stash->bri.mobile_pentium = TRUE; break;
1544 case _B(22): stash->bri.desktop_pentium = TRUE; break;
1545 case _B(23): stash->bri.mobile_celeron = TRUE; break;
1546 default: break;
1547 }
1548 }
1549
1550 static void
decode_brand_string(const char * brand,code_stash_t * stash)1551 decode_brand_string(const char* brand,
1552 code_stash_t* stash)
1553 {
1554 stash->br.mobile = (strstr(brand, "Mobile") != NULL
1555 || strstr(brand, "mobile") != NULL);
1556
1557 stash->br.celeron = strstr(brand, "Celeron") != NULL;
1558 stash->br.core = strstr(brand, "Core(TM)") != NULL;
1559 stash->br.pentium = strstr(brand, "Pentium") != NULL;
1560 stash->br.atom = strstr(brand, "Atom") != NULL;
1561 stash->br.xeon_mp = (strstr(brand, "Xeon MP") != NULL
1562 || strstr(brand, "Xeon(TM) MP") != NULL
1563 || strstr(brand, "Xeon(R)") != NULL);
1564 stash->br.xeon = strstr(brand, "Xeon") != NULL;
1565 stash->br.pentium_m = strstr(brand, "Pentium(R) M") != NULL;
1566 stash->br.pentium_d = strstr(brand, "Pentium(R) D") != NULL;
1567 stash->br.extreme = strregexp(brand, " ?X[0-9][0-9][0-9][0-9]");
1568 stash->br.generic = strstr(brand, "Genuine Intel(R) CPU") != NULL;
1569 stash->br.scalable = (strstr(brand, "Bronze") != NULL
1570 || strstr(brand, "Silver") != NULL
1571 || strstr(brand, "Gold") != NULL
1572 || strstr(brand, "Platinum") != NULL);
1573 stash->br.u_line = (strregexp(brand, "Core.* [im][3579]-[0-9]*U")
1574 || strregexp(brand, "Pentium.* [0-9]*U")
1575 || strregexp(brand, "Celeron.* [0-9]*U"));
1576 stash->br.y_line = (strregexp(brand, "Core.* [im][3579]-[0-9]*Y")
1577 || strregexp(brand, "Pentium.* [0-9]*Y")
1578 || strregexp(brand, "Celeron.* [0-9]*Y"));
1579 stash->br.g_line = strregexp(brand, "Core.* [im][3579]-[0-9]*G");
1580 stash->br.i_8000 = strregexp(brand, "Core.* [im][3579]-8[0-9][0-9][0-9]");
1581 stash->br.i_10000 = strregexp(brand, "Core.* i[3579]-10[0-9][0-9][0-9]");
1582 stash->br.cc150 = strregexp(brand, "CC150");
1583
1584 stash->br.athlon_lv = strstr(brand, "Athlon(tm) XP-M (LV)") != NULL;
1585 stash->br.athlon_xp = (strstr(brand, "Athlon(tm) XP") != NULL
1586 || strstr(brand, "Athlon(TM) XP") != NULL);
1587 stash->br.duron = strstr(brand, "Duron") != NULL;
1588 stash->br.athlon = strstr(brand, "Athlon") != NULL;
1589 stash->br.sempron = strstr(brand, "Sempron") != NULL;
1590 stash->br.phenom = strstr(brand, "Phenom") != NULL;
1591 stash->br.series = strstr(brand, "Series") != NULL;
1592 stash->br.a_series = (strstr(brand, "AMD A") != NULL
1593 || strstr(brand, "AMD PRO A") != NULL);
1594 stash->br.c_series = strstr(brand, "AMD C") != NULL;
1595 stash->br.e_series = strstr(brand, "AMD E") != NULL;
1596 stash->br.g_series = strstr(brand, "AMD G") != NULL;
1597 stash->br.r_series = strstr(brand, "AMD R") != NULL;
1598 stash->br.z_series = strstr(brand, "AMD Z") != NULL;
1599 stash->br.geode = strstr(brand, "Geode") != NULL;
1600 stash->br.turion = strstr(brand, "Turion") != NULL;
1601 stash->br.neo = strstr(brand, "Neo") != NULL;
1602 stash->br.athlon_fx = strstr(brand, "Athlon(tm) 64 FX") != NULL;
1603 stash->br.athlon_mp = strstr(brand, "Athlon(tm) MP") != NULL;
1604 stash->br.duron_mp = strstr(brand, "Duron(tm) MP") != NULL;
1605 stash->br.opteron = strstr(brand, "Opteron") != NULL;
1606 stash->br.fx = strstr(brand, "AMD FX") != NULL;
1607 stash->br.firepro = strstr(brand, "Firepro") != NULL; // total guess
1608 stash->br.ultra = strstr(brand, "Ultra") != NULL;
1609 stash->br.t_suffix = strregexp(brand, "[0-9][0-9][0-9][0-9]T");
1610 stash->br.ryzen = strstr(brand, "Ryzen") != NULL;
1611 stash->br.epyc = strstr(brand, "EPYC") != NULL;
1612 stash->br.epyc_3000 = strregexp(brand, "EPYC 3[0-9][0-9][0-9]");
1613 stash->br.montage = strstr(brand, "Montage(R)") != NULL;
1614
1615 stash->br.embedded = strstr(brand, "Embedded") != NULL;
1616 if (strstr(brand, "Dual Core") != NULL
1617 || strstr(brand, " X2 ") != NULL) {
1618 stash->br.cores = 2;
1619 } else if (strstr(brand, "Triple-Core") != NULL
1620 || strstr(brand, " X3 ") != NULL) {
1621 stash->br.cores = 3;
1622 } else if (strstr(brand, "Quad-Core") != NULL
1623 || strstr(brand, " X4 ") != NULL) {
1624 stash->br.cores = 4;
1625 } else if (strstr(brand, "Six-Core") != NULL
1626 || strstr(brand, " X6 ") != NULL) {
1627 stash->br.cores = 6;
1628 } else {
1629 stash->br.cores = 0; // means unspecified by the brand string
1630 }
1631
1632 stash->br.mediagx = strstr(brand, "MediaGXtm") != NULL;
1633
1634 stash->br.c7 = strstr(brand, "C7") != NULL;
1635 stash->br.c7m = strstr(brand, "C7-M") != NULL;
1636 stash->br.c7d = strstr(brand, "C7-D") != NULL;
1637 stash->br.eden = strstr(brand, "Eden") != NULL;
1638 stash->br.zhaoxin = strstr(brand, "ZHAOXIN") != NULL;
1639 }
1640
1641 static void
decode_brand_stash(code_stash_t * stash)1642 decode_brand_stash(code_stash_t* stash)
1643 {
1644 if (stash->override_brand[0] != '\0') {
1645 decode_brand_string(stash->override_brand, stash);
1646 } else {
1647 decode_brand_string(stash->brand, stash);
1648 }
1649 }
1650
1651 /*
1652 ** Query macros are used in the synth tables to disambiguate multiple chips
1653 ** with the same family, model, and/or stepping.
1654 */
1655
1656 #define is_intel (stash->vendor == VENDOR_INTEL)
1657 #define is_amd (stash->vendor == VENDOR_AMD)
1658 #define is_cyrix (stash->vendor == VENDOR_CYRIX)
1659 #define is_via (stash->vendor == VENDOR_VIA)
1660 #define is_transmeta (stash->vendor == VENDOR_TRANSMETA)
1661 #define is_mobile (stash->br.mobile)
1662
1663 /*
1664 ** Intel major queries:
1665 **
1666 ** d? = think "desktop"
1667 ** s? = think "server" (multiprocessor)
1668 ** M? = think "mobile"
1669 ** X? = think "Extreme Edition"
1670 ** L? = think "Line"
1671 **
1672 ** ?G = think generic CPU
1673 ** ?P = think Pentium
1674 ** ?C = think Celeron
1675 ** ?a = think Atom
1676 ** ?X = think Xeon
1677 ** ?M = think Xeon MP / Pentium M
1678 ** ?c = think Core
1679 ** ?d = think Pentium D
1680 ** ?S = think Scalable (Bronze/Silver/Gold/Platinum)
1681 */
1682 #define dG (is_intel && !is_mobile && stash->br.generic)
1683 #define dP ((is_intel && stash->br.pentium) \
1684 || stash->bri.desktop_pentium)
1685 #define dC ((is_intel && !is_mobile && stash->br.celeron) \
1686 || stash->bri.desktop_celeron)
1687 #define da (is_intel && stash->br.atom)
1688 #define dd (is_intel && stash->br.pentium_d)
1689 #define TODD_WAS_HERE
1690 #ifdef TODD_WAS_HERE
1691 #define dc (is_intel && !is_mobile && stash->br.core)
1692 #else
1693 #define dc (is_intel && !is_mobile && (stash->br.core || stash->br.generic))
1694 #endif
1695 #define sX ((is_intel && stash->br.xeon) || stash->bri.xeon)
1696 #define sM ((is_intel && stash->br.xeon_mp) \
1697 || stash->bri.xeon_mp)
1698 #define sS (is_intel && stash->br.xeon && stash->br.scalable)
1699 #define MP ((is_intel && is_mobile && stash->br.pentium) \
1700 || stash->bri.mobile_pentium)
1701 #define MC ((is_intel && is_mobile && stash->br.celeron) \
1702 || stash->bri.mobile_celeron)
1703 #define MM ((is_intel && stash->br.pentium_m)\
1704 || stash->bri.mobile_pentium_m)
1705 #define Mc (is_intel && is_mobile && stash->br.core)
1706 #define Xc (is_intel && stash->br.extreme)
1707 #define LU (is_intel && stash->br.u_line)
1708 #define LY (is_intel && stash->br.y_line)
1709 #define LG (is_intel && stash->br.g_line)
1710 #define UC (dC && stash->br.u_line)
1711 #define UP (dP && stash->br.u_line)
1712 #define YC (dC && stash->br.y_line)
1713 #define YP (dP && stash->br.y_line)
1714 #define d1 (is_intel && stash->br.cc150)
1715 #define iM (is_intel && stash->br.montage)
1716
1717 /*
1718 ** Intel special cases
1719 */
1720 /* Pentium II Xeon (Deschutes), distinguished from Pentium II (Deschutes) */
1721 #define xD (stash->L2_4w_1Mor2M)
1722 /* Mobile Pentium II (Deschutes), distinguished from Pentium II (Deschutes) */
1723 #define mD (stash->L2_4w_256K)
1724 /* Intel Celeron (Deschutes), distinguished from Pentium II (Deschutes) */
1725 #define cD (!stash->L2_4w_1Mor2M && !stash->L2_4w_512K && !stash->L2_4w_256K)
1726 /* Pentium III Xeon (Katmai), distinguished from Pentium III (Katmai) */
1727 #define xK (stash->L2_4w_1Mor2M || stash->L2_8w_1Mor2M)
1728 /* Pentium II (Katmai), verified, so distinguished from fallback case */
1729 #define pK ((stash->L2_4w_512K || stash->L2_8w_256K || stash->L2_8w_512K) \
1730 && !stash->L2_4w_1Mor2M && !stash->L2_8w_1Mor2M)
1731 /* Irwindale, distinguished from Nocona */
1732 #define sI (sX && stash->L2_2M)
1733 /* Potomac, distinguished from Cranford */
1734 #define sP (sM && stash->L3)
1735 /* Allendale, distinguished from Conroe */
1736 #define dL (dc && stash->L2_2M)
1737 /* Dual-Core Xeon Processor 5100 (Woodcrest B1) pre-production,
1738 distinguished from Core 2 Duo (Conroe B1) */
1739 #define QW (dG && stash->br.generic \
1740 && (stash->mp.cores == 4 \
1741 || (stash->mp.cores == 2 && stash->mp.hyperthreads == 2)))
1742 /* Core Duo (Yonah), distinguished from Core Solo (Yonah) */
1743 #define DG (dG && stash->mp.cores == 2)
1744 /* Core 2 Quad, distinguished from Core 2 Duo */
1745 #define Qc (dc && stash->mp.cores == 4)
1746 /* Core 2 Extreme (Conroe B1), distinguished from Core 2 Duo (Conroe B1) */
1747 #define XE (dc && strstr(stash->brand, " E6800") != NULL)
1748 /* Quad-Core Xeon, distinguished from Xeon; and
1749 Xeon Processor 3300, distinguished from Xeon Processor 3100 */
1750 #define sQ (sX && stash->mp.cores == 4)
1751 /* Xeon Processor 7000, distinguished from Xeon */
1752 #define IS_VMX(val_1_ecx) (BIT_EXTRACT_LE((val_1_ecx), 5, 6))
1753 #define s7 (sX && IS_VMX(stash->val_1_ecx))
1754 /* Wolfdale C0/E0, distinguished from Wolfdale M0/R0 */
1755 #define de (dc && stash->L2_6M)
1756 /* Penryn C0/E0, distinguished from Penryn M0/R0 */
1757 #define Me (Mc && stash->L2_6M)
1758 /* Yorkfield C1/E0, distinguished from Yorkfield M1/E0 */
1759 #define Qe (Qc && stash->L2_6M)
1760 /* Yorkfield E0, distinguished from Yorkfield R0 */
1761 #define se (sQ && stash->L2_6M)
1762 /* Amber Lake-Y, distinguished from Kaby Lake-Y */
1763 #define Y8 (LY && stash->br.i_8000)
1764 /* Comet Lake V1, distinguished from Whiskey Lake V0 */
1765 #define UX (LU && stash->br.i_10000)
1766
1767 /*
1768 ** AMD major queries:
1769 **
1770 ** d? = think "desktop"
1771 ** s? = think "server" (MP)
1772 ** M? = think "mobile"
1773 ** S? = think "Series"
1774 ** T? = think "Tablet"
1775 ** A? = think "any"
1776 ** E? = think "Embedded"
1777 **
1778 ** ?A = think Athlon
1779 ** ?X = think Athlon XP
1780 ** ?L = think Athlon XP (LV)
1781 ** ?E = think EPYC
1782 ** ?f = think FX
1783 ** ?F = think Athlon FX
1784 ** ?D = think Duron
1785 ** ?S = think Sempron
1786 ** ?O = think Opteron
1787 ** ?T = think Turion
1788 ** ?U = think Turion Ultra
1789 ** ?p = think Phenom
1790 ** ?R = think Ryzen
1791 ** ?s = think ?-Series
1792 ** ?n = think Turion Neo
1793 ** ?N = think Neo
1794 */
1795 #define dA (is_amd && !is_mobile && stash->br.athlon)
1796 #define dX (is_amd && !is_mobile && stash->br.athlon_xp)
1797 #define dF (is_amd && !is_mobile && stash->br.athlon_fx)
1798 #define df (is_amd && !is_mobile && stash->br.fx)
1799 #define dD (is_amd && !is_mobile && stash->br.duron)
1800 #define dS (is_amd && !is_mobile && stash->br.sempron)
1801 #define dp (is_amd && !is_mobile && stash->br.phenom)
1802 #define dI (is_amd && !is_mobile && stash->br.firepro)
1803 #define dR (is_amd && !is_mobile && stash->br.ryzen)
1804 #define sO (is_amd && !is_mobile && stash->br.opteron)
1805 #define sA (is_amd && !is_mobile && stash->br.athlon_mp)
1806 #define sD (is_amd && !is_mobile && stash->br.duron_mp)
1807 #define sE (is_amd && !is_mobile && stash->br.epyc)
1808 #define MA (is_amd && is_mobile && stash->br.athlon)
1809 #define MX (is_amd && is_mobile && stash->br.athlon_xp)
1810 #define ML (is_amd && is_mobile && stash->br.athlon_lv)
1811 #define MD (is_amd && is_mobile && stash->br.duron)
1812 #define MS (is_amd && is_mobile && stash->br.sempron)
1813 #define Mp (is_amd && is_mobile && stash->br.phenom)
1814 #define Ms (is_amd && is_mobile && stash->br.series)
1815 #define Mr (is_amd && is_mobile && stash->br.r_series)
1816 #define MG (is_amd && stash->br.geode)
1817 #define MT (is_amd && stash->br.turion)
1818 #define MU (is_amd && stash->br.ultra)
1819 #define Mn (is_amd && stash->br.turion && stash->br.neo)
1820 #define MN (is_amd && stash->br.neo)
1821 #define Sa (is_amd && !is_mobile && stash->br.a_series)
1822 #define Sc (is_amd && !is_mobile && stash->br.c_series)
1823 #define Se (is_amd && !is_mobile && stash->br.e_series)
1824 #define Sg (is_amd && !is_mobile && stash->br.g_series)
1825 #define Sr (is_amd && !is_mobile && stash->br.r_series)
1826 #define Sz (is_amd && !is_mobile && stash->br.z_series)
1827 #define Ta (is_amd && stash->br.t_suffix && stash->br.a_series)
1828 #define Te (is_amd && stash->br.t_suffix && stash->br.e_series)
1829 #define AR (is_amd && stash->br.ryzen)
1830 #define ER (is_amd && stash->br.ryzen && stash->br.embedded)
1831 #define EE (is_amd && stash->br.epyc_3000)
1832
1833 /*
1834 ** AMD special cases
1835 */
is_amd_egypt_athens_8xx(const code_stash_t * stash)1836 static boolean is_amd_egypt_athens_8xx(const code_stash_t* stash)
1837 {
1838 /*
1839 ** This makes its determination based on the Processor model
1840 ** logic from:
1841 ** Revision Guide for AMD Athlon 64 and AMD Opteron Processors
1842 ** (25759 Rev 3.79), Constructing the Processor Name String.
1843 ** See also decode_amd_model().
1844 */
1845
1846 if (stash->vendor == VENDOR_AMD && stash->br.opteron) {
1847 switch (__FM(stash->val_1_eax)) {
1848 case _FM(0,15, 2,1): /* Italy/Egypt */
1849 case _FM(0,15, 2,5): /* Troy/Athens */
1850 {
1851 unsigned int bti;
1852
1853 if (__B(stash->val_1_ebx) != 0) {
1854 bti = BIT_EXTRACT_LE(__B(stash->val_1_ebx), 5, 8) << 2;
1855 } else if (BIT_EXTRACT_LE(stash->val_80000001_ebx, 0, 12) != 0) {
1856 bti = BIT_EXTRACT_LE(stash->val_80000001_ebx, 6, 12);
1857 } else {
1858 return FALSE;
1859 }
1860
1861 switch (bti) {
1862 case 0x10:
1863 case 0x11:
1864 case 0x12:
1865 case 0x13:
1866 case 0x2a:
1867 case 0x30:
1868 case 0x31:
1869 case 0x39:
1870 case 0x3c:
1871 case 0x32:
1872 case 0x33:
1873 /* It's a 2xx */
1874 return FALSE;
1875 case 0x14:
1876 case 0x15:
1877 case 0x16:
1878 case 0x17:
1879 case 0x2b:
1880 case 0x34:
1881 case 0x35:
1882 case 0x3a:
1883 case 0x3d:
1884 case 0x36:
1885 case 0x37:
1886 /* It's an 8xx */
1887 return TRUE;
1888 }
1889 }
1890 }
1891 }
1892
1893 return FALSE;
1894 }
1895
1896 /* Embedded Opteron, distinguished from Opteron (Barcelona & Shanghai) */
1897 #define EO (sO && stash->br.embedded)
1898 /* Opterons, distinguished by number of processors */
1899 #define DO (sO && stash->br.cores == 2)
1900 #define SO (sO && stash->br.cores == 6)
1901 /* Athlons, distinguished by number of processors */
1902 #define DA (dA && stash->br.cores == 2)
1903 #define TA (dA && stash->br.cores == 3)
1904 #define QA (dA && stash->br.cores == 4)
1905 /* Phenoms distinguished by number of processors */
1906 #define Dp (dp && stash->br.cores == 2)
1907 #define Tp (dp && stash->br.cores == 3)
1908 #define Qp (dp && stash->br.cores == 4)
1909 #define Sp (dp && stash->br.cores == 6)
1910 /* Semprons, distinguished by number of processors */
1911 #define DS (dS && stash->br.cores == 2)
1912 /* Egypt, distinguished from Italy; and
1913 Athens, distingushed from Troy */
1914 #define s8 (sO && is_amd_egypt_athens_8xx(stash))
1915 /* Thorton A2, distinguished from Barton A2 */
1916 #define dt (dX && stash->L2_256K)
1917 /* Manchester E6, distinguished from from Toledo E6 */
1918 #define dm (dA && stash->L2_512K)
1919 /* Propus, distinguished from Regor */
1920 #define dr (dA && stash->L2_512K)
1921 /* Trinidad, distinguished from Taylor */
1922 #define Mt (MT && stash->L2_512K)
1923
1924 /*
1925 ** Cyrix major query
1926 */
1927 #define cm (is_cyrix && stash->br.mediagx)
1928
1929 /*
1930 ** VIA major query
1931 */
1932 #define v7 (is_via && stash->br.c7)
1933 #define vM (is_via && stash->br.c7m)
1934 #define vD (is_via && stash->br.c7d)
1935 #define vE (is_via && stash->br.eden)
1936 #define vZ (is_via && stash->br.zhaoxin)
1937
1938 /*
1939 ** Transmeta major queries
1940 **
1941 ** t2 = TMx200
1942 ** t4 = TMx400
1943 ** t5 = TMx500
1944 ** t6 = TMx600
1945 ** t8 = TMx800
1946 */
1947 #define tm_rev(rev) (is_transmeta \
1948 && (stash->transmeta_proc_rev & 0xffff0000) == rev)
1949 /* TODO: Add cases for Transmeta Crusoe TM5700/TM5900 */
1950 /* TODO: Add cases for Transmeta Efficeon */
1951 #define t2 (tm_rev(0x01010000))
1952 #define t4 (tm_rev(0x01020000) || (tm_rev(0x01030000) && stash->L2_4w_256K))
1953 #define t5 ((tm_rev(0x01040000) || tm_rev(0x01040000)) && stash->L2_4w_256K)
1954 #define t6 (tm_rev(0x01030000) && stash->L2_4w_512K)
1955 #define t8 ((tm_rev(0x01040000) || tm_rev(0x01040000)) && stash->L2_4w_512K)
1956
1957 static cstring
decode_vendor(vendor_t vendor,const code_stash_t * stash)1958 decode_vendor(vendor_t vendor,
1959 const code_stash_t* stash)
1960 {
1961 switch (vendor) {
1962 case VENDOR_INTEL: if (stash->br.montage) {
1963 return "Montage";
1964 } else {
1965 return "Intel";
1966 }
1967 case VENDOR_AMD: return "AMD";
1968 case VENDOR_CYRIX: return "Cyrix";
1969 case VENDOR_VIA: if (stash->br.zhaoxin) {
1970 return "Zhaoxin";
1971 } else {
1972 return "VIA";
1973 }
1974 case VENDOR_TRANSMETA: return "Transmeta";
1975 case VENDOR_UMC: return "UMC";
1976 case VENDOR_NEXGEN: return "NexGen";
1977 case VENDOR_RISE: return "Rise";
1978 case VENDOR_SIS: return "SiS";
1979 case VENDOR_NSC: return "NSC";
1980 case VENDOR_VORTEX: return "Vortex";
1981 case VENDOR_RDC: return "RDC";
1982 case VENDOR_HYGON: return "Hygon";
1983 case VENDOR_ZHAOXIN: return "Zhaoxin";
1984 case VENDOR_UNKNOWN:
1985 default:
1986 return NULL;
1987 }
1988 }
1989
1990 #define ACT(...) (__VA_ARGS__)
1991
1992 typedef struct {
1993 cstring uarch; // process-dependent name
1994 cstring family; // process-neutral name:
1995 // sometimes independent (e.g. Core)
1996 // sometimes based on lead uarch (e.g. Nehalem)
1997 cstring phys; // physical properties: die process, #pins, etc.
1998 boolean core_is_uarch; // for some uarches, the core names are based on the
1999 // uarch names, so the uarch name becomes redundant
2000 } arch_t;
2001
2002 static void
init_arch(arch_t * arch)2003 init_arch(arch_t* arch)
2004 {
2005 arch->uarch = NULL;
2006 arch->family = NULL;
2007 arch->phys = NULL;
2008 arch->core_is_uarch = FALSE;
2009 }
2010
2011 static void
decode_uarch_intel(unsigned int val,arch_t * arch,const code_stash_t * stash)2012 decode_uarch_intel(unsigned int val,
2013 arch_t* arch,
2014 const code_stash_t* stash)
2015 {
2016 init_arch(arch);
2017
2018 cstring* u = &arch->uarch;
2019 cstring* f = &arch->family;
2020 cstring* p = &arch->phys;
2021 boolean* ciu = &arch->core_is_uarch;
2022
2023 // Intel calls "Whiskey Lake", "Amber Lake", and "Comet Lake" distinct
2024 // uarch's optimized from "Kaby Lake". That just leads to confusion and long
2025 // uarch names with slashes. Their families & models overlap, and just
2026 // differ based on brand (based on target market):
2027 // (0,6),(8,14),9 = Kaby Lake -or- Amber Lake-Y
2028 // (0,6),(8,14),11 = Whiskey Lake-U -or- Amber Lake-Y
2029 // (0,6),(8,14),12 = Whiskey Lake-U -or- Amber Lake-Y -or- Comet Lake-U
2030 // If the only way to distinguish two uarch's is by brand, I am skeptical
2031 // that they really are distinct uarch's! This is analogous to the multitude
2032 // of core names in pre-Sandy Bridge days. So I am treating those 3 as
2033 // distinct cores within the "Kaby Lake" uarch. This reduces the number of
2034 // uarches in the Skylake-based era to:
2035 //
2036 // [Skylake] = lead uarch in {Skylake} family
2037 // [Cascade Lake] = Skylake + DL Boost + spectre/meltdown fixes
2038 // [Kaby Lake] = Skylake, 14nm+ (includes Whiskey, Amber, Comet)
2039 // [Coffee Lake] = Kaby Lake, 14nm++, 1.5x CPUs/die
2040 // [Palm Cove] = Coffee Lake, 10nm, AVX-512
2041 //
2042 // That is a more manageable set.
2043 //
2044
2045 START;
2046 F ( 0, 4, *f = "i486"); // *p depends on core
2047 FM ( 0, 5, 0, 0, *f = "P5", *p = ".8um");
2048 FM ( 0, 5, 0, 1, *f = "P5", *p = ".8um");
2049 FM ( 0, 5, 0, 2, *f = "P5");
2050 FM ( 0, 5, 0, 3, *f = "P5", *p = ".6um");
2051 FM ( 0, 5, 0, 4, *f = "P5 MMX");
2052 FM ( 0, 5, 0, 7, *f = "P5 MMX");
2053 FM ( 0, 5, 0, 8, *f = "P5 MMX", *p = ".25um");
2054 FM ( 0, 5, 0, 9, *f = "P5 MMX");
2055 FM ( 0, 6, 0, 0, *f = "P6 Pentium II");
2056 FM ( 0, 6, 0, 1, *f = "P6 Pentium II"); // *p depends on core
2057 FM ( 0, 6, 0, 2, *f = "P6 Pentium II");
2058 FM ( 0, 6, 0, 3, *f = "P6 Pentium II", *p = ".35um");
2059 FM ( 0, 6, 0, 4, *f = "P6 Pentium II");
2060 FM ( 0, 6, 0, 5, *f = "P6 Pentium II", *p = ".25um");
2061 FM ( 0, 6, 0, 6, *f = "P6 Pentium II", *p = "L2 cache");
2062 FM ( 0, 6, 0, 7, *f = "P6 Pentium III", *p = ".25um");
2063 FM ( 0, 6, 0, 8, *f = "P6 Pentium III", *p = ".18um");
2064 FM ( 0, 6, 0, 9, *f = "P6 Pentium M", *p = ".13um");
2065 FM ( 0, 6, 0,10, *f = "P6 Pentium III", *p = ".18um");
2066 FM ( 0, 6, 0,11, *f = "P6 Pentium III", *p = ".13um");
2067 FM ( 0, 6, 0,13, *u = "Dothan", *f = "P6 Pentium M"); // *p depends on core
2068 FM ( 0, 6, 0,14, *u = "Yonah", *f = "P6 Pentium M", *p = "65nm");
2069 FM ( 0, 6, 0,15, *u = "Merom", *f = "Core", *p = "65nm");
2070 FM ( 0, 6, 1, 5, *u = "Dothan", *f = "P6 Pentium M", *p = "90nm");
2071 FM ( 0, 6, 1, 6, *u = "Merom", *f = "Core", *p = "65nm");
2072 FM ( 0, 6, 1, 7, *u = "Penryn", *f = "Core", *p = "45nm");
2073 FM ( 0, 6, 1,10, *u = "Nehalem", *f = "Nehalem", *p = "45nm");
2074 FM ( 0, 6, 1,12, *u = "Bonnell", *p = "45nm");
2075 FM ( 0, 6, 1,13, *u = "Penryn", *f = "Core", *p = "45nm");
2076 FM ( 0, 6, 1,14, *u = "Nehalem", *f = "Nehalem", *p = "45nm");
2077 FM ( 0, 6, 1,15, *u = "Nehalem", *f = "Nehalem", *p = "45nm");
2078 FM ( 0, 6, 2, 5, *u = "Westmere", *f = "Nehalem", *p = "32nm");
2079 FM ( 0, 6, 2, 6, *u = "Bonnell", *p = "45nm");
2080 FM ( 0, 6, 2, 7, *u = "Saltwell", *p = "32nm");
2081 FM ( 0, 6, 2,10, *u = "Sandy Bridge", *ciu = TRUE, *f = "Sandy Bridge", *p = "32nm");
2082 FM ( 0, 6, 2,12, *u = "Westmere", *f = "Nehalem", *p = "32nm");
2083 FM ( 0, 6, 2,13, *u = "Sandy Bridge", *ciu = TRUE, *f = "Sandy Bridge", *p = "32nm");
2084 FM ( 0, 6, 2,14, *u = "Nehalem", *f = "Nehalem", *p = "45nm");
2085 FM ( 0, 6, 2,15, *u = "Westmere", *f = "Nehalem", *p = "32nm");
2086 FM ( 0, 6, 3, 5, *u = "Saltwell", *p = "14nm");
2087 FM ( 0, 6, 3, 6, *u = "Saltwell", *p = "32nm");
2088 FM ( 0, 6, 3, 7, *u = "Silvermont", *p = "22nm");
2089 FM ( 0, 6, 3,10, *u = "Ivy Bridge", *ciu = TRUE, *f = "Sandy Bridge", *p = "22nm");
2090 FM ( 0, 6, 3,12, *u = "Haswell", *ciu = TRUE, *f = "Haswell", *p = "22nm");
2091 FM ( 0, 6, 3,13, *u = "Broadwell", *ciu = TRUE, *f = "Haswell", *p = "14nm");
2092 FM ( 0, 6, 3,14, *u = "Ivy Bridge", *ciu = TRUE, *f = "Sandy Bridge", *p = "22nm");
2093 FM ( 0, 6, 3,15, *u = "Haswell", *ciu = TRUE, *f = "Haswell", *p = "22nm");
2094 FM ( 0, 6, 4, 5, *u = "Haswell", *ciu = TRUE, *f = "Haswell", *p = "22nm");
2095 FM ( 0, 6, 4, 6, *u = "Haswell", *ciu = TRUE, *f = "Haswell", *p = "22nm");
2096 FM ( 0, 6, 4, 7, *u = "Broadwell", *ciu = TRUE, *f = "Haswell", *p = "14nm");
2097 FM ( 0, 6, 4,10, *u = "Silvermont", *p = "22nm"); // no docs, but /proc/cpuinfo seen in wild
2098 FM ( 0, 6, 4,12, *u = "Airmont", *p = "14nm");
2099 FM ( 0, 6, 4,13, *u = "Silvermont", *p = "22nm");
2100 FMS ( 0, 6, 4,14, 8, *u = "Kaby Lake", *f = "Skylake", *p = "14nm");
2101 FM ( 0, 6, 4,14, *u = "Skylake", *ciu = TRUE, *f = "Skylake", *p = "14nm");
2102 FM ( 0, 6, 4,15, *u = "Broadwell", *ciu = TRUE, *f = "Haswell", *p = "14nm");
2103 FMQ ( 0, 6, 5, 5, iM, *u = "Jintide Gen1", *ciu = TRUE); // undocumented; only instlatx64 example
2104 FMS ( 0, 6, 5, 5, 6, *u = "Cascade Lake", *ciu = TRUE, *f = "Skylake", *p = "14nm"); // no docs, but example from Greg Stewart
2105 FMS ( 0, 6, 5, 5, 7, *u = "Cascade Lake", *ciu = TRUE, *f = "Skylake", *p = "14nm");
2106 FMS ( 0, 6, 5, 5, 10, *u = "Cooper Lake", *ciu = TRUE, *f = "Skylake", *p = "14nm");
2107 FM ( 0, 6, 5, 5, *u = "Skylake", *ciu = TRUE, *f = "Skylake", *p = "14nm");
2108 FM ( 0, 6, 5, 6, *u = "Broadwell", *ciu = TRUE, *f = "Haswell", *p = "14nm");
2109 FM ( 0, 6, 5, 7, *u = "Knights Landing", *ciu = TRUE, *p = "14nm");
2110 FM ( 0, 6, 5,10, *u = "Silvermont", *p = "22nm"); // no spec update; only MSR_CPUID_table* so far
2111 FM ( 0, 6, 5,12, *u = "Goldmont", *p = "14nm"); // no spec update for Atom; only MSR_CPUID_table* so far
2112 FM ( 0, 6, 5,13, *u = "Silvermont", *p = "22nm"); // no spec update; only MSR_CPUID_table* so far
2113 FMS ( 0, 6, 5,14, 8, *u = "Kaby Lake", *f = "Skylake", *p = "14nm");
2114 FM ( 0, 6, 5,14, *u = "Skylake", *ciu = TRUE, *f = "Skylake", *p = "14nm");
2115 FM ( 0, 6, 5,15, *u = "Goldmont", *p = "14nm");
2116 FM ( 0, 6, 6, 6, *u = "Palm Cove", *f = "Skylake", *p = "10nm"); // no spec update; only MSR_CPUID_table* so far
2117 FM ( 0, 6, 6,10, *u = "Sunny Cove", *f = "Sunny Cove", *p = "10nm");
2118 FM ( 0, 6, 6,12, *u = "Sunny Cove", *f = "Sunny Cove", *p = "10nm"); // no spec update; only MSR_CPUID_table* so far
2119 FM ( 0, 6, 7, 5, *u = "Airmont", *p = "14nm"); // no spec update; whispers & rumors
2120 FM ( 0, 6, 7,10, *u = "Goldmont Plus", *p = "14nm");
2121 FM ( 0, 6, 7,13, *u = "Sunny Cove", *f = "Sunny Cove", *p = "10nm"); // no spec update; only MSR_CPUID_table* so far
2122 FM ( 0, 6, 7,14, *u = "Sunny Cove", *f = "Sunny Cove", *p = "10nm");
2123 FM ( 0, 6, 8, 5, *u = "Knights Mill", *ciu = TRUE, *p = "14nm"); // no spec update; only MSR_CPUID_table* so far
2124 FM ( 0, 6, 8, 6, *u = "Tremont", *p = "10nm"); // LX*
2125 FM ( 0, 6, 8,10, *u = "Tremont", *p = "10nm"); // no spec update; LX*
2126 FM ( 0, 6, 8,12, *u = "Willow Cove", *f = "Sunny Cove", *p = "10nm"); // no spec update; only MSR_CPUID_table* so far
2127 FM ( 0, 6, 8,13, *u = "Willow Cove", *f = "Sunny Cove", *p = "10nm"); // no spec update; only MSR_CPUID_table* so far
2128 FM ( 0, 6, 8,14, *u = "Kaby Lake", *f = "Skylake", *p = "14nm");
2129 FM ( 0, 6, 8,15, *u = "Sapphire Rapids", *f = "Sunny Cove", *p = "10nm"); // LX*
2130 FM ( 0, 6, 9, 6, *u = "Tremont", *p = "10nm"); // LX*
2131 FM ( 0, 6, 9, 7, *u = "Golden Cove", *p = "7nm"); // LX*
2132 FM ( 0, 6, 9,10, *u = "Golden Cove", *p = "7nm"); // Coreboot*
2133 FM ( 0, 6, 9,12, *u = "Tremont", *p = "10nm"); // LX*
2134 FM ( 0, 6, 9,13, *u = "Sunny Cove", *f = "Sunny Cove", *p = "10nm"); // LX*
2135 FMS ( 0, 6, 9,14, 9, *u = "Kaby Lake", *f = "Skylake", *p = "14nm");
2136 FMS ( 0, 6, 9,14, 10, *u = "Coffee Lake", *ciu = TRUE, *f = "Skylake", *p = "14nm");
2137 FMS ( 0, 6, 9,14, 11, *u = "Coffee Lake", *ciu = TRUE, *f = "Skylake", *p = "14nm");
2138 FMS ( 0, 6, 9,14, 12, *u = "Coffee Lake", *ciu = TRUE, *f = "Skylake", *p = "14nm");
2139 FMS ( 0, 6, 9,14, 13, *u = "Coffee Lake", *ciu = TRUE, *f = "Skylake", *p = "14nm");
2140 FM ( 0, 6, 9,14, *u = "Kaby Lake / Coffee Lake", *f = "Skylake", *p = "14nm");
2141 FM ( 0, 6, 10, 5, *u = "Kaby Lake", *f = "Skylake", *p = "14nm"); // LX*
2142 FM ( 0, 6, 10, 6, *u = "Kaby Lake", *f = "Skylake", *p = "14nm"); // no spec update; only instlatx64 example
2143 FM ( 0, 6, 10, 7, *u = "Cypress Cove", *f = "Sunny Cove", *p = "14nm"); // LX*
2144 F ( 0, 7, *u = "Itanium");
2145 FM ( 0,11, 0, 0, *u = "Knights Ferry", *ciu = TRUE, *f = "K1OM", *p = "45nm"); // found only on en.wikichip.org
2146 FM ( 0,11, 0, 1, *u = "Knights Corner", *ciu = TRUE, *f = "K1OM", *p = "22nm");
2147 FM ( 0,15, 0, 0, *u = "Willamette", *f = "Netburst", *p = ".18um");
2148 FM ( 0,15, 0, 1, *u = "Willamette", *f = "Netburst", *p = ".18um");
2149 FM ( 0,15, 0, 2, *u = "Northwood", *f = "Netburst", *p = ".13um");
2150 FM ( 0,15, 0, 3, *u = "Prescott", *f = "Netburst", *p = "90nm");
2151 FM ( 0,15, 0, 4, *u = "Prescott", *f = "Netburst", *p = "90nm");
2152 FM ( 0,15, 0, 6, *u = "Cedar Mill", *f = "Netburst", *p = "65nm");
2153 F ( 0,15, *f = "Netburst");
2154 FM ( 1,15, 0, 0, *u = "Itanium2", *p = ".18um");
2155 FM ( 1,15, 0, 1, *u = "Itanium2", *p = ".13um");
2156 FM ( 1,15, 0, 2, *u = "Itanium2", *p = ".13um");
2157 F ( 1,15, *u = "Itanium2");
2158 F ( 2, 0, *u = "Itanium2", *p = "90nm");
2159 F ( 2, 1, *u = "Itanium2");
2160 DEFAULT ((void)NULL);
2161 }
2162
2163 static void
decode_uarch_amd(unsigned int val,arch_t * arch)2164 decode_uarch_amd(unsigned int val,
2165 arch_t* arch)
2166 {
2167 init_arch(arch);
2168
2169 cstring* u = &arch->uarch;
2170 cstring* p = &arch->phys;
2171
2172 START;
2173 FM ( 0, 4, 0, 3, *u = "Am486");
2174 FM ( 0, 4, 0, 7, *u = "Am486");
2175 FM ( 0, 4, 0, 8, *u = "Am486");
2176 FM ( 0, 4, 0, 9, *u = "Am486");
2177 F ( 0, 4, *u = "Am5x86");
2178 FM ( 0, 5, 0, 6, *u = "K6", *p = ".30um");
2179 FM ( 0, 5, 0, 7, *u = "K6", *p = ".25um"); // *p from sandpile.org
2180 FM ( 0, 5, 0,13, *u = "K6", *p = ".18um"); // *p from sandpile.org
2181 F ( 0, 5, *u = "K6");
2182 FM ( 0, 6, 0, 1, *u = "K7", *p = ".25um");
2183 FM ( 0, 6, 0, 2, *u = "K7", *p = ".18um");
2184 F ( 0, 6, *u = "K7");
2185 FMS ( 0,15, 0, 4, 8, *u = "K8", *p = "754-pin, .13um");
2186 FM ( 0,15, 0, 4, *u = "K8", *p = "940-pin, .13um");
2187 FM ( 0,15, 0, 5, *u = "K8", *p = "940-pin, .13um");
2188 FM ( 0,15, 0, 7, *u = "K8", *p = "939-pin, .13um");
2189 FM ( 0,15, 0, 8, *u = "K8", *p = "754-pin, .13um");
2190 FM ( 0,15, 0,11, *u = "K8", *p = "939-pin, .13um");
2191 FM ( 0,15, 0,12, *u = "K8", *p = "754-pin, .13um");
2192 FM ( 0,15, 0,14, *u = "K8", *p = "754-pin, .13um");
2193 FM ( 0,15, 0,15, *u = "K8", *p = "939-pin, .13um");
2194 FM ( 0,15, 1, 4, *u = "K8", *p = "754-pin, 90nm");
2195 FM ( 0,15, 1, 5, *u = "K8", *p = "940-pin, 90nm");
2196 FM ( 0,15, 1, 7, *u = "K8", *p = "939-pin, 90nm");
2197 FM ( 0,15, 1, 8, *u = "K8", *p = "754-pin, 90nm");
2198 FM ( 0,15, 1,11, *u = "K8", *p = "939-pin, 90nm");
2199 FM ( 0,15, 1,12, *u = "K8", *p = "754-pin, 90nm");
2200 FM ( 0,15, 1,15, *u = "K8", *p = "939-pin, 90nm");
2201 FM ( 0,15, 2, 1, *u = "K8", *p = "940-pin, 90nm");
2202 FM ( 0,15, 2, 3, *u = "K8", *p = "939-pin, 90nm");
2203 FM ( 0,15, 2, 4, *u = "K8", *p = "754-pin, 90nm");
2204 FM ( 0,15, 2, 5, *u = "K8", *p = "940-pin, 90nm");
2205 FM ( 0,15, 2, 7, *u = "K8", *p = "939-pin, 90nm");
2206 FM ( 0,15, 2,11, *u = "K8", *p = "939-pin, 90nm");
2207 FM ( 0,15, 2,12, *u = "K8", *p = "754-pin, 90nm");
2208 FM ( 0,15, 2,15, *u = "K8", *p = "939-pin, 90nm");
2209 FM ( 0,15, 4, 1, *u = "K8", *p = "90nm");
2210 FM ( 0,15, 4, 3, *u = "K8", *p = "90nm");
2211 FM ( 0,15, 4, 8, *u = "K8", *p = "90nm");
2212 FM ( 0,15, 4,11, *u = "K8", *p = "90nm");
2213 FM ( 0,15, 4,12, *u = "K8", *p = "90nm");
2214 FM ( 0,15, 4,15, *u = "K8", *p = "90nm");
2215 FM ( 0,15, 5,13, *u = "K8", *p = "90nm");
2216 FM ( 0,15, 5,15, *u = "K8", *p = "90nm");
2217 FM ( 0,15, 6, 8, *u = "K8", *p = "65nm");
2218 FM ( 0,15, 6,11, *u = "K8", *p = "65nm");
2219 FM ( 0,15, 6,12, *u = "K8", *p = "65nm");
2220 FM ( 0,15, 6,15, *u = "K8", *p = "65nm");
2221 FM ( 0,15, 7,12, *u = "K8", *p = "65nm");
2222 FM ( 0,15, 7,15, *u = "K8", *p = "65nm");
2223 FM ( 0,15, 12, 1, *u = "K8", *p = "90nm");
2224 FM ( 1,15, 0, 0, *u = "K10", *p = "65nm"); // sandpile.org
2225 FM ( 1,15, 0, 2, *u = "K10", *p = "65nm");
2226 FM ( 1,15, 0, 4, *u = "K10", *p = "45nm");
2227 FM ( 1,15, 0, 5, *u = "K10", *p = "45nm");
2228 FM ( 1,15, 0, 6, *u = "K10", *p = "45nm");
2229 FM ( 1,15, 0, 8, *u = "K10", *p = "45nm");
2230 FM ( 1,15, 0, 9, *u = "K10", *p = "45nm");
2231 FM ( 1,15, 0,10, *u = "K10", *p = "45nm");
2232 F ( 2,15, *u = "Puma 2008", *p = "65nm");
2233 F ( 3,15, *u = "K10", *p = "32nm");
2234 F ( 5,15, *u = "Bobcat", *p = "40nm");
2235 FM ( 6,15, 0, 0, *u = "Bulldozer", *p = "32nm"); // instlatx64 engr sample
2236 FM ( 6,15, 0, 1, *u = "Bulldozer", *p = "32nm");
2237 FM ( 6,15, 0, 2, *u = "Piledriver", *p = "32nm");
2238 FM ( 6,15, 1, 0, *u = "Piledriver", *p = "32nm");
2239 FM ( 6,15, 1, 3, *u = "Piledriver", *p = "32nm");
2240 FM ( 6,15, 3, 0, *u = "Steamroller", *p = "28nm");
2241 FM ( 6,15, 3, 8, *u = "Steamroller", *p = "28nm");
2242 FM ( 6,15, 4, 0, *u = "Steamroller", *p = "28nm"); // Software Optimization Guide (15h) says it has the same inst latencies as (6,15),(3,x).
2243 FM ( 6,15, 6, 0, *u = "Excavator", *p = "28nm"); // undocumented, but instlatx64 samples
2244 FM ( 6,15, 6, 5, *u = "Excavator", *p = "28nm"); // undocumented, but sample from Alexandros Couloumbis
2245 FM ( 6,15, 7, 0, *u = "Excavator", *p = "28nm");
2246 FM ( 7,15, 0, 0, *u = "Jaguar", *p = "28nm");
2247 FM ( 7,15, 2, 6, *u = "Cato", *p = "28nm"); // only instlatx64 example; engr sample?
2248 FM ( 7,15, 3, 0, *u = "Puma 2014", *p = "28nm");
2249 FM ( 8,15, 0, 0, *u = "Zen", *p = "14nm"); // instlatx64 engr sample
2250 FM ( 8,15, 0, 1, *u = "Zen", *p = "14nm");
2251 FM ( 8,15, 0, 8, *u = "Zen+", *p = "12nm");
2252 FM ( 8,15, 1, 1, *u = "Zen", *p = "14nm"); // found only on en.wikichip.org & instlatx64 examples
2253 FM ( 8,15, 1, 8, *u = "Zen+", *p = "12nm");
2254 FM ( 8,15, 2, 0, *u = "Zen", *p = "14nm");
2255 FM ( 8,15, 3, 1, *u = "Zen 2", *p = "7nm"); // found only on en.wikichip.org
2256 FM ( 8,15, 4, 7, *u = "Zen 2", *p = "7nm"); // only instlatx64 example; engr sample?
2257 FM ( 8,15, 6, 0, *u = "Zen 2", *p = "7nm");
2258 FM ( 8,15, 6, 8, *u = "Zen 2", *p = "7nm"); // undocumented, but instlatx64 samples
2259 FM ( 8,15, 7, 1, *u = "Zen 2", *p = "7nm"); // undocumented, but samples from Steven Noonan
2260 F (10,15, *u = "Zen 3", *p = "7nm");
2261 DEFAULT ((void)NULL);
2262 }
2263
2264 static void
decode_uarch_cyrix(unsigned int val,arch_t * arch)2265 decode_uarch_cyrix(unsigned int val,
2266 arch_t* arch)
2267 {
2268 init_arch(arch);
2269
2270 cstring* u = &arch->uarch;
2271 boolean* ciu = &arch->core_is_uarch;
2272
2273 START;
2274 F (0, 5, *u = "M1", *ciu = TRUE);
2275 F (0, 6, *u = "M2", *ciu = TRUE);
2276 DEFAULT ((void)NULL);
2277 }
2278
2279 static void
decode_uarch_via(unsigned int val,arch_t * arch,const code_stash_t * stash)2280 decode_uarch_via(unsigned int val,
2281 arch_t* arch,
2282 const code_stash_t* stash)
2283 {
2284 init_arch(arch);
2285
2286 cstring* u = &arch->uarch;
2287 boolean* ciu = &arch->core_is_uarch;
2288 cstring* p = &arch->phys;
2289
2290 START;
2291 F (0, 5, *u = "WinChip", *ciu = TRUE);
2292 FM (0, 6, 0, 6, *u = "C3", *ciu = TRUE, *p = ".18um");
2293 FM (0, 6, 0, 7, *u = "C3", *ciu = TRUE); // *p depends on core
2294 FM (0, 6, 0, 8, *u = "C3", *ciu = TRUE, *p = ".13um");
2295 FM (0, 6, 0, 9, *u = "C3", *ciu = TRUE, *p = ".13um");
2296 FM (0, 6, 0,10, *u = "C7", *p = "90nm");
2297 FM (0, 6, 0,13, *u = "C7", *p = "90nm");
2298 FMSQ(0, 6, 0,15, 14, vZ, *u = "ZhangJiang", *p = "28nm");
2299 FM (0, 6, 0,15, *u = "C7"); // *p depends on core
2300 FM (0, 7, 0,11, *u = "ZhangJiang", *p = "28nm");
2301 DEFAULT ((void)NULL);
2302 }
2303
2304 static void
decode_uarch_umc(unsigned int val,arch_t * arch)2305 decode_uarch_umc(unsigned int val,
2306 arch_t* arch)
2307 {
2308 init_arch(arch);
2309
2310 cstring* u = &arch->uarch;
2311 boolean* ciu = &arch->core_is_uarch;
2312
2313 START;
2314 F (0, 4, *u = "486 U5", *ciu = TRUE);
2315 DEFAULT ((void)NULL);
2316 }
2317
2318 static void
decode_uarch_nexgen(unsigned int val,arch_t * arch)2319 decode_uarch_nexgen(unsigned int val,
2320 arch_t* arch)
2321 {
2322 init_arch(arch);
2323
2324 cstring* u = &arch->uarch;
2325
2326 START;
2327 F (0, 5, *u = "Nx586");
2328 DEFAULT ((void)NULL);
2329 }
2330
2331 static void
decode_uarch_rise(unsigned int val,arch_t * arch)2332 decode_uarch_rise(unsigned int val,
2333 arch_t* arch)
2334 {
2335 init_arch(arch);
2336
2337 cstring* u = &arch->uarch;
2338 boolean* ciu = &arch->core_is_uarch;
2339
2340 START;
2341 F (0, 5, *u = "mP6", *ciu = TRUE);
2342 DEFAULT ((void)NULL);
2343 }
2344
2345 static void
decode_uarch_transmeta(unsigned int val,arch_t * arch)2346 decode_uarch_transmeta(unsigned int val,
2347 arch_t* arch)
2348 {
2349 init_arch(arch);
2350
2351 cstring* u = &arch->uarch;
2352 boolean* ciu = &arch->core_is_uarch;
2353
2354 START;
2355 F (0, 5, *u = "Crusoe", *ciu = TRUE);
2356 F (0,15, *u = "Efficeon", *ciu = TRUE);
2357 DEFAULT ((void)NULL);
2358 }
2359
2360 static void
decode_uarch_sis(unsigned int val,arch_t * arch)2361 decode_uarch_sis(unsigned int val,
2362 arch_t* arch)
2363 {
2364 init_arch(arch);
2365
2366 cstring* u = &arch->uarch;
2367 boolean* ciu = &arch->core_is_uarch;
2368
2369 START;
2370 F (0, 5, *u = "mP6", *ciu = TRUE);
2371 DEFAULT ((void)NULL);
2372 }
2373
2374 static void
decode_uarch_hygon(unsigned int val,arch_t * arch)2375 decode_uarch_hygon(unsigned int val,
2376 arch_t* arch)
2377 {
2378 init_arch(arch);
2379
2380 cstring* u = &arch->uarch;
2381 cstring* p = &arch->phys;
2382
2383 START;
2384 FM (9,15, 0, 0, *u = "Moksha", *p = "14nm");
2385 DEFAULT ((void)NULL);
2386 }
2387
2388 static void
decode_uarch_zhaoxin(unsigned int val,arch_t * arch)2389 decode_uarch_zhaoxin(unsigned int val,
2390 arch_t* arch)
2391 {
2392 init_arch(arch);
2393
2394 cstring* u = &arch->uarch;
2395 boolean* ciu = &arch->core_is_uarch;
2396 cstring* p = &arch->phys;
2397
2398 START;
2399 FM (0, 7, 1,11, *u = "WuDaoKou", *ciu = TRUE, *p = "28nm");
2400 FM (0, 7, 3,11, *u = "LuJiaZui", *ciu = TRUE, *p = "16nm");
2401 DEFAULT ((void)NULL);
2402 }
2403
2404 #undef ACT
2405
2406 static void
decode_uarch(unsigned int val,vendor_t vendor,const code_stash_t * stash,arch_t * arch)2407 decode_uarch(unsigned int val,
2408 vendor_t vendor,
2409 const code_stash_t* stash,
2410 arch_t* arch)
2411 {
2412 init_arch(arch);
2413
2414 switch (vendor) {
2415 case VENDOR_INTEL:
2416 decode_uarch_intel(val, arch, stash);
2417 break;
2418 case VENDOR_AMD:
2419 decode_uarch_amd(val, arch);
2420 break;
2421 case VENDOR_CYRIX:
2422 decode_uarch_cyrix(val, arch);
2423 break;
2424 case VENDOR_VIA:
2425 decode_uarch_via(val, arch, stash);
2426 break;
2427 case VENDOR_TRANSMETA:
2428 decode_uarch_transmeta(val, arch);
2429 break;
2430 case VENDOR_UMC:
2431 decode_uarch_umc(val, arch);
2432 break;
2433 case VENDOR_NEXGEN:
2434 decode_uarch_nexgen(val, arch);
2435 break;
2436 case VENDOR_RISE:
2437 decode_uarch_rise(val, arch);
2438 break;
2439 case VENDOR_SIS:
2440 decode_uarch_sis(val, arch);
2441 break;
2442 case VENDOR_HYGON:
2443 decode_uarch_hygon(val, arch);
2444 break;
2445 case VENDOR_ZHAOXIN:
2446 decode_uarch_zhaoxin(val, arch);
2447 break;
2448 case VENDOR_NSC:
2449 case VENDOR_VORTEX:
2450 case VENDOR_RDC:
2451 case VENDOR_UNKNOWN:
2452 break;
2453 }
2454 }
2455
2456 static void
print_uarch(const code_stash_t * stash)2457 print_uarch(const code_stash_t* stash)
2458 {
2459 arch_t arch;
2460 decode_uarch(stash->val_1_eax, stash->vendor, stash, &arch);
2461 if (arch.uarch != NULL || arch.family != NULL || arch.phys != NULL) {
2462 ccstring vendor = decode_vendor(stash->vendor, stash);
2463 printf(" (uarch synth) =");
2464 if (vendor != NULL) {
2465 printf(" %s", vendor);
2466 }
2467 if (arch.uarch != NULL) {
2468 printf(" %s", arch.uarch);
2469 }
2470 if (arch.family != NULL) {
2471 printf(" {%s}", arch.family);
2472 }
2473 if (arch.phys != NULL) {
2474 printf(", %s", arch.phys);
2475 }
2476 printf("\n");
2477 }
2478 }
2479
2480 static cstring
append_uarch(ccstring synth,unsigned int val,vendor_t vendor,const code_stash_t * stash)2481 append_uarch(ccstring synth,
2482 unsigned int val,
2483 vendor_t vendor,
2484 const code_stash_t* stash)
2485 {
2486 if (synth != NULL) {
2487 arch_t arch;
2488 decode_uarch(val, vendor, stash, &arch);
2489 if ((arch.uarch != NULL && !arch.core_is_uarch)
2490 || arch.family != NULL
2491 || arch.phys != NULL) {
2492 static char buffer[1024];
2493 char* ptr = buffer;
2494
2495 ptr += sprintf(ptr, "%s", synth);
2496
2497 if (arch.uarch != NULL && !arch.core_is_uarch) {
2498 ptr += sprintf(ptr, " [%s]", arch.uarch);
2499 }
2500 if (arch.family != NULL) {
2501 ptr += sprintf(ptr, " {%s}", arch.family);
2502 }
2503 if (arch.phys != NULL) {
2504 ptr += sprintf(ptr, ", %s", arch.phys);
2505 }
2506 return buffer;
2507 }
2508 }
2509
2510 return synth;
2511 }
2512
2513 static void
debug_queries(const code_stash_t * stash)2514 debug_queries(const code_stash_t* stash)
2515 {
2516 #define DEBUGQ(q) printf("%s = %s\n", #q, (q) ? "TRUE" : "FALSE")
2517 #define DEBUGF(f) printf("%s = %s\n", #f, f(stash) ? "TRUE" : "FALSE")
2518
2519 DEBUGQ(is_intel);
2520 DEBUGQ(is_amd);
2521 DEBUGQ(is_transmeta);
2522 DEBUGQ(is_mobile);
2523 DEBUGQ(MC);
2524 DEBUGQ(Mc);
2525 DEBUGQ(MP);
2526 DEBUGQ(sM);
2527 DEBUGQ(sX);
2528 DEBUGQ(dC);
2529 DEBUGQ(da);
2530 DEBUGQ(MM);
2531 DEBUGQ(dd);
2532 DEBUGQ(dP);
2533 DEBUGQ(Xc);
2534 DEBUGQ(dc);
2535 DEBUGQ(dG);
2536
2537 DEBUGQ(xD);
2538 DEBUGQ(mD);
2539 DEBUGQ(cD);
2540 DEBUGQ(xK);
2541 DEBUGQ(pK);
2542 DEBUGQ(sI);
2543 DEBUGQ(sP);
2544 DEBUGQ(dL);
2545 DEBUGQ(QW);
2546 DEBUGQ(DG);
2547 DEBUGQ(Qc);
2548 DEBUGQ(XE);
2549 DEBUGQ(sQ);
2550 DEBUGQ(s7);
2551 DEBUGQ(de);
2552 DEBUGQ(Me);
2553 DEBUGQ(Qe);
2554 DEBUGQ(se);
2555
2556 DEBUGQ(dp);
2557 DEBUGQ(dX);
2558 DEBUGQ(dF);
2559 DEBUGQ(df);
2560 DEBUGQ(dD);
2561 DEBUGQ(dS);
2562 DEBUGQ(dR);
2563 DEBUGQ(sO);
2564 DEBUGQ(sA);
2565 DEBUGQ(sD);
2566 DEBUGQ(sE);
2567 DEBUGQ(dD);
2568 DEBUGQ(dA);
2569 DEBUGQ(dS);
2570 DEBUGQ(ML);
2571 DEBUGQ(MX);
2572 DEBUGQ(MD);
2573 DEBUGQ(MA);
2574 DEBUGQ(MS);
2575 DEBUGQ(Mp);
2576 DEBUGQ(Ms);
2577 DEBUGQ(MG);
2578 DEBUGQ(MT);
2579 DEBUGQ(Mn);
2580 DEBUGQ(MN);
2581 DEBUGQ(Sa);
2582
2583 DEBUGF(is_amd_egypt_athens_8xx);
2584 DEBUGQ(EO);
2585 DEBUGQ(DO);
2586 DEBUGQ(SO);
2587 DEBUGQ(DA);
2588 DEBUGQ(TA);
2589 DEBUGQ(QA);
2590 DEBUGQ(Dp);
2591 DEBUGQ(Tp);
2592 DEBUGQ(Qp);
2593 DEBUGQ(Sp);
2594 DEBUGQ(DS);
2595 DEBUGQ(s8);
2596 DEBUGQ(dt);
2597 DEBUGQ(dm);
2598 DEBUGQ(dr);
2599 DEBUGQ(Mt);
2600
2601 DEBUGQ(t2);
2602 DEBUGQ(t4);
2603 DEBUGQ(t5);
2604 DEBUGQ(t6);
2605 DEBUGQ(t8);
2606
2607 #undef DEBUGQ
2608 #undef DEBUGF
2609 }
2610
2611 #define ACT(str) (result = (str))
2612
2613 static cstring
decode_synth_intel(unsigned int val,const code_stash_t * stash)2614 decode_synth_intel(unsigned int val, /* val_1_eax */
2615 const code_stash_t* stash)
2616 {
2617 cstring result = NULL;
2618
2619 START;
2620 FM ( 0, 4, 0, 0, "Intel i80486DX-25/33, .18um"); // process from sandpile.org
2621 FM ( 0, 4, 0, 1, "Intel i80486DX-50, .18um"); // process from sandpile.org
2622 FM ( 0, 4, 0, 2, "Intel i80486SX, .18um"); // process from sandpile.org
2623 FM ( 0, 4, 0, 3, "Intel i80486DX/2");
2624 FM ( 0, 4, 0, 4, "Intel i80486SL, .8um");
2625 FM ( 0, 4, 0, 5, "Intel i80486SX/2, .8um");
2626 FM ( 0, 4, 0, 7, "Intel i80486DX/2-WB, .8um");
2627 FM ( 0, 4, 0, 8, "Intel i80486DX/4, .6um");
2628 FM ( 0, 4, 0, 9, "Intel i80486DX/4-WB, .6um");
2629 F ( 0, 4, "Intel i80486 (unknown model)");
2630 FM ( 0, 5, 0, 0, "Intel Pentium 60/66 A-step"); // no docs
2631 // Intel docs (243326).
2632 TFM (1, 0, 5, 0, 1, "Intel Pentium 60/66 OverDrive for P5");
2633 FMS ( 0, 5, 0, 1, 3, "Intel Pentium 60/66 (B1)");
2634 FMS ( 0, 5, 0, 1, 5, "Intel Pentium 60/66 (C1)");
2635 FMS ( 0, 5, 0, 1, 7, "Intel Pentium 60/66 (D1)");
2636 FM ( 0, 5, 0, 1, "Intel Pentium 60/66");
2637 // Intel docs (242480).
2638 TFM (1, 0, 5, 0, 2, "Intel Pentium 75 - 200 OverDrive for P54C");
2639 FMS ( 0, 5, 0, 2, 1, "Intel Pentium P54C 75 - 200 (B1)");
2640 FMS ( 0, 5, 0, 2, 2, "Intel Pentium P54C 75 - 200 (B3)");
2641 FMS ( 0, 5, 0, 2, 4, "Intel Pentium P54C 75 - 200 (B5)");
2642 FMS ( 0, 5, 0, 2, 5, "Intel Pentium P54C 75 - 200 (C2/mA1)");
2643 FMS ( 0, 5, 0, 2, 6, "Intel Pentium P54C 75 - 200 (E0)");
2644 FMS ( 0, 5, 0, 2, 11, "Intel Pentium P54C 75 - 200 (cB1)");
2645 FMS ( 0, 5, 0, 2, 12, "Intel Pentium P54C 75 - 200 (cC0)");
2646 FM ( 0, 5, 0, 2, "Intel Pentium P54C 75 - 200");
2647 TFM (1, 0, 5, 0, 3, "Intel Pentium OverDrive for i486 (P24T)"); // no docs
2648 // Intel docs (242480).
2649 TFM (1, 0, 5, 0, 4, "Intel Pentium OverDrive for P54C");
2650 FMS ( 0, 5, 0, 4, 3, "Intel Pentium MMX P55C (B1)");
2651 FMS ( 0, 5, 0, 4, 4, "Intel Pentium MMX P55C (A3)");
2652 FM ( 0, 5, 0, 4, "Intel Pentium MMX P55C");
2653 // Intel docs (242480).
2654 FMS ( 0, 5, 0, 7, 0, "Intel Pentium MMX P54C 75 - 200 (A4)");
2655 FM ( 0, 5, 0, 7, "Intel Pentium MMX P54C 75 - 200");
2656 // Intel docs (242480).
2657 FMS ( 0, 5, 0, 8, 1, "Intel Pentium MMX P55C (Tillamook A0)");
2658 FMS ( 0, 5, 0, 8, 2, "Intel Pentium MMX P55C (Tillamook B2)");
2659 FM ( 0, 5, 0, 8, "Intel Pentium MMX P55C (Tillamook)");
2660 // Intel docs (329676) provides stepping names, but no numbers.
2661 // However, A0 is the only name.
2662 FM ( 0, 5, 0, 9, "Intel Quark X1000 / D1000 / D2000 / C1000 (Lakemont)");
2663 F ( 0, 5, "Intel Pentium (unknown model)");
2664 FM ( 0, 6, 0, 0, "Intel Pentium Pro A-step");
2665 // Intel docs (242689).
2666 FMS ( 0, 6, 0, 1, 1, "Intel Pentium Pro (B0)");
2667 FMS ( 0, 6, 0, 1, 2, "Intel Pentium Pro (C0)");
2668 FMS ( 0, 6, 0, 1, 6, "Intel Pentium Pro (sA0)");
2669 FMS ( 0, 6, 0, 1, 7, "Intel Pentium Pro (sA1), .35um");
2670 FMS ( 0, 6, 0, 1, 9, "Intel Pentium Pro (sB1), .35um");
2671 FM ( 0, 6, 0, 1, "Intel Pentium Pro");
2672 // Intel docs (243337)
2673 TFM (1, 0, 6, 0, 3, "Intel Pentium II OverDrive");
2674 FMS ( 0, 6, 0, 3, 3, "Intel Pentium II (Klamath C0)");
2675 FMS ( 0, 6, 0, 3, 4, "Intel Pentium II (Klamath C1)");
2676 FM ( 0, 6, 0, 3, "Intel Pentium II (Klamath)");
2677 FM ( 0, 6, 0, 4, "Intel Pentium P55CT OverDrive (Deschutes)");
2678 // Intel docs (243337, 243748, 243776, 243887).
2679 FMSQ( 0, 6, 0, 5, 0, xD, "Intel Pentium II Xeon (Deschutes A0)");
2680 FMSQ( 0, 6, 0, 5, 0, mD, "Intel Mobile Pentium II (Deschutes A0)");
2681 FMSQ( 0, 6, 0, 5, 0, cD, "Intel Celeron (Deschutes A0)");
2682 FMS ( 0, 6, 0, 5, 0, "Intel Pentium II (unknown type) (Deschutes A0)");
2683 FMSQ( 0, 6, 0, 5, 1, xD, "Intel Pentium II Xeon (Deschutes A1)");
2684 FMSQ( 0, 6, 0, 5, 1, cD, "Intel Celeron (Deschutes A1)");
2685 FMS ( 0, 6, 0, 5, 1, "Intel Pentium II (unknown type) (Deschutes A1)");
2686 FMSQ( 0, 6, 0, 5, 2, xD, "Intel Pentium II Xeon (Deschutes B0)");
2687 FMSQ( 0, 6, 0, 5, 2, mD, "Intel Mobile Pentium II (Deschutes B0)");
2688 FMSQ( 0, 6, 0, 5, 2, cD, "Intel Celeron (Deschutes B0)");
2689 FMS ( 0, 6, 0, 5, 2, "Intel Pentium II (unknown type) (Deschutes B0)");
2690 FMSQ( 0, 6, 0, 5, 3, xD, "Intel Pentium II Xeon (Deschutes B1)");
2691 FMSQ( 0, 6, 0, 5, 3, cD, "Intel Celeron (Deschutes B1)");
2692 FMS ( 0, 6, 0, 5, 3, "Intel Pentium II (unknown type) (Deschutes B1)");
2693 FMQ ( 0, 6, 0, 5, xD, "Intel Pentium II Xeon (Deschutes)");
2694 FMQ ( 0, 6, 0, 5, mD, "Intel Mobile Pentium II (Deschutes)");
2695 FMQ ( 0, 6, 0, 5, cD, "Intel Celeron (Deschutes)");
2696 FM ( 0, 6, 0, 5, "Intel Pentium II (unknown type) (Deschutes)");
2697 // Intel docs (243748, 243887, 244444).
2698 FMSQ( 0, 6, 0, 6, 0, dP, "Intel Pentium II (Mendocino A0)");
2699 FMSQ( 0, 6, 0, 6, 0, dC, "Intel Celeron (Mendocino A0)");
2700 FMS ( 0, 6, 0, 6, 0, "Intel Pentium II (unknown type) (Mendocino A0)");
2701 FMSQ( 0, 6, 0, 6, 5, dC, "Intel Celeron (Mendocino B0)");
2702 FMSQ( 0, 6, 0, 6, 5, dP, "Intel Pentium II (Mendocino B0)");
2703 FMS ( 0, 6, 0, 6, 5, "Intel Pentium II (unknown type) (Mendocino B0)");
2704 FMS ( 0, 6, 0, 6, 10, "Intel Mobile Pentium II (Mendocino A0)");
2705 FM ( 0, 6, 0, 6, "Intel Pentium II (Mendocino)");
2706 // Intel docs (244453, 244460).
2707 FMSQ( 0, 6, 0, 7, 2, pK, "Intel Pentium III (Katmai B0)");
2708 FMSQ( 0, 6, 0, 7, 2, xK, "Intel Pentium III Xeon (Katmai B0)");
2709 FMS ( 0, 6, 0, 7, 2, "Intel Pentium III (unknown type) (Katmai B0)");
2710 FMSQ( 0, 6, 0, 7, 3, pK, "Intel Pentium III (Katmai C0)");
2711 FMSQ( 0, 6, 0, 7, 3, xK, "Intel Pentium III Xeon (Katmai C0)");
2712 FMS ( 0, 6, 0, 7, 3, "Intel Pentium III (unknown type) (Katmai C0)");
2713 FMQ ( 0, 6, 0, 7, pK, "Intel Pentium III (Katmai)");
2714 FMQ ( 0, 6, 0, 7, xK, "Intel Pentium III Xeon (Katmai)");
2715 FM ( 0, 6, 0, 7, "Intel Pentium III (unknown type) (Katmai)");
2716 // Intel docs (243748, 244453, 244460, 245306, 245421).
2717 FMSQ( 0, 6, 0, 8, 1, sX, "Intel Pentium III Xeon (Coppermine A2)");
2718 FMSQ( 0, 6, 0, 8, 1, MC, "Intel Mobile Celeron (Coppermine A2)");
2719 FMSQ( 0, 6, 0, 8, 1, dC, "Intel Celeron (Coppermine A2)");
2720 FMSQ( 0, 6, 0, 8, 1, MP, "Intel Mobile Pentium III (Coppermine A2)");
2721 FMSQ( 0, 6, 0, 8, 1, dP, "Intel Pentium III (Coppermine A2)");
2722 FMS ( 0, 6, 0, 8, 1, "Intel Pentium III (unknown type) (Coppermine A2)");
2723 FMSQ( 0, 6, 0, 8, 3, sX, "Intel Pentium III Xeon (Coppermine B0)");
2724 FMSQ( 0, 6, 0, 8, 3, MC, "Intel Mobile Celeron (Coppermine B0)");
2725 FMSQ( 0, 6, 0, 8, 3, dC, "Intel Celeron (Coppermine B0)");
2726 FMSQ( 0, 6, 0, 8, 3, MP, "Intel Mobile Pentium III (Coppermine B0)");
2727 FMSQ( 0, 6, 0, 8, 3, dP, "Intel Pentium III (Coppermine B0)");
2728 FMS ( 0, 6, 0, 8, 3, "Intel Pentium III (unknown type) (Coppermine B0)");
2729 FMSQ( 0, 6, 0, 8, 6, sX, "Intel Pentium III Xeon (Coppermine C0)");
2730 FMSQ( 0, 6, 0, 8, 6, MC, "Intel Mobile Celeron (Coppermine C0)");
2731 FMSQ( 0, 6, 0, 8, 6, dC, "Intel Celeron (Coppermine C0)");
2732 FMSQ( 0, 6, 0, 8, 6, MP, "Intel Mobile Pentium III (Coppermine C0)");
2733 FMSQ( 0, 6, 0, 8, 6, dP, "Intel Pentium III (Coppermine C0)");
2734 FMS ( 0, 6, 0, 8, 6, "Intel Pentium III (unknown type) (Coppermine C0)");
2735 FMSQ( 0, 6, 0, 8, 10, sX, "Intel Pentium III Xeon (Coppermine D0)");
2736 FMSQ( 0, 6, 0, 8, 10, MC, "Intel Mobile Celeron (Coppermine D0)");
2737 FMSQ( 0, 6, 0, 8, 10, dC, "Intel Celeron (Coppermine D0)");
2738 FMSQ( 0, 6, 0, 8, 10, MP, "Intel Mobile Pentium III (Coppermine D0)");
2739 FMSQ( 0, 6, 0, 8, 10, dP, "Intel Pentium III (Coppermine D0)");
2740 FMS ( 0, 6, 0, 8, 10, "Intel Pentium III (unknown type) (Coppermine D0)");
2741 FMQ ( 0, 6, 0, 8, sX, "Intel Pentium III Xeon (Coppermine)");
2742 FMQ ( 0, 6, 0, 8, MC, "Intel Mobile Celeron (Coppermine)");
2743 FMQ ( 0, 6, 0, 8, dC, "Intel Celeron (Coppermine)");
2744 FMQ ( 0, 6, 0, 8, MP, "Intel Mobile Pentium III (Coppermine)");
2745 FMQ ( 0, 6, 0, 8, dP, "Intel Pentium III (Coppermine)");
2746 FM ( 0, 6, 0, 8, "Intel Pentium III (unknown type) (Coppermine)");
2747 // Intel docs (252665, 300303).
2748 FMSQ( 0, 6, 0, 9, 5, dC, "Intel Celeron M (Banias B1)");
2749 FMSQ( 0, 6, 0, 9, 5, dP, "Intel Pentium M (Banias B1)");
2750 FMS ( 0, 6, 0, 9, 5, "Intel Pentium M (unknown type) (Banias B1)");
2751 FMQ ( 0, 6, 0, 9, dC, "Intel Celeron M (Banias)");
2752 FMQ ( 0, 6, 0, 9, dP, "Intel Pentium M (Banias)");
2753 FM ( 0, 6, 0, 9, "Intel Pentium M (unknown type) (Banias)");
2754 // Intel docs (244460).
2755 FMS ( 0, 6, 0,10, 0, "Intel Pentium III Xeon (Cascades A0)");
2756 FMS ( 0, 6, 0,10, 1, "Intel Pentium III Xeon (Cascades A1)");
2757 FMS ( 0, 6, 0,10, 4, "Intel Pentium III Xeon (Cascades B0)");
2758 FM ( 0, 6, 0,10, "Intel Pentium III Xeon (Cascades)");
2759 // Intel docs (243748, 244453, 245306, 245421).
2760 FMSQ( 0, 6, 0,11, 1, dC, "Intel Celeron (Tualatin A1)");
2761 FMSQ( 0, 6, 0,11, 1, MC, "Intel Mobile Celeron (Tualatin A1)");
2762 FMSQ( 0, 6, 0,11, 1, dP, "Intel Pentium III (Tualatin A1)");
2763 FMS ( 0, 6, 0,11, 1, "Intel Pentium III (unknown type) (Tualatin A1)");
2764 FMSQ( 0, 6, 0,11, 4, dC, "Intel Celeron (Tualatin B1)");
2765 FMSQ( 0, 6, 0,11, 4, MC, "Intel Mobile Celeron (Tualatin B1)");
2766 FMSQ( 0, 6, 0,11, 4, dP, "Intel Pentium III (Tualatin B1)");
2767 FMS ( 0, 6, 0,11, 4, "Intel Pentium III (unknown type) (Tualatin B1)");
2768 FMQ ( 0, 6, 0,11, dC, "Intel Celeron (Tualatin)");
2769 FMQ ( 0, 6, 0,11, MC, "Intel Mobile Celeron (Tualatin)");
2770 FMQ ( 0, 6, 0,11, dP, "Intel Pentium III (Tualatin)");
2771 FM ( 0, 6, 0,11, "Intel Pentium III (unknown type) (Tualatin)");
2772 // Intel docs (300303, 302209).
2773 FMSQ( 0, 6, 0,13, 6, dC, "Intel Celeron M (Dothan B1), 90nm");
2774 FMSQ( 0, 6, 0,13, 6, dP, "Intel Pentium M (Dothan B1), 90nm");
2775 FMS ( 0, 6, 0,13, 6, "Intel Pentium M (unknown type) (Dothan B1), 90nm");
2776 FMSQ( 0, 6, 0,13, 8, dC, "Intel Celeron M (Dothan C0), 90nm/65nm");
2777 FMSQ( 0, 6, 0,13, 8, MP, "Intel Processor A100/A110 (Stealey C0) / Pentium M (Crofton C0), 90nm");
2778 FMSQ( 0, 6, 0,13, 8, dP, "Intel Pentium M (Dothan C0), 90nm");
2779 FMS ( 0, 6, 0,13, 8, "Intel Pentium M (unknown type) (Dothan/Stealey/Crofton C0), 90nm/65nm");
2780 FMQ ( 0, 6, 0,13, dC, "Intel Celeron M (Dothan)");
2781 FMQ ( 0, 6, 0,13, MP, "Intel Processor A100/A110 (Stealey)");
2782 FMQ ( 0, 6, 0,13, dP, "Intel Pentium M (Dothan)");
2783 FM ( 0, 6, 0,13, "Intel Pentium M (unknown type) (Dothan/Crofton)");
2784 // Intel docs (300303, 309222, 311392, 316515).
2785 FMSQ( 0, 6, 0,14, 8, sX, "Intel Xeon Processor LV (Sossaman C0)");
2786 FMSQ( 0, 6, 0,14, 8, dC, "Intel Celeron (Yonah C0)");
2787 FMSQ( 0, 6, 0,14, 8, DG, "Intel Core Duo (Yonah C0)");
2788 FMSQ( 0, 6, 0,14, 8, dG, "Intel Core Solo (Yonah C0)");
2789 FMS ( 0, 6, 0,14, 8, "Intel Core (unknown type) (Yonah/Sossaman C0)");
2790 FMSQ( 0, 6, 0,14, 12, sX, "Intel Xeon Processor LV (Sossaman D0)");
2791 FMSQ( 0, 6, 0,14, 12, dC, "Intel Celeron M (Yonah D0)");
2792 FMSQ( 0, 6, 0,14, 12, MP, "Intel Pentium Dual-Core Mobile T2000 (Yonah D0)");
2793 FMSQ( 0, 6, 0,14, 12, DG, "Intel Core Duo (Yonah D0)");
2794 FMSQ( 0, 6, 0,14, 12, dG, "Intel Core Solo (Yonah D0)");
2795 FMS ( 0, 6, 0,14, 12, "Intel Core (unknown type) (Yonah/Sossaman D0)");
2796 FMS ( 0, 6, 0,14, 13, "Intel Pentium Dual-Core Mobile T2000 (Yonah M0)");
2797 FMQ ( 0, 6, 0,14, sX, "Intel Xeon Processor LV (Sossaman)");
2798 FMQ ( 0, 6, 0,14, dC, "Intel Celeron (Yonah)");
2799 FMQ ( 0, 6, 0,14, MP, "Intel Pentium Dual-Core Mobile (Yonah)");
2800 FMQ ( 0, 6, 0,14, DG, "Intel Core Duo (Yonah)");
2801 FMQ ( 0, 6, 0,14, dG, "Intel Core Solo (Yonah)");
2802 FM ( 0, 6, 0,14, "Intel Core (unknown type) (Yonah/Sossaman)");
2803 // Intel docs (313279, 313356, 314079, 314916, 315338, 315593, 316134,
2804 // 316515, 316982, 317667, 318081, 318925, 319735).
2805 FMSQ( 0, 6, 0,15, 2, sX, "Intel Dual-Core Xeon Processor 3000 (Conroe L2)");
2806 FMSQ( 0, 6, 0,15, 2, Mc, "Intel Core Duo Mobile (Merom L2)");
2807 FMSQ( 0, 6, 0,15, 2, dc, "Intel Core Duo (Conroe L2)");
2808 FMSQ( 0, 6, 0,15, 2, dP, "Intel Pentium Dual-Core Desktop Processor E2000 (Allendale L2)");
2809 FMS ( 0, 6, 0,15, 2, "Intel Core (unknown type) (Conroe/Merom/Allendale L2)");
2810 FMS ( 0, 6, 0,15, 4, "Intel Core 2 Duo (Conroe B0) / Xeon Processor 5100 (Woodcrest B0) (pre-production)");
2811 FMSQ( 0, 6, 0,15, 5, QW, "Intel Dual-Core Xeon Processor 5100 (Woodcrest B1) (pre-production)");
2812 FMSQ( 0, 6, 0,15, 5, XE, "Intel Core 2 Extreme Processor (Conroe B1)");
2813 FMSQ( 0, 6, 0,15, 5, dL, "Intel Core 2 Duo (Allendale B1)");
2814 FMSQ( 0, 6, 0,15, 5, dc, "Intel Core 2 Duo (Conroe B1)");
2815 FMS ( 0, 6, 0,15, 5, "Intel Core 2 (unknown type) (Conroe/Allendale B1)");
2816 FMSQ( 0, 6, 0,15, 6, Xc, "Intel Core 2 Extreme Processor (Conroe B2)");
2817 FMSQ( 0, 6, 0,15, 6, Mc, "Intel Core 2 Duo Mobile (Merom B2)");
2818 FMSQ( 0, 6, 0,15, 6, dL, "Intel Core 2 Duo (Allendale B2)");
2819 FMSQ( 0, 6, 0,15, 6, dc, "Intel Core 2 Duo (Conroe B2)");
2820 FMSQ( 0, 6, 0,15, 6, dC, "Intel Celeron M (Conroe B2)");
2821 FMSQ( 0, 6, 0,15, 6, sX, "Intel Dual-Core Xeon Processor 3000 (Conroe B2) / Dual-Core Xeon Processor 5100 (Woodcrest B2)");
2822 FMS ( 0, 6, 0,15, 6, "Intel Core 2 (unknown type) (Conroe/Allendale/Woodcrest B2)");
2823 FMSQ( 0, 6, 0,15, 7, sX, "Intel Quad-Core Xeon Processor 3200 (Kentsfield B3) / Quad-Core Xeon Processor 5300 (Clovertown B3)");
2824 FMSQ( 0, 6, 0,15, 7, Xc, "Intel Core 2 Extreme Quad-Core Processor QX6xx0 (Kentsfield B3)");
2825 FMS ( 0, 6, 0,15, 7, "Intel Core 2 (unknown type) (Kentsfield/Clovertown B3)");
2826 FMSQ( 0, 6, 0,15, 10, Mc, "Intel Core 2 Duo Mobile (Merom E1)");
2827 FMSQ( 0, 6, 0,15, 10, dC, "Intel Celeron Processor 500 (Merom E1)");
2828 FMS ( 0, 6, 0,15, 10, "Intel Core 2 (unknown type) (Merom E1)");
2829 FMSQ( 0, 6, 0,15, 11, sQ, "Intel Quad-Core Xeon Processor 5300 (Clovertown G0)");
2830 FMSQ( 0, 6, 0,15, 11, sX, "Intel Xeon Processor 3000 (Conroe G0) / Xeon Processor 3200 (Kentsfield G0) / Xeon Processor 7200/7300 (Tigerton G0)");
2831 FMSQ( 0, 6, 0,15, 11, Xc, "Intel Core 2 Extreme Quad-Core Processor QX6xx0 (Kentsfield G0)");
2832 FMSQ( 0, 6, 0,15, 11, Mc, "Intel Core 2 Duo Mobile (Merom G2)");
2833 FMSQ( 0, 6, 0,15, 11, Qc, "Intel Core 2 Quad (Conroe G0)");
2834 FMSQ( 0, 6, 0,15, 11, dc, "Intel Core 2 Duo (Conroe G0)");
2835 FMS ( 0, 6, 0,15, 11, "Intel Core 2 (unknown type) (Merom/Conroe/Kentsfield/Clovertown/Tigerton G0)");
2836 FMSQ( 0, 6, 0,15, 13, Mc, "Intel Core 2 Duo Mobile (Merom M1) / Celeron Processor 500 (Merom E1)");
2837 FMSQ( 0, 6, 0,15, 13, Qc, "Intel Core 2 Quad (Conroe M0)");
2838 FMSQ( 0, 6, 0,15, 13, dc, "Intel Core 2 Duo (Conroe M0)");
2839 FMSQ( 0, 6, 0,15, 13, dP, "Intel Pentium Dual-Core Desktop Processor E2000 (Allendale M0)");
2840 FMSQ( 0, 6, 0,15, 13, dC, "Intel Celeron Dual-Core E1000 (Allendale M0) / Celeron Dual-Core T1000 (Merom M0)");
2841 FMS ( 0, 6, 0,15, 13, "Intel Core 2 (unknown type) (Merom/Conroe/Allendale M0 / Merom E1)");
2842 FMQ ( 0, 6, 0,15, sQ, "Intel Quad-Core Xeon (Woodcrest)");
2843 FMQ ( 0, 6, 0,15, sX, "Intel Dual-Core Xeon (Conroe / Woodcrest) / Quad-Core Xeon (Kentsfield / Clovertown) / Xeon (Tigerton G0)");
2844 FMQ ( 0, 6, 0,15, Xc, "Intel Core 2 Extreme Processor (Conroe) / Core 2 Extreme Quad-Core (Kentsfield)");
2845 FMQ ( 0, 6, 0,15, Mc, "Intel Core Duo Mobile / Core 2 Duo Mobile (Merom) / Celeron (Merom)");
2846 FMQ ( 0, 6, 0,15, Qc, "Intel Core 2 Quad (Conroe)");
2847 FMQ ( 0, 6, 0,15, dc, "Intel Core Duo / Core 2 Duo (Conroe)");
2848 FMQ ( 0, 6, 0,15, dP, "Intel Pentium Dual-Core (Allendale)");
2849 FMQ ( 0, 6, 0,15, dC, "Intel Celeron M (Conroe) / Celeron (Merom) / Celeron Dual-Core (Allendale)");
2850 FM ( 0, 6, 0,15, "Intel Core 2 (unknown type) (Merom/Conroe/Allendale/Kentsfield/Allendale/Clovertown/Woodcrest/Tigerton)");
2851 // Intel docs (320257).
2852 FMS ( 0, 6, 1, 5, 0, "Intel EP80579 (Tolapai B0)");
2853 // Intel docs (314079, 316964, 317667, 318547).
2854 FMSQ( 0, 6, 1, 6, 1, MC, "Intel Celeron Processor 200/400/500 (Conroe-L/Merom-L A1)");
2855 FMSQ( 0, 6, 1, 6, 1, dC, "Intel Celeron M (Merom-L A1)");
2856 FMSQ( 0, 6, 1, 6, 1, Mc, "Intel Core 2 Duo Mobile (Merom A1)");
2857 FMS ( 0, 6, 1, 6, 1, "Intel Core 2 (unknown type) (Merom/Conroe A1)");
2858 FMQ ( 0, 6, 1, 6, MC, "Intel Celeron Processor 200/400/500 (Conroe-L/Merom-L)");
2859 FMQ ( 0, 6, 1, 6, dC, "Intel Celeron M (Merom-L)");
2860 FMQ ( 0, 6, 1, 6, Mc, "Intel Core 2 Duo Mobile (Merom)");
2861 FM ( 0, 6, 1, 6, "Intel Core 2 (unknown type) (Merom/Conroe)");
2862 // Intel docs (318585, 318586, 318727, 318733, 318915, 319006, 319007,
2863 // 319129, 320121, 320468, 320469, 322568).
2864 FMSQ( 0, 6, 1, 7, 6, sQ, "Intel Xeon Processor 3300 (Yorkfield C0) / Xeon Processor 5200 (Wolfdale C0) / Xeon Processor 5400 (Harpertown C0)");
2865 FMSQ( 0, 6, 1, 7, 6, sX, "Intel Xeon Processor 3100 (Wolfdale C0) / Xeon Processor 5200 (Wolfdale C0) / Xeon Processor 5400 (Harpertown C0)");
2866 FMSQ( 0, 6, 1, 7, 6, Xc, "Intel Core 2 Extreme QX9000 (Yorkfield C0)");
2867 FMSQ( 0, 6, 1, 7, 6, Me, "Intel Mobile Core 2 Duo (Penryn C0)");
2868 FMSQ( 0, 6, 1, 7, 6, Mc, "Intel Mobile Core 2 Duo (Penryn M0)");
2869 FMSQ( 0, 6, 1, 7, 6, de, "Intel Core 2 Duo (Wolfdale C0)");
2870 FMSQ( 0, 6, 1, 7, 6, dc, "Intel Core 2 Duo (Wolfdale M0)");
2871 FMSQ( 0, 6, 1, 7, 6, dP, "Intel Pentium Dual-Core Processor E5000 (Wolfdale M0)");
2872 FMS ( 0, 6, 1, 7, 6, "Intel Core 2 (unknown type) (Penryn/Wolfdale/Yorkfield/Harpertown C0/M0)");
2873 FMSQ( 0, 6, 1, 7, 7, sQ, "Intel Xeon Processor 3300 (Yorkfield C1)");
2874 FMSQ( 0, 6, 1, 7, 7, Xc, "Intel Core 2 Extreme QX9000 (Yorkfield C1)");
2875 FMSQ( 0, 6, 1, 7, 7, Qe, "Intel Core 2 Quad-Core Q9000 (Yorkfield C1)");
2876 FMSQ( 0, 6, 1, 7, 7, Qc, "Intel Core 2 Quad-Core Q9000 (Yorkfield M1)");
2877 FMS ( 0, 6, 1, 7, 7, "Intel Core 2 (unknown type) (Penryn/Wolfdale/Yorkfield/Harpertown C1/M1)");
2878 FMSQ( 0, 6, 1, 7, 10, Me, "Intel Mobile Core 2 (Penryn E0)");
2879 FMSQ( 0, 6, 1, 7, 10, Mc, "Intel Mobile Core 2 (Penryn R0)");
2880 FMSQ( 0, 6, 1, 7, 10, Qe, "Intel Core 2 Quad-Core Q9000 (Yorkfield E0)");
2881 FMSQ( 0, 6, 1, 7, 10, Qc, "Intel Core 2 Quad-Core Q9000 (Yorkfield R0)");
2882 FMSQ( 0, 6, 1, 7, 10, de, "Intel Core 2 Duo (Wolfdale E0)");
2883 FMSQ( 0, 6, 1, 7, 10, dc, "Intel Core 2 Duo (Wolfdale R0)");
2884 FMSQ( 0, 6, 1, 7, 10, dP, "Intel Pentium Dual-Core Processor E5000/E6000 / Pentium T4000 (Wolfdale R0)");
2885 FMSQ( 0, 6, 1, 7, 10, dC, "Intel Celeron E3000 / T3000 / 900 / SU2300 (Wolfdale R0)"); // T3000 & 900 names from MRG* 2018-03-06
2886 FMSQ( 0, 6, 1, 7, 10, MC, "Intel Celeron M ULV 700 (Penryn R0)");
2887 FMSQ( 0, 6, 1, 7, 10, se, "Intel Xeon Processor 3300 (Yorkfield E0)");
2888 FMSQ( 0, 6, 1, 7, 10, sQ, "Intel Xeon Processor 3300 (Yorkfield R0)");
2889 FMSQ( 0, 6, 1, 7, 10, sX, "Intel Xeon Processor 3100 (Wolfdale E0) / Xeon Processor 3300 (Yorkfield R0) / Xeon Processor 5200 (Wolfdale E0) / Xeon Processor 5400 (Harpertown E0)");
2890 FMS ( 0, 6, 1, 7, 10, "Intel Core 2 (unknown type) (Penryn/Wolfdale/Yorkfield/Harpertown E0/R0)");
2891 FMQ ( 0, 6, 1, 7, se, "Intel Xeon (Wolfdale / Yorkfield / Harpertown)");
2892 FMQ ( 0, 6, 1, 7, sQ, "Intel Xeon (Wolfdale / Yorkfield / Harpertown)");
2893 FMQ ( 0, 6, 1, 7, sX, "Intel Xeon (Wolfdale / Yorkfield / Harpertown)");
2894 FMQ ( 0, 6, 1, 7, Mc, "Intel Mobile Core 2 (Penryn)");
2895 FMQ ( 0, 6, 1, 7, Xc, "Intel Core 2 Extreme (Yorkfield)");
2896 FMQ ( 0, 6, 1, 7, Qc, "Intel Core 2 Quad-Core (Yorkfield)");
2897 FMQ ( 0, 6, 1, 7, dc, "Intel Core 2 Duo (Wolfdale)");
2898 FMQ ( 0, 6, 1, 7, dC, "Intel Celeron (Wolfdale)");
2899 FMQ ( 0, 6, 1, 7, MC, "Intel Celeron M ULV (Penryn)");
2900 FMQ ( 0, 6, 1, 7, dP, "Intel Pentium (Wolfdale)");
2901 FM ( 0, 6, 1, 7, "Intel Core 2 (unknown type) (Penryn/Wolfdale/Yorkfield/Harpertown)");
2902 // Intel docs (320836, 321324, 321333).
2903 FMS ( 0, 6, 1,10, 4, "Intel Core i7-900 (Bloomfield C0)");
2904 FMSQ( 0, 6, 1,10, 5, dc, "Intel Core i7-900 (Bloomfield D0)");
2905 FMSQ( 0, 6, 1,10, 5, sX, "Intel Xeon Processor 3500 (Bloomfield D0) / Xeon Processor 5500 (Gainestown D0)");
2906 FMS ( 0, 6, 1,10, 5, "Intel Core (unknown type) (Bloomfield/Gainestown D0)");
2907 FMQ ( 0, 6, 1,10, dc, "Intel Core (Bloomfield)");
2908 FMQ ( 0, 6, 1,10, sX, "Intel Xeon (Bloomfield / Gainestown)");
2909 FM ( 0, 6, 1,10, "Intel Core (unknown type) (Bloomfield / Gainestown)");
2910 // Intel docs (319536, 319974, 320047, 320529, 322861, 322862, 322849,
2911 // 324341).
2912 FMS ( 0, 6, 1,12, 1, "Intel Atom N270 (Diamondville B0)");
2913 FMS ( 0, 6, 1,12, 2, "Intel Atom 200/N200/300 (Diamondville C0) / Atom Z500 (Silverthorne C0)");
2914 FMS ( 0, 6, 1,12, 10, "Intel Atom D400/N400 (Pineview A0) / Atom D500/N500 (Pineview B0)");
2915 FM ( 0, 6, 1,12, "Intel Atom (Diamondville / Silverthorne / Pineview)");
2916 // Intel docs (320336).
2917 FMS ( 0, 6, 1,13, 1, "Intel Xeon Processor 7400 (Dunnington A1)");
2918 FM ( 0, 6, 1,13, "Intel Xeon (unknown type) (Dunnington)");
2919 // Intel docs (320767, 322166, 322373, 323105).
2920 FMSQ( 0, 6, 1,14, 4, sX, "Intel Xeon Processor EC3500/EC5500 (Jasper Forest B0)"); // EC names from MRG* 2018-03-06
2921 FMSQ( 0, 6, 1,14, 4, dC, "Intel Celeron P1053 (Jasper Forest B0)");
2922 FMS ( 0, 6, 1,14, 4, "Intel Xeon (unknown type) (Jasper Forest B0)");
2923 FMSQ( 0, 6, 1,14, 5, sX, "Intel Xeon Processor 3400 (Lynnfield B1)");
2924 FMSQ( 0, 6, 1,14, 5, Mc, "Intel Core i7-700/800/900 Mobile (Clarksfield B1)");
2925 FMSQ( 0, 6, 1,14, 5, dc, "Intel Core i*-700/800/900 (Lynnfield B1)"); // 900 from MRG* 2018-03-06
2926 FMS ( 0, 6, 1,14, 5, "Intel Core (unknown type) (Lynnfield/Clarksfield B1)");
2927 FMQ ( 0, 6, 1,14, sX, "Intel Xeon (Lynnfield) / Xeon (Jasper Forest)");
2928 FMQ ( 0, 6, 1,14, dC, "Intel Celeron (Jasper Forest)");
2929 FMQ ( 0, 6, 1,14, Mc, "Intel Core Mobile (Clarksfield)");
2930 FMQ ( 0, 6, 1,14, dc, "Intel Core (Lynnfield)");
2931 FM ( 0, 6, 1,14, "Intel Core (unknown type) (Lynnfield/Clarksfield)");
2932 FM ( 0, 6, 1,15, "Intel (unknown model) (Havendale/Auburndale)");
2933 // Intel docs (322814, 322911, 323179, 323847, 323056, 324456).
2934 FMSQ( 0, 6, 2, 5, 2, sX, "Intel Xeon Processor L3406 (Clarkdale C2)");
2935 FMSQ( 0, 6, 2, 5, 2, MC, "Intel Celeron Mobile P4500 (Arrandale C2)");
2936 FMSQ( 0, 6, 2, 5, 2, MP, "Intel Pentium P6000 Mobile (Arrandale C2)");
2937 FMSQ( 0, 6, 2, 5, 2, dP, "Intel Pentium G6900 / P4500 (Clarkdale C2)");
2938 FMSQ( 0, 6, 2, 5, 2, Mc, "Intel Core i*-300/400/500/600 Mobile (Arrandale C2)");
2939 FMSQ( 0, 6, 2, 5, 2, dc, "Intel Core i*-300/500/600 (Clarkdale C2)");
2940 FMS ( 0, 6, 2, 5, 2, "Intel Core (unknown type) (Clarkdale/Arrandale C2)");
2941 FMSQ( 0, 6, 2, 5, 5, MC, "Intel Celeron Mobile U3400 (Arrandale K0) / Celeron Mobile P4600 (Arrandale K0)");
2942 FMSQ( 0, 6, 2, 5, 5, MP, "Intel Pentium U5000 Mobile (Arrandale K0)");
2943 FMSQ( 0, 6, 2, 5, 5, dP, "Intel Pentium P4500 / U3400 / G6900 (Clarkdale K0)"); // G6900 only from MRG* 2018-03-06
2944 FMSQ( 0, 6, 2, 5, 5, dc, "Intel Core i*-300/400/500/600 (Clarkdale K0)");
2945 FMS ( 0, 6, 2, 5, 5, "Intel Core (unknown type) (Clarkdale/Arrandale K0)");
2946 FMQ ( 0, 6, 2, 5, sX, "Intel Xeon Processor L3406 (Clarkdale)");
2947 FMQ ( 0, 6, 2, 5, MC, "Intel Celeron Mobile (Arrandale)");
2948 FMQ ( 0, 6, 2, 5, MP, "Intel Pentium Mobile (Arrandale)");
2949 FMQ ( 0, 6, 2, 5, dP, "Intel Pentium (Clarkdale)");
2950 FMQ ( 0, 6, 2, 5, Mc, "Intel Core Mobile (Arrandale)");
2951 FMQ ( 0, 6, 2, 5, dc, "Intel Core (Clarkdale)");
2952 FM ( 0, 6, 2, 5, "Intel Core (unknown type) (Clarkdale/Arrandale)");
2953 // Intel docs (324209, 325307, 325309, 325630).
2954 FMS ( 0, 6, 2, 6, 1, "Intel Atom Z600 (Lincroft C0) / Atom E600 (Tunnel Creek B0/B1)");
2955 FM ( 0, 6, 2, 6, "Intel Atom Z600 (Lincroft) / Atom E600 (Tunnel Creek B0/B1)");
2956 FM ( 0, 6, 2, 7, "Intel Atom Z2000 (Medfield)"); // no spec update, only instlatx64 example (stepping 1)
2957 // Intel docs (327335) omit stepping numbers, but (324643, 324827, 324972)
2958 // provide some. An instlatx64 stepping 6 example has been spoted, but it
2959 // isn't known which stepping name that is.
2960 FMSQ( 0, 6, 2,10, 7, Xc, "Intel Mobile Core i7 Extreme (Sandy Bridge D2/J1/Q0)");
2961 FMSQ( 0, 6, 2,10, 7, Mc, "Intel Mobile Core i*-2000 (Sandy Bridge D2/J1/Q0)");
2962 FMSQ( 0, 6, 2,10, 7, dc, "Intel Core i*-2000 (Sandy Bridge D2/J1/Q0)");
2963 FMSQ( 0, 6, 2,10, 7, MC, "Intel Celeron G400/G500/700/800/B800 (Sandy Bridge J1/Q0)");
2964 FMSQ( 0, 6, 2,10, 7, sX, "Intel Xeon E3-1100 / E3-1200 v1 (Sandy Bridge D2/J1/Q0)");
2965 FMSQ( 0, 6, 2,10, 7, dP, "Intel Pentium G500/G600/G800 / Pentium 900 (Sandy Bridge Q0)");
2966 FMS ( 0, 6, 2,10, 7, "Intel Core (unknown type) (Sandy Bridge D2/J1/Q0)");
2967 FMQ ( 0, 6, 2,10, Xc, "Intel Mobile Core i7 Extreme (Sandy Bridge)");
2968 FMQ ( 0, 6, 2,10, Mc, "Intel Mobile Core i*-2000 (Sandy Bridge)");
2969 FMQ ( 0, 6, 2,10, dc, "Intel Core i*-2000 (Sandy Bridge)");
2970 FMQ ( 0, 6, 2,10, MC, "Intel Celeron G400/G500/700/800/B800 (Sandy Bridge)");
2971 FMQ ( 0, 6, 2,10, sX, "Intel Xeon E3-1100 / E3-1200 v1 (Sandy Bridge)");
2972 FMQ ( 0, 6, 2,10, dP, "Intel Pentium G500/G600/G800 / Pentium 900 (Sandy Bridge)");
2973 FM ( 0, 6, 2,10, "Intel Core (unknown type) (Sandy Bridge)");
2974 // Intel docs (323254: i7-900, 323338: Xeon 3600, 323372: Xeon 5600).
2975 // https://en.wikipedia.org/wiki/Westmere_(microarchitecture) provided
2976 // A0 & B0 stepping values.
2977 FMSQ( 0, 6, 2,12, 0, dc, "Intel Core i7-900 / Core i7-980X (Gulftown A0)");
2978 FMSQ( 0, 6, 2,12, 0, sX, "Intel Xeon Processor 3600 / 5600 (Westmere-EP A0)");
2979 FMS ( 0, 6, 2,12, 0, "Intel Core (unknown type) (Gulftown/Westmere-EP A0)");
2980 FMSQ( 0, 6, 2,12, 1, dc, "Intel Core i7-900 / Core i7-980X (Gulftown B0)");
2981 FMSQ( 0, 6, 2,12, 1, sX, "Intel Xeon Processor 3600 / 5600 (Westmere-EP B0)");
2982 FMS ( 0, 6, 2,12, 1, "Intel Core (unknown type) (Gulftown/Westmere-EP B0)");
2983 FMSQ( 0, 6, 2,12, 2, dc, "Intel Core i7-900 / Core i7-980X (Gulftown B1)");
2984 FMSQ( 0, 6, 2,12, 2, sX, "Intel Xeon Processor 3600 / 5600 (Westmere-EP B1)");
2985 FMS ( 0, 6, 2,12, 2, "Intel Core (unknown type) (Gulftown/Westmere-EP B1)");
2986 FMQ ( 0, 6, 2,12, dc, "Intel Core (unknown type) (Gulftown)");
2987 FMQ ( 0, 6, 2,12, sX, "Intel Xeon (unknown type) (Westmere-EP)");
2988 FM ( 0, 6, 2,12, "Intel (unknown type) (Gulftown/Westmere-EP)");
2989 // Intel docs (326198, 326510).
2990 FMSQ( 0, 6, 2,13, 6, sX, "Intel Xeon E5-1600/2600 (Sandy Bridge-E C1/M0)");
2991 FMSQ( 0, 6, 2,13, 6, dc, "Intel Core i7-3800/3900 (Sandy Bridge-E C1)");
2992 FMS ( 0, 6, 2,13, 6, "Intel Core (unknown type) (Sandy Bridge-E C1)");
2993 FMSQ( 0, 6, 2,13, 7, sX, "Intel Xeon E5-1600/2600/4600 (Sandy Bridge-E C2/M1)");
2994 FMSQ( 0, 6, 2,13, 7, dc, "Intel Core i7-3800/3900 (Sandy Bridge-E C2)");
2995 FMSQ( 0, 6, 2,13, 7, dP, "Intel Pentium 1405 (Sandy Bridge-E C1)"); // MRG* 2018-03-06
2996 FMS ( 0, 6, 2,13, 7, "Intel Core (unknown type) (Sandy Bridge-E C2/M1)");
2997 FMQ ( 0, 6, 2,13, sX, "Intel Xeon E5-1600/2600 (Sandy Bridge-E)");
2998 FMQ ( 0, 6, 2,13, dc, "Intel Core i7-3800/3900 (Sandy Bridge-E)");
2999 FMQ ( 0, 6, 2,13, dP, "Intel Pentium 1405 (Sandy Bridge-E)"); // MRG* 2018-03-06
3000 FM ( 0, 6, 2,13, "Intel Core (unknown type) (Sandy Bridge-E)");
3001 // Intel docs (323344) are inconsistent. Using Table 2 information.
3002 // instlatx64 samples have steppings 4 & 5, but no idea which stepping names
3003 // those are.
3004 FMS ( 0, 6, 2,14, 6, "Intel Xeon Processor 6500 / 7500 (Beckton D0)");
3005 FM ( 0, 6, 2,14, "Intel Xeon Processor 6500 / 7500 (Beckton)");
3006 // Intel docs (325122).
3007 FMS ( 0, 6, 2,15, 2, "Intel Xeon E7-8800 / Xeon E7-4800 / Xeon E7-2800 (Westmere-EX A2)");
3008 FM ( 0, 6, 2,15, "Intel Xeon (unknown type) (Westmere-EX)");
3009 // Intel docs (332067) omit stepping numbers for D1, but (328105) provide
3010 // some.
3011 FMS ( 0, 6, 3, 5, 1, "Intel Atom Z2760 (Clover Trail C0) / Z8000 (Cherry Trail C0)");
3012 FM ( 0, 6, 3, 5, "Intel Atom Z2760 (Clover Trail) / Z8000 (Cherry Trail)");
3013 // Intel docs (326140) for Cedarview
3014 // Intel docs (328198) do not provide any FMS for Centerton, but an example
3015 // from jhladky@redhat.com does.
3016 // instlatx64 has example with stepping 9, but no idea what stepping name
3017 // that is.
3018 FMS ( 0, 6, 3, 6, 1, "Intel Atom D2000/N2000 (Cedarview B1/B2/B3) / S1200 (Centerton B1)");
3019 FM ( 0, 6, 3, 6, "Intel Atom D2000/N2000 (Cedarview) / S1200 (Centerton)");
3020 // Intel docs (329475, 329671, 329901, 600827).
3021 FMS ( 0, 6, 3, 7, 1, "Intel Atom Z3000 (Bay Trail-T A0)");
3022 FMSQ( 0, 6, 3, 7, 2, dC, "Intel Celeron N2800 / N2900 (Bay Trail-M B0/B1)");
3023 FMSQ( 0, 6, 3, 7, 2, dP, "Intel Pentium N3500 / J2800 / J2900 (Bay Trail-M B0/B1)");
3024 FMS ( 0, 6, 3, 7, 2, "Intel Atom (unknown type) (Bay Trail-M B0/B1)");
3025 FMSQ( 0, 6, 3, 7, 3, dC, "Intel Celeron N1700 / N1800 / N2800 / N2900 / J1700 / J1800 / J1900 (Bay Trail-M B2/B3)");
3026 FMSQ( 0, 6, 3, 7, 3, dP, "Intel Pentium N3500 / J2800 / J2900 (Bay Trail-M B2/B3) / Atom E3800 (Bay Trail-I B3)");
3027 FMSQ( 0, 6, 3, 7, 3, da, "Intel Atom E3800 / Z3700 (Bay Trail-I B3)"); // Z3700 only from MRG* 2019-08-31
3028 FMS ( 0, 6, 3, 7, 3, "Intel Atom (unknown type) (Bay Trail B2/B3)");
3029 FMSQ( 0, 6, 3, 7, 4, dC, "Intel Celeron N2800 / N2900 (Bay Trail-M C0)");
3030 FMSQ( 0, 6, 3, 7, 4, dP, "Intel Pentium N3500 / J2800 / J2900 (Bay Trail-M C0)");
3031 FMS ( 0, 6, 3, 7, 4, "Intel Atom (unknown type) (Bay Trail-M C0 / Bay Trail-T B2/B3)");
3032 FMSQ( 0, 6, 3, 7, 8, da, "Intel Atom Z3700 (Bay Trail)"); // only MRG* 2019-08-31 (unknown stepping name)
3033 FMSQ( 0, 6, 3, 7, 8, dC, "Intel Celeron N2800 / N2900 (Bay Trail)"); // only MRG* 2019-08-31 (unknown stepping name)
3034 FMSQ( 0, 6, 3, 7, 8, dP, "Intel Pentium N3500 (Bay Trail)"); // only MRG* 2019-08-31 (unknown stepping name)
3035 FMS ( 0, 6, 3, 7, 8, "Intel Atom (unknown type) (Bay Trail)"); // only MRG* 2019-08-31 (unknown stepping name)
3036 FMSQ( 0, 6, 3, 7, 9, da, "Intel Atom E3800 (Bay Trail-I D0)");
3037 FMSQ( 0, 6, 3, 7, 9, dC, "Intel Celeron N2800 / N2900 (Bay Trail-M/D D0/D1)"); // only MRG* 2018-03-06
3038 FMSQ( 0, 6, 3, 7, 9, dP, "Intel Pentium J1800 / J1900 (Bay Trail-M/D D0/D1)"); // only MRG* 2018-03-06
3039 FMS ( 0, 6, 3, 7, 9, "Intel Atom (unknown type) (Bay Trail D0)");
3040 FM ( 0, 6, 3, 7, "Intel Atom (unknown type) (Bay Trail-M / Bay Trail-T / Bay Trail-I)");
3041 // Intel docs (326766, 326770, 326774, 329376).
3042 // How to differentiate Gladden from Ivy Bridge here?
3043 FMSQ( 0, 6, 3,10, 9, Mc, "Intel Mobile Core i*-3000 (Ivy Bridge E1/L1) / Pentium 900/1000/2000/2100 (P0)");
3044 FMSQ( 0, 6, 3,10, 9, dc, "Intel Core i*-3000 (Ivy Bridge E1/N0/L1)");
3045 FMSQ( 0, 6, 3,10, 9, sX, "Intel Xeon E3-1100 v2 / E3-1200 v2 (Ivy Bridge E1/N0/L1)");
3046 FMSQ( 0, 6, 3,10, 9, dC, "Intel Celeron 1000 / G1600 (Ivy Bridge P0)"); // only MRG 2019-08-31
3047 FMSQ( 0, 6, 3,10, 9, dP, "Intel Pentium G1600/G2000/G2100 / Pentium B900C (Ivy Bridge P0)");
3048 FMS ( 0, 6, 3,10, 9, "Intel Core (unknown type) (Ivy Bridge E1/N0/L1/P0)");
3049 FMQ ( 0, 6, 3,10, Mc, "Intel Mobile Core i*-3000 (Ivy Bridge) / Pentium 900/1000/2000/2100");
3050 FMQ ( 0, 6, 3,10, dc, "Intel Core i*-3000 (Ivy Bridge)");
3051 FMQ ( 0, 6, 3,10, sX, "Intel Xeon E3-1100 v2 / E3-1200 v2 (Ivy Bridge)");
3052 FMQ ( 0, 6, 3,10, dC, "Intel Celeron 1000 / G1600 (Ivy Bridge)"); // only MRG 2019-08-31
3053 FMQ ( 0, 6, 3,10, dP, "Intel Pentium G1600/G2000/G2100 / Pentium B900C (Ivy Bridge)");
3054 FM ( 0, 6, 3,10, "Intel Core (unknown type) (Ivy Bridge)");
3055 // Intel docs (328899, 328903, 328908) omit the stepping numbers for (0,6),(3,12) C0 & D0.
3056 // MRG* 2018-03-06 mentions (0,6),(3,12),3, but doesn't specify which stepping name it is.
3057 // Coreboot* identifies the steppings.
3058 FMSQ( 0, 6, 3,12, 1, sX, "Intel Xeon E3-1200 v3 (Haswell A0)");
3059 FMSQ( 0, 6, 3,12, 1, Mc, "Intel Mobile Core i*-4000U (Mobile M) (Haswell A0)");
3060 FMSQ( 0, 6, 3,12, 1, dc, "Intel Core i*-4000 / Mobile Core i*-4000 (Haswell A0)");
3061 FMSQ( 0, 6, 3,12, 1, MC, "Intel Mobile Celeron 2900U (Mobile M) (Haswell A0)");
3062 FMSQ( 0, 6, 3,12, 1, dC, "Intel Celeron G1800 / G2000 (Haswell A0)"); // G2000 only from MRG* 2019-08-31
3063 FMSQ( 0, 6, 3,12, 1, MP, "Intel Mobile Pentium 3500U / 3600U / 3500Y (Mobile M) (Haswell A0)");
3064 FMSQ( 0, 6, 3,12, 1, dP, "Intel Pentium G3000 (Haswell A0)");
3065 FMS ( 0, 6, 3,12, 1, "Intel Core (unknown type) (Haswell A0)");
3066 FMSQ( 0, 6, 3,12, 2, sX, "Intel Xeon E3-1200 v3 (Haswell B0)");
3067 FMSQ( 0, 6, 3,12, 2, Mc, "Intel Mobile Core i*-4000U (Mobile M) (Haswell B0)");
3068 FMSQ( 0, 6, 3,12, 2, dc, "Intel Core i*-4000 / Mobile Core i*-4000 (Haswell B0)");
3069 FMSQ( 0, 6, 3,12, 2, MC, "Intel Mobile Celeron 2900U (Mobile M) (Haswell B0)");
3070 FMSQ( 0, 6, 3,12, 2, dC, "Intel Celeron G1800 / G2000 (Haswell B0)"); // G2000 only from MRG* 2019-08-31
3071 FMSQ( 0, 6, 3,12, 2, MP, "Intel Mobile Pentium 3500U / 3600U / 3500Y (Mobile M) (Haswell B0)");
3072 FMSQ( 0, 6, 3,12, 2, dP, "Intel Pentium G3000 (Haswell B0)");
3073 FMS ( 0, 6, 3,12, 2, "Intel Core (unknown type) (Haswell B0)");
3074 FMSQ( 0, 6, 3,12, 3, sX, "Intel Xeon E3-1200 v3 (Haswell C0)");
3075 FMSQ( 0, 6, 3,12, 3, Mc, "Intel Mobile Core i*-4000U (Mobile M) (Haswell C0)");
3076 FMSQ( 0, 6, 3,12, 3, dc, "Intel Core i*-4000 / Mobile Core i*-4000 (Haswell C0)");
3077 FMSQ( 0, 6, 3,12, 3, MC, "Intel Mobile Celeron 2900U (Mobile M) (Haswell C0)");
3078 FMSQ( 0, 6, 3,12, 3, dC, "Intel Celeron G1800 / G2000 (Haswell C0)"); // G2000 only from MRG* 2019-08-31
3079 FMSQ( 0, 6, 3,12, 3, MP, "Intel Mobile Pentium 3500U / 3600U / 3500Y (Mobile M) (Haswell C0)");
3080 FMSQ( 0, 6, 3,12, 3, dP, "Intel Pentium G3000 (Haswell C0)");
3081 FMS ( 0, 6, 3,12, 3, "Intel Core (unknown type) (Haswell C0)");
3082 FMQ ( 0, 6, 3,12, sX, "Intel Xeon E3-1200 v3 (Haswell)");
3083 FMQ ( 0, 6, 3,12, Mc, "Intel Mobile Core i*-4000U (Mobile M) (Haswell)");
3084 FMQ ( 0, 6, 3,12, dc, "Intel Core i*-4000 / Mobile Core i*-4000 (Haswell)");
3085 FMQ ( 0, 6, 3,12, MC, "Intel Mobile Celeron 2900U (Mobile M) (Haswell)");
3086 FMQ ( 0, 6, 3,12, dC, "Intel Celeron G1800 / G2000 (Haswell)"); // G2000 only from MRG* 2019-08-31
3087 FMQ ( 0, 6, 3,12, MP, "Intel Mobile Pentium 3500U / 3600U / 3500Y (Mobile M) (Haswell)");
3088 FMQ ( 0, 6, 3,12, dP, "Intel Pentium G3000 (Haswell)");
3089 FM ( 0, 6, 3,12, "Intel Core (unknown type) (Haswell)");
3090 // Intel docs (330836) omit the stepping numbers for (0,6),(3,13) E0 & F0.
3091 // MRG* 2019-08-31 mentions stepping 4, but doesn't specify which stepping name it is.
3092 // Coreboot* identifies the steppings.
3093 FMSQ( 0, 6, 3,13, 2, dc, "Intel Core i*-5000 (Broadwell-U C0) / Core M (Broadwell-Y C0)");
3094 FMSQ( 0, 6, 3,13, 2, MC, "Intel Mobile Celeron 3000 (Broadwell-U C0)");
3095 FMSQ( 0, 6, 3,13, 2, dC, "Intel Celeron 3000 (Broadwell-U C0)");
3096 FMSQ( 0, 6, 3,13, 2, dP, "Intel Pentium 3700U / 3800U / 3200U (Broadwell-U C0)"); // only MRG* 2018-03-06, 2019-08-31
3097 FMS ( 0, 6, 3,13, 2, "Intel Core (unknown type) (Broadwell-U/Y C0)");
3098 FMSQ( 0, 6, 3,13, 3, dc, "Intel Core i*-5000 (Broadwell-U D0) / Core M (Broadwell-Y D0)");
3099 FMSQ( 0, 6, 3,13, 3, MC, "Intel Mobile Celeron 3000 (Broadwell-U D0)");
3100 FMSQ( 0, 6, 3,13, 3, dC, "Intel Celeron 3000 (Broadwell-U D0)");
3101 FMSQ( 0, 6, 3,13, 3, dP, "Intel Pentium 3700U / 3800U / 3200U (Broadwell-U D0)"); // only MRG* 2018-03-06, 2019-08-31
3102 FMS ( 0, 6, 3,13, 3, "Intel Core (unknown type) (Broadwell-U/Y D0)");
3103 FMSQ( 0, 6, 3,13, 4, dc, "Intel Core i*-5000 (Broadwell-U E0) / Core M (Broadwell-Y E0)");
3104 FMSQ( 0, 6, 3,13, 4, MC, "Intel Mobile Celeron 3000 (Broadwell-U E0)");
3105 FMSQ( 0, 6, 3,13, 4, dC, "Intel Celeron 3000 (Broadwell-U E0)");
3106 FMSQ( 0, 6, 3,13, 4, dP, "Intel Pentium 3700U / 3800U / 3200U (Broadwell-U E0)"); // only MRG* 2018-03-06, 2019-08-31
3107 FMS ( 0, 6, 3,13, 4, "Intel Core (unknown type) (Broadwell-U/Y E0)");
3108 FMQ ( 0, 6, 3,13, dc, "Intel Core i*-5000 (Broadwell-U) / Core M (Broadwell-Y)");
3109 FMQ ( 0, 6, 3,13, MC, "Intel Mobile Celeron 3000 (Broadwell-U)");
3110 FMQ ( 0, 6, 3,13, dC, "Intel Celeron 3000 (Broadwell-U)");
3111 FMQ ( 0, 6, 3,13, dP, "Intel Pentium 3700U / 3800U / 3200U (Broadwell-U)"); // only MRG* 2018-03-06, 2019-08-31
3112 FM ( 0, 6, 3,13, "Intel Core (unknown type) (Broadwell-U/Y)");
3113 // Intel docs (329189, 329368, 329597).
3114 FMSQ( 0, 6, 3,14, 4, sX, "Intel Xeon E5-1600/E5-2600 v2 (Ivy Bridge-EP C1/M1/S1)");
3115 FMSQ( 0, 6, 3,14, 4, dc, "Intel Core i*-4000 (Ivy Bridge-E S1)");
3116 FMS ( 0, 6, 3,14, 4, "Intel Core (unknown type) (Ivy Bridge-EP C1/M1/S1)");
3117 FMSQ( 0, 6, 3,14, 7, sX, "Intel Xeon E5-4600 / E7-2800 / E7-4800 / E7-8800 v2 (Ivy Bridge-EX D1)"); // E5-4600 names from MRG* 2018-03-06, 2019-08-31
3118 FMS ( 0, 6, 3,14, 7, "Intel Xeon (unknown type) (Ivy Bridge-EX D1)");
3119 FMQ ( 0, 6, 3,14, sX, "Intel Xeon E5-1600 / E5-2600 v2 (Ivy Bridge-EP) / Xeon E5-4600 / E7-2800 / E7-4800 / E7-8800 (Ivy Bridge-EX)");
3120 FMQ ( 0, 6, 3,14, dc, "Intel Core i9-4000 (Ivy Bridge-E)");
3121 FM ( 0, 6, 3,14, "Intel Core (unknown type) (Ivy Bridge-E / Ivy Bridge-EP / Ivy Bridge-EX)");
3122 // Intel docs (330785, 330841, 332317).
3123 FMSQ( 0, 6, 3,15, 2, dc, "Intel Core i7-5000 Extreme Edition (Haswell-E R2)");
3124 FMSQ( 0, 6, 3,15, 2, sX, "Intel Xeon E5-x600 v3 (Haswell-EP C1/M1/R2)");
3125 FMS ( 0, 6, 3,15, 2, "Intel (unknown type) (Haswell C1/M1/R2)");
3126 FMS ( 0, 6, 3,15, 4, "Intel Xeon E7-4800 / E7-8800 v3 (Haswell-EP E0)");
3127 FM ( 0, 6, 3,15, "Intel Core (unknown type) (Haswell R2 / Haswell-EP)");
3128 // Intel docs (328903) omit the stepping numbers for (0,6),(4,5) C0 & D0.
3129 // MRG* 2019-08-31 mentions stepping 1, but doesn't specify which stepping name it is.
3130 // Coreboot* identifies the 0 stepping as B0, but not what the 1 stepping is.
3131 FMSQ( 0, 6, 4, 5, 0, dc, "Intel Core i*-4000U (Haswell-ULT B0)"); // no docs, but example from Brice Goglin
3132 FMSQ( 0, 6, 4, 5, 0, Mc, "Intel Mobile Core i*-4000Y (Mobile U/Y) (Haswell-ULT B0)");
3133 FMSQ( 0, 6, 4, 5, 0, MP, "Intel Mobile Pentium 3500U / 3600U / 3500Y (Mobile U/Y) (Haswell-ULT B0)");
3134 FMSQ( 0, 6, 4, 5, 0, MC, "Intel Mobile Celeron 2900U (Mobile U/Y) (Haswell-ULT B0)");
3135 FMS ( 0, 6, 4, 5, 0, "Intel Core (unknown type) (Haswell-ULT B0)");
3136 FMQ ( 0, 6, 4, 5, dc, "Intel Core i*-4000U (Haswell-ULT)"); // no docs, but example from Brice Goglin
3137 FMQ ( 0, 6, 4, 5, Mc, "Intel Mobile Core i*-4000Y (Mobile U/Y) (Haswell-ULT)");
3138 FMQ ( 0, 6, 4, 5, MP, "Intel Mobile Pentium 3500U / 3600U / 3500Y (Mobile U/Y) (Haswell-ULT)");
3139 FMQ ( 0, 6, 4, 5, MC, "Intel Mobile Celeron 2900U (Mobile U/Y) (Haswell-ULT)");
3140 FM ( 0, 6, 4, 5, "Intel Core (unknown type) (Haswell-ULT)");
3141 // Intel docs (328899,328903) omit the stepping numbers for (0,6),(4,6) C0 & D0.
3142 // MRG* mentions (0,6),(4,6),1, but doesn't specify which stepping name it is.
3143 FMQ ( 0, 6, 4, 6, Mc, "Intel Mobile Core i*-4000Y (Mobile H) (Crystal Well)");
3144 FMQ ( 0, 6, 4, 6, dc, "Intel Core i*-4000 / Mobile Core i*-4000 (Desktop R) (Crystal Well)");
3145 FMQ ( 0, 6, 4, 6, MP, "Intel Mobile Pentium 3500U / 3600U / 3500Y (Mobile H) (Crystal Well)");
3146 FMQ ( 0, 6, 4, 6, dC, "Intel Celeron G1800 (Desktop R) (Crystal Well)");
3147 FMQ ( 0, 6, 4, 6, MC, "Intel Mobile Celeron 2900U (Mobile H) (Crystal Well)");
3148 FMQ ( 0, 6, 4, 6, dP, "Intel Pentium G3000 (Desktop R) (Crystal Well)");
3149 FM ( 0, 6, 4, 6, "Intel Core (unknown type) (Crystal Well)");
3150 // So far, all these (0,6),(4,7) processors are stepping G0, but the
3151 // Intel docs (332381, 332382) omit the stepping number for G0.
3152 // MRG* 2018-03-06 describes Broadwell H 43e.
3153 FMSQ( 0, 6, 4, 7, 1, dc, "Intel Core i*-5000 (Broadwell G0)");
3154 FMSQ( 0, 6, 4, 7, 1, Mc, "Intel Mobile Core i7-5000 (Broadwell G0)");
3155 FMSQ( 0, 6, 4, 7, 1, sX, "Intel Xeon E3-1200 v4 (Broadwell G0)");
3156 FMS ( 0, 6, 4, 7, 1, "Intel (unknown type) (Broadwell-H G0)");
3157 FMQ ( 0, 6, 4, 7, dc, "Intel Core i7-5000 (Broadwell)");
3158 FMQ ( 0, 6, 4, 7, Mc, "Intel Mobile Core i7-5000 (Broadwell)");
3159 FMQ ( 0, 6, 4, 7, sX, "Intel Xeon E3-1200 v4 (Broadwell)");
3160 FM ( 0, 6, 4, 7, "Intel Core (unknown type) (Broadwell)");
3161 // no spec update; only MSR_CPUID_table* so far
3162 // MRG* 2018-03-06 mentions steppings 8 and 9, but without names for either.
3163 FM ( 0, 6, 4,10, "Intel Atom Z3400 (Merrifield)");
3164 // Intel docs (332095).
3165 FMSQ( 0, 6, 4,12, 3, dC, "Intel Celeron N3000 / J3000 (Braswell C0)");
3166 FMSQ( 0, 6, 4,12, 3, dP, "Intel Pentium N3000 / J3000 (Braswell C0)");
3167 FMSQ( 0, 6, 4,12, 3, da, "Intel Atom x5-E8000 / x*-Z8000 (Cherry Trail C0)"); // no spec update; only MRG* 2018-03-06, 2019-08-31
3168 FMS ( 0, 6, 4,12, 3, "Intel Atom (unknown type) (Braswell/Cherry Trail C0)");
3169 FMSQ( 0, 6, 4,12, 4, dC, "Intel Celeron N3000 / J3000 (Braswell D1)");
3170 FMSQ( 0, 6, 4,12, 4, dP, "Intel Pentium N3000 / J3000 (Braswell D1)");
3171 FMSQ( 0, 6, 4,12, 4, da, "Intel Atom x5-E8000 / x*-Z8000 (Cherry Trail D1)"); // no spec update; only MRG* 2018-03-06, 2019-08-31
3172 FMS ( 0, 6, 4,12, 4, "Intel Atom (unknown type) (Braswell/Cherry Trail D1)");
3173 FMQ ( 0, 6, 4,12, dC, "Intel Celeron N3000 / J3000 (Braswell)");
3174 FMQ ( 0, 6, 4,12, dP, "Intel Pentium N3000 / J3000 (Braswell)");
3175 FMQ ( 0, 6, 4,12, da, "Intel Atom x5-E8000 / x*-Z8000 (Cherry Trail)"); // no spec update; only MRG* 2018-03-06, 2019-08-31
3176 FM ( 0, 6, 4,12, "Intel Atom (unknown type) (Braswell/Cherry Trail)");
3177 // Intel docs (329460, 330061).
3178 FMS ( 0, 6, 4,13, 0, "Intel Atom C2000 (Avoton A0/A1)");
3179 FMS ( 0, 6, 4,13, 8, "Intel Atom C2000 (Avoton/Rangeley B0/C0)");
3180 FM ( 0, 6, 4,13, "Intel Atom C2000 (Avoton)");
3181 // Intel docs (332689) omit the stepping numbers for (0,6),(4,14) D1 & K1.
3182 // MRG* 2018-03-06 mentions (0,6),(4,14),3, but doesn't specify which
3183 // stepping name it is.
3184 // Coreboot* identifies the 2 (C0) & 3 (D0) steppings, neither of which is
3185 // mentioned in (332689).
3186 // Coreboot* identifies stepping 8 as (Kaby Lake G0). Perhaps they were just
3187 // early engineering samples of Kaby Lake.
3188 FMSQ( 0, 6, 4,14, 2, dc, "Intel Core i*-6000U / m*-6Y00 (Skylake C0)");
3189 FMSQ( 0, 6, 4,14, 2, dP, "Intel Pentium 4405U / Pentium 4405Y (Skylake C0)");
3190 FMSQ( 0, 6, 4,14, 2, dC, "Intel Celeron 3800U / 39000U (Skylake C0)");
3191 FMSQ( 0, 6, 4,14, 2, sX, "Intel Xeon E3-1500m (Skylake C0)"); // no spec update; only MSR_CPUID_table* so far
3192 FMS ( 0, 6, 4,14, 2, "Intel Core (unknown type) (Skylake C0)");
3193 FMSQ( 0, 6, 4,14, 3, dc, "Intel Core i*-6000U / m*-6Y00 (Skylake D0)");
3194 FMSQ( 0, 6, 4,14, 3, dP, "Intel Pentium 4405U / Pentium 4405Y (Skylake D0)");
3195 FMSQ( 0, 6, 4,14, 3, dC, "Intel Celeron 3800U / 39000U (Skylake D0)");
3196 FMSQ( 0, 6, 4,14, 3, sX, "Intel Xeon E3-1500m (Skylake D0)"); // no spec update; only MSR_CPUID_table* so far
3197 FMS ( 0, 6, 4,14, 3, "Intel Core (unknown type) (Skylake D0)");
3198 FMS ( 0, 6, 4,14, 8, "Intel Core (unknown type) (Kaby Lake G0)"); // Coreboot*
3199 FMQ ( 0, 6, 4,14, dc, "Intel Core i*-6000U / m*-6Y00 (Skylake)");
3200 FMQ ( 0, 6, 4,14, dP, "Intel Pentium 4405U / Pentium 4405Y (Skylake)");
3201 FMQ ( 0, 6, 4,14, dC, "Intel Celeron 3800U / 39000U (Skylake)");
3202 FMQ ( 0, 6, 4,14, sX, "Intel Xeon E3-1500m (Skylake)"); // no spec update; only MSR_CPUID_table* so far
3203 FM ( 0, 6, 4,14, "Intel Core (unknown type) (Skylake)");
3204 // Intel docs (333811, 334165) omit the stepping numbers for (0,6),(4,15)
3205 // B0, M0 & R0, but (334208) provide some.
3206 FMSQ( 0, 6, 4,15, 1, dc, "Intel Core i7-6800K / i7-6900K / i7-6900X (Broadwell-E R0)");
3207 FMQ ( 0, 6, 4,15, dc, "Intel Core i7-6800K / i7-6900K / i7-6900X (Broadwell-E)");
3208 FMSQ( 0, 6, 4,15, 1, sX, "Intel Xeon E5-1600 / E5-2600 / E5-4600 v4 (Broadwell-E) / E7-4800 / E7-8800 v4 (Broadwell-EX B0)");
3209 FMQ ( 0, 6, 4,15, sX, "Intel Xeon E5-1600 / E5-2600 / E5-4600 v4 (Broadwell-E) / E7-4800 / E7-8800 v4 (Broadwell-EX)");
3210 FM ( 0, 6, 4,15, "Intel Core (unknown type) (Broadwell-E / Broadwell-EX)");
3211 // Intel docs (335901) omit almost all details for the Core versions of
3212 // (0,6),(5,5). But Intel docs (336065: Xeon Scalable steppings 2 & 4,
3213 // 338848: Xeon Scalable (2nd gen) stepping 7, and 338854: Xeon D-2000
3214 // stepping 2) provides some.
3215 // MRG* 2019-11-13 mentions stepping 3, but doesn't mention stepping name.
3216 // geekbench.com has an "Intel Xeon Gold 6230" example of a stepping 5, but
3217 // no stepping name.
3218 FMSQ( 0, 6, 5, 5, 2, sS, "Intel Scalable Bronze/Silver/Gold/Platinum (Skylake B0/L0)");
3219 FMSQ( 0, 6, 5, 5, 2, sX, "Intel Xeon W 2000 / D-2100 (Skylake B0/L0)");
3220 FMSQ( 0, 6, 5, 5, 4, sS, "Intel Scalable Bronze/Silver/Gold/Platinum (Skylake H0/M0/U0)");
3221 FMSQ( 0, 6, 5, 5, 4, sX, "Intel Xeon W 2000 / D-2100 (Skylake H0/M0/U0)"); // D-2100 from MRG* 2018-03-06
3222 FMSQ( 0, 6, 5, 5, 4, dc, "Intel Core i9-7000X (Skylake-X H0/M0/U0)"); // only from MRG* 2018-03-06
3223 FMSQ( 0, 6, 5, 5, 4, iM, "Montage Jintide Gen1"); // undocumented; only instlatx64 example
3224 FMSQ( 0, 6, 5, 5, 6, sS, "Intel Scalable (2nd Gen) Bronze/Silver/Gold/Platinum (Cascade Lake)"); // no docs, but example from Greg Stewart
3225 FMSQ( 0, 6, 5, 5, 6, sX, "Intel Xeon W 2000 (Cascade Lake)"); // no docs, but example from Greg Stewart
3226 FMSQ( 0, 6, 5, 5, 7, dc, "Intel Core i*-10000X (Cascade Lake-X B1/L1/R1)"); // no docs, but instlatx64 example
3227 FMSQ( 0, 6, 5, 5, 7, sS, "Intel Scalable (2nd Gen) Bronze/Silver/Gold/Platinum (Cascade Lake B1/L1/R1)");
3228 FMSQ( 0, 6, 5, 5, 7, sX, "Intel Xeon W 2000 (Cascade Lake-W B1/L1/R1)");
3229 FMS ( 0, 6, 5, 5, 10, "Intel (unknown type) (Cooper Lake)");
3230 FMQ ( 0, 6, 5, 5, sS, "Intel Scalable Bronze/Silver/Gold/Platinum (Skylake / Cascade Lake)");
3231 FMQ ( 0, 6, 5, 5, sX, "Intel Xeon W 2000 / D-2100 (Skylake / Cascade Lake)");
3232 FMQ ( 0, 6, 5, 5, dc, "Intel Core i*-6000X / i*-7000X (Skylake-X) / i*-10000X (Cascade Lake-X)");
3233 FM ( 0, 6, 5, 5, "Intel Core (unknown type) (Skylake / Skylake-X / Cascade Lake / Cascade Lake-X)");
3234 // Intel docs (332054).
3235 FMS ( 0, 6, 5, 6, 1, "Intel Xeon D-1500 (Broadwell-DE U0)");
3236 FMS ( 0, 6, 5, 6, 2, "Intel Xeon D-1500 (Broadwell-DE V1)");
3237 FMS ( 0, 6, 5, 6, 3, "Intel Xeon D-1500 (Broadwell-DE V2/V3)"); // V3 from MRG* 2018-03-06
3238 FMS ( 0, 6, 5, 6, 4, "Intel Xeon D-1500 (Broadwell-DE Y0)");
3239 FMS ( 0, 6, 5, 6, 5, "Intel Xeon D-1500N (Broadwell-DE A1)");
3240 FM ( 0, 6, 5, 6, "Intel Xeon (unknown type) (Broadwell-DE)");
3241 // Intel docs (334646) omit the stepping number for B0. But as of Jan 2020,
3242 // it is the only stepping, and all examples seen have stepping number 1.
3243 FMS ( 0, 6, 5, 7, 1, "Intel Xeon Phi x200 (Knights Landing B0)");
3244 FM ( 0, 6, 5, 7, "Intel Xeon Phi x200 (Knights Landing)");
3245 FM ( 0, 6, 5,10, "Intel Atom Z3500 (Moorefield)"); // no spec update; only MSR_CPUID_table* & instlatx64 example so far
3246 // Intel docs (334820) & MRG* 2018-03-06
3247 // Coreboot* provides stepping 8 (A0).
3248 FMS ( 0, 6, 5,12, 2, "Intel Atom T5000 (Apollo Lake)"); // no spec update; only MRG* 2018-03-06
3249 FMS ( 0, 6, 5,12, 8, "Intel Atom (unknown type) (Apollo Lake A0)");
3250 FMSQ( 0, 6, 5,12, 9, dP, "Intel Pentium N4000 / J4000 (Apollo Lake B0/B1/D0)");
3251 FMSQ( 0, 6, 5,12, 9, dC, "Intel Celeron N3000 / J3000 (Apollo Lake B0/B1/D0)");
3252 FMSQ( 0, 6, 5,12, 9, da, "Intel Atom x*-E3900 / x*-A3900 (Apollo Lake B0/B1/D0)"); // A3900 only from MRG* 2019-08-31
3253 FMS ( 0, 6, 5,12, 9, "Intel Atom (unknown type) (Apollo Lake B0/B1/D0)");
3254 FMSQ( 0, 6, 5,12, 10, da, "Intel Atom x*-E3900 (Apollo Lake E0)");
3255 FMS ( 0, 6, 5,12, 10, "Intel Atom (unknown type) (Apollo Lake E0)");
3256 FM ( 0, 6, 5,12, "Intel Atom (unknown type) (Apollo Lake)"); // no spec update for Atom; only MSR_CPUID_table* so far
3257 // No spec update; only MSR_CPUID_table* so far (and instlatx64 example)
3258 // MRG* 2018-03-06 mentions (0,6),(5,13),1 stepping, but doesn't mention stepping name.
3259 FM ( 0, 6, 5,13, "Intel Atom x3-C3000 (SoFIA)");
3260 // Intel docs (332689,333133) omit the stepping numbers for (0,6),(5,14)
3261 // R0 & S0.
3262 // MRG* 2018-03-06 mentions (0,6),(5,14),3, but doesn't specify which
3263 // stepping name it is.
3264 // Coreboot* identifies the 1 (Q0) & 3 (R0) steppings, but not the S0
3265 // stepping.
3266 // Coreboot* identifies stepping 8 as (Kaby Lake-H A0). Perhaps they were just
3267 // early engineering samples of Kaby Lake.
3268 FMSQ( 0, 6, 5,14, 1, dc, "Intel Core i*-6000 (Skylake-H Q0)");
3269 FMSQ( 0, 6, 5,14, 1, dP, "Intel Pentium G4000 (Skylake-H Q0)");
3270 FMSQ( 0, 6, 5,14, 1, dC, "Intel Celeron G3900 (Skylake-H Q0)");
3271 FMSQ( 0, 6, 5,14, 1, sX, "Intel Xeon E3-1200 / E3-1500 v5 (Skylake-H Q0)"); // E3-1500 only from MRG 2019-08-31
3272 FMS ( 0, 6, 5,14, 1, "Intel Core (unknown type) (Skylake-H Q0)");
3273 FMSQ( 0, 6, 5,14, 3, dc, "Intel Core i*-6000 (Skylake-H R0)");
3274 FMSQ( 0, 6, 5,14, 3, dP, "Intel Pentium G4000 (Skylake-H R0)");
3275 FMSQ( 0, 6, 5,14, 3, dC, "Intel Celeron G3900 (Skylake-H R0)");
3276 FMSQ( 0, 6, 5,14, 3, sX, "Intel Xeon E3-1200 / E3-1500 v5 (Skylake-H R0)"); // E3-1500 only from MRG 2019-08-31
3277 FMS ( 0, 6, 5,14, 3, "Intel Core (unknown type) (Skylake-H R0)");
3278 FMS ( 0, 6, 5,14, 8, "Intel Core (unknown type) (Kaby Lake-H A0)"); // Coreboot*
3279 FMQ ( 0, 6, 5,14, dc, "Intel Core i*-6000 (Skylake-H)");
3280 FMQ ( 0, 6, 5,14, dP, "Intel Pentium G4000 (Skylake-H)");
3281 FMQ ( 0, 6, 5,14, dC, "Intel Celeron G3900 (Skylake-H)");
3282 FMQ ( 0, 6, 5,14, sX, "Intel Xeon E3-1200 / E3-1500 v5 (Skylake-H)"); // E3-1500 only from MRG 2019-08-31
3283 FM ( 0, 6, 5,14, "Intel Core (unknown type) (Skylake-H)");
3284 // Intel docs (336345).
3285 FMS ( 0, 6, 5,15, 0, "Intel Atom C3000 (Denverton A0/A1)");
3286 FMS ( 0, 6, 5,15, 1, "Intel Atom C3000 (Denverton B0/B1)");
3287 FM ( 0, 6, 5,15, "Intel Atom C3000 (Denverton)");
3288 FM ( 0, 6, 6, 5, "Intel XMM 7272 (SoFIA)"); // no spec update; only MRG* 2018-03-06, 2019-08-31
3289 // no spec update; only MSR_CPUID_table* & instlatx64 example so far
3290 // Coreboot* provides the steppings.
3291 FMS ( 0, 6, 6, 6, 0, "Intel Core (Cannon Lake A0)");
3292 FMS ( 0, 6, 6, 6, 1, "Intel Core (Cannon Lake B0)");
3293 FMS ( 0, 6, 6, 6, 2, "Intel Core (Cannon Lake C0)");
3294 FMS ( 0, 6, 6, 6, 3, "Intel Core (Cannon Lake D0)");
3295 FM ( 0, 6, 6, 6, "Intel Core (Cannon Lake)");
3296 FMSQ( 0, 6, 6,10, 6, sS, "Intel Scalable (3rd Gen) Bronze/Silver/Gold/Platinum (Ice Lake D2/M1)");
3297 FMQ ( 0, 6, 6,10, sS, "Intel Scalable (3rd Gen) Bronze/Silver/Gold/Platinum (Ice Lake)");
3298 FM ( 0, 6, 6,10, "Intel (unknown type) (Ice Lake)");
3299 FM ( 0, 6, 6,12, "Intel Core (Ice Lake)"); // no spec update; only MSR_CPUID_table* so far
3300 // No spec update; only MRG* 2018-03-06, 2019-08-31. It is some sort of Atom,
3301 // but no idea which uarch or core.
3302 FM ( 0, 6, 6,14, "Intel Puma 7");
3303 // No spec update; only instlatx64 example.
3304 FM ( 0, 6, 7, 5, "Intel Spreadtrum SC9853I-IA");
3305 // Intel docs (336562).
3306 // MRG* 2019-11-13 mentions stepping 8, but doesn't mention stepping name.
3307 // Coreboot* provides steppings 0 (A0) & 8 (R0).
3308 FMSQ( 0, 6, 7,10, 0, dP, "Intel Pentium Silver N5000 / J5000 (Gemini Lake A0)");
3309 FMSQ( 0, 6, 7,10, 0, dC, "Intel Celeron N4000 / J4000 (Gemini Lake A0)");
3310 FMS ( 0, 6, 7,10, 0, "Intel (unknown type) (Gemini Lake A0)");
3311 FMSQ( 0, 6, 7,10, 1, dP, "Intel Pentium Silver N5000 / J5000 (Gemini Lake B0)");
3312 FMSQ( 0, 6, 7,10, 1, dC, "Intel Celeron N4000 / J4000 (Gemini Lake B0)");
3313 FMS ( 0, 6, 7,10, 1, "Intel (unknown type) (Gemini Lake B0)");
3314 FMSQ( 0, 6, 7,10, 8, dP, "Intel Pentium Silver N5000 / J5000 (Gemini Lake R0)");
3315 FMSQ( 0, 6, 7,10, 8, dC, "Intel Celeron N4000 / J4000 (Gemini Lake R0)");
3316 FMS ( 0, 6, 7,10, 8, "Intel (unknown type) (Gemini Lake R0)");
3317 FMQ ( 0, 6, 7,10, dP, "Intel Pentium Silver N5000 / J5000 (Gemini Lake)");
3318 FMQ ( 0, 6, 7,10, dC, "Intel Celeron N4000 / J4000 (Gemini Lake)");
3319 FM ( 0, 6, 7,10, "Intel (unknown type) (Gemini Lake)");
3320 FM ( 0, 6, 7,13, "Intel Core i*-10000 (Ice Lake)"); // no spec update; only MSR_CPUID_table* so far
3321 // Intel docs (341079) provide inconsistent information about stepping
3322 // numbers for (0,6),(7,14), and it contradicts actual samples, so I'm
3323 // ignoring it.
3324 // Currently there are no Ice Lake CPUs for Xeon/Pentium/Celeron.
3325 // Coreboot* provides steppings 0 (A0) & 1 (B0), but not for stepping 5,
3326 // seen in an instlatx64 sample.
3327 FMS ( 0, 6, 7,14, 0, "Intel Core i*-10000 (Ice Lake-U/Y A0)");
3328 FMS ( 0, 6, 7,14, 1, "Intel Core i*-10000 (Ice Lake-U/Y B0)");
3329 FM ( 0, 6, 7,14, "Intel Core i*-10000 (Ice Lake-U/Y)");
3330 // no spec update; only MSR_CPUID_table* so far
3331 // MRG* 2018-03-06 mentions stepping 0, but doesn't specify which stepping name it is.
3332 FM ( 0, 6, 8, 5, "Intel Xeon Phi (Knights Mill)");
3333 FM ( 0, 6, 8, 6, "Intel Atom (Elkhart Lake)");
3334 FM ( 0, 6, 8,10, "Intel Atom (Lakefield)"); // no spec update; LX*
3335 // Coreboot* provides steppings.
3336 FMS ( 0, 6, 8,12, 0, "Intel Core (Tiger Lake-U A0)");
3337 FMSQ( 0, 6, 8,12, 1, dC, "Intel Celeron 6000 (Tiger Lake-U B0)");
3338 FMSQ( 0, 6, 8,12, 1, dP, "Intel Pentium Gold 7505 (Tiger Lake-U B0)");
3339 FMSQ( 0, 6, 8,12, 1, dc, "Intel Core i*-11000 / i*-1100G* (Tiger Lake-U B0)");
3340 FMS ( 0, 6, 8,12, 1, "Intel (unknown type) (Tiger Lake-U B0)");
3341 FMQ ( 0, 6, 8,12, dC, "Intel Celeron (Tiger Lake-U)");
3342 FMQ ( 0, 6, 8,12, dP, "Intel Pentium (Tiger Lake-U)");
3343 FMQ ( 0, 6, 8,12, dc, "Intel Core (Tiger Lake-U)");
3344 FM ( 0, 6, 8,12, "Intel (unknown type) (Tiger Lake-U)");
3345 // no spec update; only MSR_CPUID_table* so far
3346 // Coreboot* provides stepping.
3347 FMS ( 0, 6, 8,13, 1, "Intel Core (Tiger Lake R0)");
3348 FM ( 0, 6, 8,13, "Intel Core (Tiger Lake)");
3349 // Intel docs (334663) omit the stepping numbers for (0,6),(8,14)
3350 // H0, J1 & Y0, but (338025, 615213) provide some.
3351 // Coreboot* provides the 9 (H0) & 10 (Y0) stepping, but not J1.
3352 FMSQ( 0, 6, 8,14, 9, UC, "Intel Celeron 3x65U (Kaby Lake H0)"); // MRG* 2019-08-31 pinned down stepping
3353 FMSQ( 0, 6, 8,14, 9, UP, "Intel Celeron 4415U (Kaby Lake H0)"); // MRG* 2019-08-31 pinned down stepping
3354 FMSQ( 0, 6, 8,14, 9, YC, "Intel Celeron 3x65Y (Kaby Lake H0)"); // MRG* 2019-08-31 pinned down stepping
3355 FMSQ( 0, 6, 8,14, 9, YP, "Intel Celeron 4410Y (Kaby Lake H0)"); // MRG* 2019-08-31 pinned down stepping
3356 FMSQ( 0, 6, 8,14, 9, Y8, "Intel i*-8000Y / m*-8000Y (Amber Lake-Y H0)"); // no spec update; only MRG* 2019-08-31 & instlatx64 examples
3357 FMSQ( 0, 6, 8,14, 9, LY, "Intel Core i*-7000Y (Kaby Lake H0)"); // no spec update; only MRG* 2019-08-31 & instlatx64 examples
3358 FMSQ( 0, 6, 8,14, 9, dc, "Intel Core i*-7000U (Kaby Lake H0)"); // no docs on stepping; MRG* 2018-03-06, 2019-08-31
3359 FMSQ( 0, 6, 8,14, 10, dc, "Intel Core i*-8000U (Kaby Lake Y0)"); // no docs on stepping; MRG* 2018-03-06
3360 FMSQ( 0, 6, 8,14, 11, LU, "Intel Core i*-8000U (Whiskey Lake-U W0)");
3361 FMSQ( 0, 6, 8,14, 11, LY, "Intel Core i*-8000Y (Amber Lake-Y W0)");
3362 FMSQ( 0, 6, 8,14, 11, UC, "Intel Celeron 4205U (Whiskey Lake-U W0)");
3363 FMSQ( 0, 6, 8,14, 11, UP, "Intel Pentium 5405U (Whiskey Lake-U W0)");
3364 FMS ( 0, 6, 8,14, 11, "Intel Core (unknown type) (Whiskey Lake-U W0 / Amber Lake-Y W0)");
3365 FMSQ( 0, 6, 8,14, 12, UX, "Intel Core i*-10000U (Comet Lake-U V1)");
3366 FMSQ( 0, 6, 8,14, 12, LU, "Intel Core i*-8000U (Whiskey Lake-U V0)");
3367 FMSQ( 0, 6, 8,14, 12, LY, "Intel Core i*-8000Y / m*-8000Y / i*-10000Y (Amber Lake-Y V0)"); // m*-8000Y & i*-10000Y from MRG* 2019-11-13
3368 FMSQ( 0, 6, 8,14, 12, dP, "Intel Pentium 6000U (Comet Lake-U V1)"); // MRG* 2019-08-31 pinned down stepping
3369 FMSQ( 0, 6, 8,14, 12, dC, "Intel Celeron 5000U (Comet Lake-U V1)"); // MRG* 2019-08-31 pinned down stepping
3370 FMS ( 0, 6, 8,14, 12, "Intel (unknown type) (Whiskey Lake-U V0 / Comet Lake-U V1)");
3371 FM ( 0, 6, 8,14, "Intel Core (unknown type) (Kaby Lake / Amber Lake-Y / Whiskey Lake-U / Comet Lake-U)");
3372 FM ( 0, 6, 8,15, "Intel Xeon (unknown type) (Sapphire Rapids)"); // LX*
3373 // LX*. Coreboot* provides stepping.
3374 FMSQ( 0, 6, 9, 6, 0, dC, "Intel Celeron J6400 / N6400 (Elkhart Lake A0)");
3375 FMSQ( 0, 6, 9, 6, 0, dP, "Intel Pentium J6400 / N6400 (Elkhart Lake A0)");
3376 FMSQ( 0, 6, 9, 6, 0, da, "Intel Atom (Elkhart Lake A0)");
3377 FMS ( 0, 6, 9, 6, 0, "Intel (unknown type) (Elkhart Lake A0)");
3378 FMSQ( 0, 6, 9, 6, 1, dC, "Intel Celeron J6400 / N6400 (Elkhart Lake B0/B1)");
3379 FMSQ( 0, 6, 9, 6, 1, dP, "Intel Pentium J6400 / N6400 (Elkhart Lake B0/B1)");
3380 FMSQ( 0, 6, 9, 6, 1, da, "Intel Atom (Elkhart Lake B0/B1)");
3381 FMS ( 0, 6, 9, 6, 1, "Intel (unknown type) (Elkhart Lake B0/B1)");
3382 FMQ ( 0, 6, 9, 6, dC, "Intel Celeron (Elkhart Lake)");
3383 FMQ ( 0, 6, 9, 6, dP, "Intel Pentium (Elkhart Lake)");
3384 FMQ ( 0, 6, 9, 6, da, "Intel Atom (Elkhart Lake)");
3385 FM ( 0, 6, 9, 6, "Intel (unknown type) (Elkhart Lake)");
3386 // LX*. Coreboot* provides stepping.
3387 FMS ( 0, 6, 9, 7, 0, "Intel Atom (Alder Lake-S A0)");
3388 FM ( 0, 6, 9, 7, "Intel Atom (Alder Lake-S)");
3389 // Coreboot*. Coreboot* provides stepping.
3390 FMS ( 0, 6, 9,10, 0, "Intel Atom (Alder Lake A0)");
3391 FMS ( 0, 6, 9,10, 1, "Intel Atom (Alder Lake A1)");
3392 FMS ( 0, 6, 9,10, 2, "Intel Atom (Alder Lake A2)");
3393 FMS ( 0, 6, 9,10, 4, "Intel Atom (Alder Lake A3)");
3394 FM ( 0, 6, 9,10, "Intel Atom (Alder Lake)");
3395 // LX*. Coreboot* provides stepping.
3396 FMSQ( 0, 6, 9,12, 0, dC, "Intel Celeron N4500 / N5100 (Jasper Lake A0)");
3397 FMSQ( 0, 6, 9,12, 0, dP, "Intel Pentium N6000 (Jasper Lake A0)");
3398 FMS ( 0, 6, 9,12, 0, "Intel (unknown type) (Jasper Lake A0)");
3399 FMQ ( 0, 6, 9,12, dC, "Intel Celeron N4500 / N5100 (Jasper Lake)");
3400 FMQ ( 0, 6, 9,12, dP, "Intel Pentium N6000 (Jasper Lake)");
3401 FM ( 0, 6, 9,12, "Intel (unknown type) (Jasper Lake)");
3402 FM ( 0, 6, 9,13, "Intel NNP I-1000 (Spring Hill)"); // LX*
3403 // Intel docs (334663, 335718, 336466, 338014) omit the stepping numbers for
3404 // (0,6),(9,14) B0, but (337346) provides some.
3405 // Coreboot* provides the 9 (B0) stepping.
3406 // WARNING: If adding new steppings here, also update decode_uarch_intel.
3407 FMSQ( 0, 6, 9,14, 9, LG, "Intel Core i*-8700 (Kaby Lake-H B0)"); // no docs on stepping; only MRG* 2018-03-06, 2019-08-31
3408 FMSQ( 0, 6, 9,14, 9, dc, "Intel Core i*-7700 (Kaby Lake-H B0)"); // no docs on stepping; only MRG* 2018-03-06 & instlatx64 examples
3409 FMSQ( 0, 6, 9,14, 9, sX, "Intel Xeon E3-1200 v6 (Kaby Lake-H B0)"); // no docs on stepping; only MRG* 2018-03-06
3410 FMSQ( 0, 6, 9,14, 9, dC, "Intel Celeron G3930 (Kaby Lake-H B0)"); // MRG* 2020-01-27 pinned down stepping
3411 FMSQ( 0, 6, 9,14, 10, LU, "Intel Core i*-8000 U Line (Coffee Lake D0)");
3412 FMSQ( 0, 6, 9,14, 10, dc, "Intel Core i*-8000 S/H Line (Coffee Lake U0)");
3413 FMSQ( 0, 6, 9,14, 10, sX, "Intel Xeon E-2100 (Coffee Lake U0)"); // MRG* 2019-08-31
3414 FMSQ( 0, 6, 9,14, 11, dc, "Intel Core i*-8000 S Line (Coffee Lake B0)");
3415 FMSQ( 0, 6, 9,14, 11, dC, "Intel Celeron G4900 (Coffee Lake B0)"); // no spec update; MRG* 2020-01-27
3416 FMSQ( 0, 6, 9,14, 11, dP, "Intel Pentium Gold G5000 (Coffee Lake B0)"); // MRG* 2020-01-27 pinned down stepping
3417 FMSQ( 0, 6, 9,14, 12, dc, "Intel Core i*-9000 S Line (Coffee Lake P0)");
3418 FMSQ( 0, 6, 9,14, 13, d1, "Intel CC150 (Coffee Lake R0)"); // no docs; only instlatx64 example
3419 FMSQ( 0, 6, 9,14, 13, dc, "Intel Core i*-9000 H Line (Coffee Lake R0)");
3420 FMSQ( 0, 6, 9,14, 13, sX, "Intel Xeon E-2200 (Coffee Lake R0)"); // no docs on stepping; only MRG 2019-11-13
3421 FM ( 0, 6, 9,14, "Intel (unknown type) (Kaby Lake / Coffee Lake)");
3422 // LX*. Coreboot* provides more detail & steppings
3423 // (615213) mentions the (0,6),(10,5),2 and (0,6),(10,5),5 steppings, but
3424 // does not provide their names.
3425 // en.wikichip.org provides more details on stepping names.
3426 FMSQ( 0, 6, 10, 5, 0, dC, "Intel Celeron 5000 (Comet Lake-H/S G0)");
3427 FMSQ( 0, 6, 10, 5, 0, dP, "Intel Pentium Gold G6400 / G6500 (Comet Lake-H/S G0)");
3428 FMSQ( 0, 6, 10, 5, 0, dc, "Intel Core i*-10000 (Comet Lake-H/S G0)");
3429 FMSQ( 0, 6, 10, 5, 0, sX, "Intel Xeon W-1200 (Comet Lake-H/S G0)");
3430 FMS ( 0, 6, 10, 5, 0, "Intel (unknown type) (Comet Lake-H/S G0)");
3431 FMSQ( 0, 6, 10, 5, 1, dC, "Intel Celeron 5000 (Comet Lake-H/S P0)");
3432 FMSQ( 0, 6, 10, 5, 1, dP, "Intel Pentium Gold G6400 / G6500 (Comet Lake-H/S P0)");
3433 FMSQ( 0, 6, 10, 5, 1, dc, "Intel Core i*-10000 (Comet Lake-H/S P0)");
3434 FMSQ( 0, 6, 10, 5, 1, sX, "Intel Xeon W-1200 (Comet Lake-H/S P0)");
3435 FMS ( 0, 6, 10, 5, 1, "Intel (unknown type) (Comet Lake-H/S P0)");
3436 FMSQ( 0, 6, 10, 5, 2, dC, "Intel Celeron 5000 (Comet Lake-H/S R1)");
3437 FMSQ( 0, 6, 10, 5, 2, dP, "Intel Pentium Gold G6400 / G6500 (Comet Lake-H/S R1)");
3438 FMSQ( 0, 6, 10, 5, 2, dc, "Intel Core i*-10000 (Comet Lake-H/S R1)");
3439 FMSQ( 0, 6, 10, 5, 2, sX, "Intel Xeon W-1200 (Comet Lake-H/S R1)");
3440 FMS ( 0, 6, 10, 5, 2, "Intel (unknown type) (Comet Lake-H/S R1)");
3441 FMSQ( 0, 6, 10, 5, 3, dC, "Intel Celeron 5000 (Comet Lake-H/S G1)");
3442 FMSQ( 0, 6, 10, 5, 3, dP, "Intel Pentium Gold G6400 / G6500 (Comet Lake-H/S G1)");
3443 FMSQ( 0, 6, 10, 5, 3, dc, "Intel Core i*-10000 (Comet Lake-H/S G1)");
3444 FMSQ( 0, 6, 10, 5, 3, sX, "Intel Xeon W-1200 (Comet Lake-H/S G1)");
3445 FMS ( 0, 6, 10, 5, 3, "Intel (unknown type) (Comet Lake-H/S G1)");
3446 FMSQ( 0, 6, 10, 5, 4, dC, "Intel Celeron 5000 (Comet Lake-H/S P1)");
3447 FMSQ( 0, 6, 10, 5, 4, dP, "Intel Pentium Gold G6400 / G6500 (Comet Lake-H/S P1)");
3448 FMSQ( 0, 6, 10, 5, 4, dc, "Intel Core i*-10000 (Comet Lake-H/S P1)");
3449 FMSQ( 0, 6, 10, 5, 4, sX, "Intel Xeon W-1200 (Comet Lake-H/S P1)");
3450 FMS ( 0, 6, 10, 5, 4, "Intel (unknown type) (Comet Lake-H/S P1)");
3451 FMSQ( 0, 6, 10, 5, 5, dC, "Intel Celeron 5000 (Comet Lake-H/S Q0)");
3452 FMSQ( 0, 6, 10, 5, 5, dP, "Intel Pentium Gold G6400 / G6500 (Comet Lake-H/S Q0)");
3453 FMSQ( 0, 6, 10, 5, 5, dc, "Intel Core i*-10000 (Comet Lake-H/S Q0)");
3454 FMSQ( 0, 6, 10, 5, 5, sX, "Intel Xeon W-1200 (Comet Lake-H/S Q0)");
3455 FMS ( 0, 6, 10, 5, 5, "Intel (unknown type) (Comet Lake-H/S Q0)");
3456 FMQ ( 0, 6, 10, 5, dC, "Intel Celeron 5000 (Comet Lake-H/S)");
3457 FMQ ( 0, 6, 10, 5, dP, "Intel Pentium Gold G6400 / G6500 (Comet Lake-H/S)");
3458 FMQ ( 0, 6, 10, 5, dc, "Intel Core i*-10000 (Comet Lake-H/S)");
3459 FMQ ( 0, 6, 10, 5, sX, "Intel Xeon W-1200 (Comet Lake-H/S)");
3460 FM ( 0, 6, 10, 5, "Intel (unknown type) (Comet Lake-H/S)");
3461 // (615213) provides steppings.
3462 // MRG* 2019-11-13 & instlatx64 example
3463 // Coreboot* provides steppings.
3464 FMS ( 0, 6, 10, 6, 0, "Intel Core i*-10000 (Comet Lake-U A0)");
3465 FMS ( 0, 6, 10, 6, 1, "Intel Core i*-10000 (Comet Lake-U K0/K1/S0)");
3466 FMS ( 0, 6, 10, 6, 2, "Intel Core i*-10000 (Comet Lake-H R1)");
3467 FMS ( 0, 6, 10, 6, 3, "Intel Core i*-10000 (Comet Lake-S G1)");
3468 FMS ( 0, 6, 10, 6, 5, "Intel Core i*-10000 (Comet Lake-S Q0)");
3469 FM ( 0, 6, 10, 6, "Intel Core i*-10000 (Comet Lake)");
3470 FMQ ( 0, 6, 10, 7, dc, "Intel Core i*-11000 (Rocket Lake)");
3471 FMQ ( 0, 6, 10, 7, sX, "Intel Xeon E-1300 / E-2300G (Rocket Lake)");
3472 FM ( 0, 6, 10, 7, "Intel (unknown type) (Rocket Lake)");
3473 FQ ( 0, 6, sX, "Intel Xeon (unknown model)");
3474 FQ ( 0, 6, se, "Intel Xeon (unknown model)");
3475 FQ ( 0, 6, MC, "Intel Mobile Celeron (unknown model)");
3476 FQ ( 0, 6, dC, "Intel Celeron (unknown model)");
3477 FQ ( 0, 6, Xc, "Intel Core Extreme (unknown model)");
3478 FQ ( 0, 6, Mc, "Intel Mobile Core (unknown model)");
3479 FQ ( 0, 6, dc, "Intel Core (unknown model)");
3480 FQ ( 0, 6, MP, "Intel Mobile Pentium (unknown model)");
3481 FQ ( 0, 6, dP, "Intel Pentium (unknown model)");
3482 F ( 0, 6, "Intel (unknown model)");
3483 // Intel docs (249720).
3484 FMS ( 0, 7, 0, 0, 6, "Intel Itanium (Merced C0)");
3485 FMS ( 0, 7, 0, 0, 7, "Intel Itanium (Merced C1)");
3486 FMS ( 0, 7, 0, 0, 8, "Intel Itanium (Merced C2)");
3487 F ( 0, 7, "Intel Itanium (unknown model)");
3488 FM ( 0,11, 0, 0, "Intel Xeon Phi x100 Coprocessor (Knights Ferry)"); // found only on en.wikichip.org
3489 // Intel docs (328205).
3490 FMS ( 0,11, 0, 1, 1, "Intel Xeon Phi x100 Coprocessor (Knights Corner B0)");
3491 FMS ( 0,11, 0, 1, 3, "Intel Xeon Phi x100 Coprocessor (Knights Corner B1)");
3492 FMS ( 0,11, 0, 1, 4, "Intel Xeon Phi x100 Coprocessor (Knights Corner C0)");
3493 FM ( 0,11, 0, 1, "Intel Xeon Phi x100 Coprocessor (Knights Corner)");
3494 // Intel docs (249199, 249678).
3495 FMS ( 0,15, 0, 0, 7, "Intel Pentium 4 (Willamette B2)");
3496 FMSQ( 0,15, 0, 0, 10, dP, "Intel Pentium 4 (Willamette C1)");
3497 FMSQ( 0,15, 0, 0, 10, sX, "Intel Xeon (Foster C1)");
3498 FMS ( 0,15, 0, 0, 10, "Intel Pentium 4 (unknown type) 4 (Willamette/Foster C1)");
3499 FMQ ( 0,15, 0, 0, dP, "Intel Pentium 4 (Willamette)");
3500 FMQ ( 0,15, 0, 0, sX, "Intel Xeon (Foster)");
3501 FM ( 0,15, 0, 0, "Intel Pentium 4 (unknown type) (Willamette/Foster)");
3502 // Intel docs (249199, 249678, 290741, 290749).
3503 FMS ( 0,15, 0, 1, 1, "Intel Xeon MP (Foster C0)");
3504 FMSQ( 0,15, 0, 1, 2, dP, "Intel Pentium 4 (Willamette D0)");
3505 FMSQ( 0,15, 0, 1, 2, sX, "Intel Xeon (Foster D0)");
3506 FMS ( 0,15, 0, 1, 2, "Intel Pentium 4 (unknown type) (Willamette/Foster D0)");
3507 FMSQ( 0,15, 0, 1, 3, dP, "Intel Pentium 4(Willamette E0)");
3508 FMSQ( 0,15, 0, 1, 3, dC, "Intel Celeron 478-pin (Willamette E0)");
3509 FMS ( 0,15, 0, 1, 3, "Intel Pentium 4 (unknown type) (Willamette/Foster E0)");
3510 FMQ ( 0,15, 0, 1, dP, "Intel Pentium 4 (Willamette)");
3511 FMQ ( 0,15, 0, 1, sX, "Intel Xeon (Foster)");
3512 FM ( 0,15, 0, 1, "Intel Pentium 4 (unknown type) (Willamette/Foster)");
3513 // Intel docs (249199, 249678, 250721, 251309, 253176, 290741, 290749).
3514 FMS ( 0,15, 0, 2, 2, "Intel Xeon MP (Gallatin A0)");
3515 FMSQ( 0,15, 0, 2, 4, sX, "Intel Xeon (Prestonia B0)");
3516 FMSQ( 0,15, 0, 2, 4, MM, "Intel Mobile Pentium 4 Processor-M (Northwood B0)");
3517 FMSQ( 0,15, 0, 2, 4, MC, "Intel Mobile Celeron (Northwood B0)");
3518 FMSQ( 0,15, 0, 2, 4, dP, "Intel Pentium 4 (Northwood B0)");
3519 FMS ( 0,15, 0, 2, 4, "Intel Pentium 4 (unknown type) (Northwood/Prestonia B0)");
3520 FMSQ( 0,15, 0, 2, 5, dP, "Intel Pentium 4 (Northwood B1/M0)");
3521 FMSQ( 0,15, 0, 2, 5, sM, "Intel Xeon MP (Gallatin B1)");
3522 FMSQ( 0,15, 0, 2, 5, sX, "Intel Xeon (Prestonia B1)");
3523 FMS ( 0,15, 0, 2, 5, "Intel Pentium 4 (unknown type) (Northwood/Prestonia/Gallatin B1/M0)");
3524 FMS ( 0,15, 0, 2, 6, "Intel Xeon MP (Gallatin C0)");
3525 FMSQ( 0,15, 0, 2, 7, sX, "Intel Xeon (Prestonia C1)");
3526 FMSQ( 0,15, 0, 2, 7, dC, "Intel Celeron 478-pin (Northwood C1)");
3527 FMSQ( 0,15, 0, 2, 7, MC, "Intel Mobile Celeron (Northwood C1)");
3528 FMSQ( 0,15, 0, 2, 7, MM, "Intel Mobile Pentium 4 Processor-M (Northwood C1)");
3529 FMSQ( 0,15, 0, 2, 7, dP, "Intel Pentium 4 (Northwood C1)");
3530 FMS ( 0,15, 0, 2, 7, "Intel Pentium 4 (unknown type) (Northwood/Prestonia C1)");
3531 FMSQ( 0,15, 0, 2, 9, sX, "Intel Xeon (Prestonia D1)");
3532 FMSQ( 0,15, 0, 2, 9, dC, "Intel Celeron 478-pin (Northwood D1)");
3533 FMSQ( 0,15, 0, 2, 9, MC, "Intel Mobile Celeron (Northwood D1)");
3534 FMSQ( 0,15, 0, 2, 9, MM, "Intel Mobile Pentium 4 Processor-M (Northwood D1)");
3535 FMSQ( 0,15, 0, 2, 9, MP, "Intel Mobile Pentium 4 (Northwood D1)");
3536 FMSQ( 0,15, 0, 2, 9, dP, "Intel Pentium 4 (Northwood D1)");
3537 FMS ( 0,15, 0, 2, 9, "Intel Pentium 4 (unknown type) (Northwood/Prestonia D1)");
3538 FMQ ( 0,15, 0, 2, dP, "Intel Pentium 4 (Northwood)");
3539 FMQ ( 0,15, 0, 2, sM, "Intel Xeon MP (Gallatin)");
3540 FMQ ( 0,15, 0, 2, sX, "Intel Xeon (Prestonia)");
3541 FM ( 0,15, 0, 2, "Intel Pentium 4 (unknown type) (Northwood/Prestonia/Gallatin)");
3542 // Intel docs (302352, 302402, 302403, 302441).
3543 FMSQ( 0,15, 0, 3, 3, dP, "Intel Pentium 4 (Prescott C0)");
3544 FMSQ( 0,15, 0, 3, 3, dC, "Intel Celeron D (Prescott C0)");
3545 FMS ( 0,15, 0, 3, 3, "Intel Pentium 4 (unknown type) (Prescott C0)");
3546 FMSQ( 0,15, 0, 3, 4, sX, "Intel Xeon (Nocona D0)");
3547 FMSQ( 0,15, 0, 3, 4, dC, "Intel Celeron D (Prescott D0)");
3548 FMSQ( 0,15, 0, 3, 4, MP, "Intel Mobile Pentium 4 (Prescott D0)");
3549 FMSQ( 0,15, 0, 3, 4, dP, "Intel Pentium 4 (Prescott D0)");
3550 FMS ( 0,15, 0, 3, 4, "Intel Pentium 4 (unknown type) (Prescott/Nocona D0)");
3551 FMQ ( 0,15, 0, 3, sX, "Intel Xeon (Nocona)");
3552 FMQ( 0,15, 0, 3, dC, "Intel Celeron D (Prescott)");
3553 FMQ ( 0,15, 0, 3, MP, "Intel Mobile Pentium 4 (Prescott)");
3554 FMQ ( 0,15, 0, 3, dP, "Intel Pentium 4 (Prescott)");
3555 FM ( 0,15, 0, 3, "Intel Pentium 4 (unknown type) (Prescott/Nocona)");
3556 // Intel docs (302354, 306752, 306757, 306832, 309159, 309627).
3557 FMSQ( 0,15, 0, 4, 1, sP, "Intel Xeon MP (Potomac C0)");
3558 FMSQ( 0,15, 0, 4, 1, sM, "Intel Xeon MP (Cranford A0)");
3559 FMSQ( 0,15, 0, 4, 1, sX, "Intel Xeon (Nocona E0)");
3560 FMSQ( 0,15, 0, 4, 1, dC, "Intel Celeron D (Prescott E0)");
3561 FMSQ( 0,15, 0, 4, 1, MP, "Intel Mobile Pentium 4 (Prescott E0)");
3562 FMSQ( 0,15, 0, 4, 1, dP, "Intel Pentium 4 (Prescott E0)");
3563 FMS ( 0,15, 0, 4, 1, "Intel Pentium 4 (unknown type) (Prescott/Nocona/Cranford/Potomac E0)");
3564 FMSQ( 0,15, 0, 4, 3, sI, "Intel Xeon (Irwindale N0)");
3565 FMSQ( 0,15, 0, 4, 3, sX, "Intel Xeon (Nocona N0)");
3566 FMSQ( 0,15, 0, 4, 3, dP, "Intel Pentium 4 (Prescott N0)");
3567 FMS ( 0,15, 0, 4, 3, "Intel Pentium 4 (unknown type) (Prescott/Nocona/Irwindale N0)");
3568 FMSQ( 0,15, 0, 4, 4, dd, "Intel Pentium D Processor 8x0 (Smithfield A0)");
3569 FMSQ( 0,15, 0, 4, 4, dG, "Intel Pentium Extreme Edition Processor 840 (Smithfield A0)");
3570 FMS ( 0,15, 0, 4, 4, "Intel Pentium D (unknown type) (Smithfield A0)");
3571 FMSQ( 0,15, 0, 4, 7, dd, "Intel Pentium D Processor 8x0 (Smithfield B0)");
3572 FMSQ( 0,15, 0, 4, 7, dG, "Pentium Extreme Edition Processor 840 (Smithfield B0)");
3573 FMS ( 0,15, 0, 4, 7, "Intel Pentium D (unknown type) (Smithfield B0)");
3574 FMSQ( 0,15, 0, 4, 8, s7, "Intel Dual-Core Xeon Processor 7000 (Paxville A0)");
3575 FMSQ( 0,15, 0, 4, 8, sX, "Intel Dual-Core Xeon (Paxville A0)");
3576 FMS ( 0,15, 0, 4, 8, "Intel Dual-Core Xeon (unknown type) (Paxville A0)");
3577 FMSQ( 0,15, 0, 4, 9, sM, "Intel Xeon MP (Cranford B0)");
3578 FMSQ( 0,15, 0, 4, 9, dC, "Intel Celeron D (Prescott G1)");
3579 FMSQ( 0,15, 0, 4, 9, dP, "Intel Pentium 4 (Prescott G1)");
3580 FMS ( 0,15, 0, 4, 9, "Intel Pentium 4 (unknown type) (Prescott/Cranford G1)");
3581 FMSQ( 0,15, 0, 4, 10, sI, "Intel Xeon (Irwindale R0)");
3582 FMSQ( 0,15, 0, 4, 10, sX, "Intel Xeon (Nocona R0)");
3583 FMSQ( 0,15, 0, 4, 10, dP, "Intel Pentium 4 (Prescott R0)");
3584 FMS ( 0,15, 0, 4, 10, "Intel Pentium 4 (unknown type) (Prescott/Nocona/Irwindale R0)");
3585 FMQ ( 0,15, 0, 4, sM, "Intel Xeon MP (Nocona/Potomac)");
3586 FMQ ( 0,15, 0, 4, sX, "Intel Xeon (Nocona/Irwindale)");
3587 FMQ ( 0,15, 0, 4, dC, "Intel Celeron D (Prescott)");
3588 FMQ ( 0,15, 0, 4, MP, "Intel Mobile Pentium 4 (Prescott)");
3589 FMQ ( 0,15, 0, 4, dd, "Intel Pentium D (Smithfield A0)");
3590 FMQ ( 0,15, 0, 4, dP, "Intel Pentium 4 (Prescott) / Pentium Extreme Edition (Smithfield A0)");
3591 FM ( 0,15, 0, 4, "Intel Pentium 4 (unknown type) (Prescott/Nocona/Irwindale/Smithfield/Cranford/Potomac)");
3592 // Intel docs (310307, 310309, 311827, 313065, 314554).
3593 FMSQ( 0,15, 0, 6, 2, dd, "Intel Pentium D Processor 9xx (Presler B1)");
3594 FMSQ( 0,15, 0, 6, 2, dP, "Intel Pentium 4 Processor 6x1 (Cedar Mill B1) / Pentium Extreme Edition Processor 955 (Presler B1)");
3595 FMS ( 0,15, 0, 6, 2, "Intel Pentium 4 (unknown type) (Cedar Mill/Presler B1)");
3596 FMSQ( 0,15, 0, 6, 4, dd, "Intel Pentium D Processor 9xx (Presler C1)");
3597 FMSQ( 0,15, 0, 6, 4, dP, "Intel Pentium 4 Processor 6x1 (Cedar Mill C1) / Pentium Extreme Edition Processor 955 (Presler C1)");
3598 FMSQ( 0,15, 0, 6, 4, dC, "Intel Celeron D Processor 34x/35x (Cedar Mill C1)");
3599 FMSQ( 0,15, 0, 6, 4, sX, "Intel Xeon Processor 5000 (Dempsey C1)");
3600 FMS ( 0,15, 0, 6, 4, "Intel Pentium 4 (unknown type) (Cedar Mill/Presler/Dempsey C1)");
3601 FMSQ( 0,15, 0, 6, 5, dC, "Intel Celeron D Processor 36x (Cedar Mill D0)");
3602 FMSQ( 0,15, 0, 6, 5, dd, "Intel Pentium D Processor 9xx (Presler D0)");
3603 FMSQ( 0,15, 0, 6, 5, dP, "Intel Pentium 4 Processor 6x1 (Cedar Mill D0) / Pentium Extreme Edition Processor 955 (Presler D0)");
3604 FMS ( 0,15, 0, 6, 5, "Intel Pentium 4 (unknown type) (Cedar Mill/Presler D0)");
3605 FMS ( 0,15, 0, 6, 8, "Intel Xeon Processor 71x0 (Tulsa B0)");
3606 FMQ ( 0,15, 0, 6, dd, "Intel Pentium D (Presler)");
3607 FMQ ( 0,15, 0, 6, dP, "Intel Pentium 4 (Cedar Mill) / Pentium Extreme Edition (Presler)");
3608 FMQ ( 0,15, 0, 6, dC, "Intel Celeron D (Cedar Mill)");
3609 FMQ ( 0,15, 0, 6, sX, "Intel Xeon (Dempsey / Tulsa)");
3610 FM ( 0,15, 0, 6, "Intel Pentium 4 (unknown type) (Cedar Mill/Presler/Dempsey/Tulsa)");
3611 FQ ( 0,15, sM, "Intel Xeon MP (unknown model)");
3612 FQ ( 0,15, sX, "Intel Xeon (unknown model)");
3613 FQ ( 0,15, MC, "Intel Mobile Celeron (unknown model)");
3614 FQ ( 0,15, MC, "Intel Mobile Pentium 4 (unknown model)");
3615 FQ ( 0,15, MM, "Intel Mobile Pentium 4 Processor-M (unknown model)");
3616 FQ ( 0,15, dC, "Intel Celeron (unknown model)");
3617 FQ ( 0,15, dd, "Intel Pentium D (unknown model)");
3618 FQ ( 0,15, dP, "Intel Pentium 4 (unknown model)");
3619 FQ ( 0,15, dc, "Intel Pentium (unknown model)");
3620 F ( 0,15, "Intel Pentium 4 / Pentium D / Xeon / Xeon MP / Celeron / Celeron D (unknown model)");
3621 // NOTE: Intel spec updates describe CPUID in Itanium Register 3 format:
3622 // AAFFMMSSNN
3623 // AA = archrev (not reported via CPUID instruction)
3624 // FF = family
3625 // MM = model
3626 // SS = revision/stepping
3627 // NN = number (not reported via CPUID instruction)
3628 // Intel docs (251141).
3629 FMS ( 1,15, 0, 0, 7, "Intel Itanium2 (McKinley B3)");
3630 FM ( 1,15, 0, 0, "Intel Itanium2 (McKinley)");
3631 // Intel docs (251141).
3632 FMS ( 1,15, 0, 1, 5, "Intel Itanium2 (Madison/Deerfield/Hondo B1)");
3633 FM ( 1,15, 0, 1, "Intel Itanium2 (Madison/Deerfield/Hondo)");
3634 // Intel docs (251141).
3635 FMS ( 1,15, 0, 2, 1, "Intel Itanium2 (Madison 9M/Fanwood A1)");
3636 FMS ( 1,15, 0, 2, 2, "Intel Itanium2 (Madison 9M/Fanwood A2)");
3637 FM ( 1,15, 0, 2, "Intel Itanium2 (Madison)");
3638 F ( 1,15, "Intel Itanium2 (unknown model)");
3639 // Intel docs (251141).
3640 FMS ( 2, 0, 0, 0, 5, "Intel Itanium2 Dual-Core Processor 9000 (Montecito/Millington C1), 90nm");
3641 FMS ( 2, 0, 0, 0, 7, "Intel Itanium2 Dual-Core Processor 9000 (Montecito/Millington C2), 90nm");
3642 FM ( 2, 0, 0, 0, "Intel Itanium2 Dual-Core Processor 9000 (Montecito/Millington), 90nm");
3643 // Intel docs (251141).
3644 FMS ( 2, 0, 0, 1, 1, "Intel Itanium2 Dual-Core Processor 9100 (Montvale A1), 90nm");
3645 FM ( 2, 0, 0, 1, "Intel Itanium2 Dual-Core Processor 9100 (Montvale), 90nm");
3646 // Intel docs (323169).
3647 FMS ( 2, 0, 0, 2, 4, "Intel Itanium2 Processor 9300 (Tukwila E0), 65nm");
3648 FM ( 2, 0, 0, 2, "Intel Itanium2 Processor 9300 (Tukwila), 65nm");
3649 F ( 2, 0, "Intel Itanium2 (unknown model)");
3650 // Intel docs (323169).
3651 FMS ( 2, 1, 0, 0, 4, "Intel Itanium2 Processor 9500 (Poulson D0), 32nm");
3652 FMS ( 2, 1, 0, 0, 5, "Intel Itanium2 Processor 9700 (Kittson E0), 22nm");
3653 FM ( 2, 1, 0, 0, "Intel Itanium2 (unknown model) (Poulson/Kittson)");
3654 F ( 2, 1, "Intel Itanium2 (unknown model)");
3655 DEFAULT ("unknown");
3656
3657 return result;
3658 }
3659
3660 static cstring
decode_synth_amd(unsigned int val,const code_stash_t * stash)3661 decode_synth_amd(unsigned int val,
3662 const code_stash_t* stash)
3663 {
3664 cstring result = NULL;
3665
3666 START;
3667 FM ( 0, 4, 0, 3, "AMD 80486DX2");
3668 FM ( 0, 4, 0, 7, "AMD 80486DX2WB");
3669 FM ( 0, 4, 0, 8, "AMD 80486DX4");
3670 FM ( 0, 4, 0, 9, "AMD 80486DX4WB");
3671 FM ( 0, 4, 0,10, "AMD Elan SC400"); // sandpile.org
3672 FM ( 0, 4, 0,14, "AMD 5x86");
3673 FM ( 0, 4, 0,15, "AMD 5xWB");
3674 F ( 0, 4, "AMD 80486 / 5x (unknown model)");
3675 FM ( 0, 5, 0, 0, "AMD SSA5 (PR75, PR90, PR100)");
3676 FM ( 0, 5, 0, 1, "AMD 5k86 (PR120, PR133)");
3677 FM ( 0, 5, 0, 2, "AMD 5k86 (PR166)");
3678 FM ( 0, 5, 0, 3, "AMD 5k86 (PR200)");
3679 FM ( 0, 5, 0, 5, "AMD Geode GX");
3680 FM ( 0, 5, 0, 6, "AMD K6");
3681 FM ( 0, 5, 0, 7, "AMD K6 (Little Foot)");
3682 FMS ( 0, 5, 0, 8, 0, "AMD K6-2 (Chomper A)");
3683 FMS ( 0, 5, 0, 8, 12, "AMD K6-2 (Chomper A)");
3684 FM ( 0, 5, 0, 8, "AMD K6-2 (Chomper)");
3685 FMS ( 0, 5, 0, 9, 1, "AMD K6-III (Sharptooth B)");
3686 FM ( 0, 5, 0, 9, "AMD K6-III (Sharptooth)");
3687 FM ( 0, 5, 0,10, "AMD Geode LX");
3688 FM ( 0, 5, 0,13, "AMD K6-2+, K6-III+");
3689 F ( 0, 5, "AMD 5k86 / K6 / Geode (unknown model)");
3690 FM ( 0, 6, 0, 1, "AMD Athlon (Argon)");
3691 FM ( 0, 6, 0, 2, "AMD Athlon (K75 / Pluto / Orion)");
3692 FMS ( 0, 6, 0, 3, 0, "AMD Duron / mobile Duron (Spitfire A0)");
3693 FMS ( 0, 6, 0, 3, 1, "AMD Duron / mobile Duron (Spitfire A2)");
3694 FM ( 0, 6, 0, 3, "AMD Duron / mobile Duron (Spitfire)");
3695 FMS ( 0, 6, 0, 4, 2, "AMD Athlon (Thunderbird A4-A7)");
3696 FMS ( 0, 6, 0, 4, 4, "AMD Athlon (Thunderbird A9)");
3697 FM ( 0, 6, 0, 4, "AMD Athlon (Thunderbird)");
3698 FMSQ( 0, 6, 0, 6, 0, sA, "AMD Athlon MP (Palomino A0)");
3699 FMSQ( 0, 6, 0, 6, 0, dA, "AMD Athlon (Palomino A0)");
3700 FMSQ( 0, 6, 0, 6, 0, MA, "AMD mobile Athlon 4 (Palomino A0)");
3701 FMSQ( 0, 6, 0, 6, 0, sD, "AMD Duron MP (Palomino A0)");
3702 FMSQ( 0, 6, 0, 6, 0, MD, "AMD mobile Duron (Palomino A0)");
3703 FMS ( 0, 6, 0, 6, 0, "AMD Athlon (unknown type) (Palomino A0)");
3704 FMSQ( 0, 6, 0, 6, 1, sA, "AMD Athlon MP (Palomino A2)");
3705 FMSQ( 0, 6, 0, 6, 1, dA, "AMD Athlon (Palomino A2)");
3706 FMSQ( 0, 6, 0, 6, 1, MA, "AMD mobile Athlon 4 (Palomino A2)");
3707 FMSQ( 0, 6, 0, 6, 1, sD, "AMD Duron MP (Palomino A2)");
3708 FMSQ( 0, 6, 0, 6, 1, MD, "AMD mobile Duron (Palomino A2)");
3709 FMSQ( 0, 6, 0, 6, 1, dD, "AMD Duron (Palomino A2)");
3710 FMS ( 0, 6, 0, 6, 1, "AMD Athlon (unknown type) (Palomino A2)");
3711 FMSQ( 0, 6, 0, 6, 2, sA, "AMD Athlon MP (Palomino A5)");
3712 FMSQ( 0, 6, 0, 6, 2, dX, "AMD Athlon XP (Palomino A5)");
3713 FMSQ( 0, 6, 0, 6, 2, MA, "AMD mobile Athlon 4 (Palomino A5)");
3714 FMSQ( 0, 6, 0, 6, 2, sD, "AMD Duron MP (Palomino A5)");
3715 FMSQ( 0, 6, 0, 6, 2, MD, "AMD mobile Duron (Palomino A5)");
3716 FMSQ( 0, 6, 0, 6, 2, dD, "AMD Duron (Palomino A5)");
3717 FMS ( 0, 6, 0, 6, 2, "AMD Athlon (unknown type) (Palomino A5)");
3718 FMQ ( 0, 6, 0, 6, MD, "AMD mobile Duron (Palomino)");
3719 FMQ ( 0, 6, 0, 6, dD, "AMD Duron (Palomino)");
3720 FMQ ( 0, 6, 0, 6, MA, "AMD mobile Athlon (Palomino)");
3721 FMQ ( 0, 6, 0, 6, dX, "AMD Athlon XP (Palomino)");
3722 FMQ ( 0, 6, 0, 6, dA, "AMD Athlon (Palomino)");
3723 FM ( 0, 6, 0, 6, "AMD Athlon (unknown type) (Palomino)");
3724 FMSQ( 0, 6, 0, 7, 0, sD, "AMD Duron MP (Morgan A0)");
3725 FMSQ( 0, 6, 0, 7, 0, MD, "AMD mobile Duron (Morgan A0)");
3726 FMSQ( 0, 6, 0, 7, 0, dD, "AMD Duron (Morgan A0)");
3727 FMS ( 0, 6, 0, 7, 0, "AMD Duron (unknown type) (Morgan A0)");
3728 FMSQ( 0, 6, 0, 7, 1, sD, "AMD Duron MP (Morgan A1)");
3729 FMSQ( 0, 6, 0, 7, 1, MD, "AMD mobile Duron (Morgan A1)");
3730 FMSQ( 0, 6, 0, 7, 1, dD, "AMD Duron (Morgan A1)");
3731 FMS ( 0, 6, 0, 7, 1, "AMD Duron (unknown type) (Morgan A1)");
3732 FMQ ( 0, 6, 0, 7, sD, "AMD Duron MP (Morgan)");
3733 FMQ ( 0, 6, 0, 7, MD, "AMD mobile Duron (Morgan)");
3734 FMQ ( 0, 6, 0, 7, dD, "AMD Duron (Morgan)");
3735 FM ( 0, 6, 0, 7, "AMD Duron (unknown type) (Morgan)");
3736 FMSQ( 0, 6, 0, 8, 0, dS, "AMD Sempron (Thoroughbred A0)");
3737 FMSQ( 0, 6, 0, 8, 0, sD, "AMD Duron MP (Applebred A0)");
3738 FMSQ( 0, 6, 0, 8, 0, dD, "AMD Duron (Applebred A0)");
3739 FMSQ( 0, 6, 0, 8, 0, MX, "AMD mobile Athlon XP (Thoroughbred A0)");
3740 FMSQ( 0, 6, 0, 8, 0, sA, "AMD Athlon MP (Thoroughbred A0)");
3741 FMSQ( 0, 6, 0, 8, 0, dX, "AMD Athlon XP (Thoroughbred A0)");
3742 FMSQ( 0, 6, 0, 8, 0, dA, "AMD Athlon (Thoroughbred A0)");
3743 FMS ( 0, 6, 0, 8, 0, "AMD Athlon (unknown type) (Thoroughbred A0)");
3744 FMSQ( 0, 6, 0, 8, 1, MG, "AMD Geode NX (Thoroughbred B0)");
3745 FMSQ( 0, 6, 0, 8, 1, dS, "AMD Sempron (Thoroughbred B0)");
3746 FMSQ( 0, 6, 0, 8, 1, sD, "AMD Duron MP (Applebred B0)");
3747 FMSQ( 0, 6, 0, 8, 1, dD, "AMD Duron (Applebred B0)");
3748 FMSQ( 0, 6, 0, 8, 1, sA, "AMD Athlon MP (Thoroughbred B0)");
3749 FMSQ( 0, 6, 0, 8, 1, dX, "AMD Athlon XP (Thoroughbred B0)");
3750 FMSQ( 0, 6, 0, 8, 1, dA, "AMD Athlon (Thoroughbred B0)");
3751 FMS ( 0, 6, 0, 8, 1, "AMD Athlon (unknown type) (Thoroughbred B0)");
3752 FMQ ( 0, 6, 0, 8, MG, "AMD Geode NX (Thoroughbred)");
3753 FMQ ( 0, 6, 0, 8, dS, "AMD Sempron (Thoroughbred)");
3754 FMQ ( 0, 6, 0, 8, sD, "AMD Duron MP (Thoroughbred)");
3755 FMQ ( 0, 6, 0, 8, dD, "AMD Duron (Thoroughbred)");
3756 FMQ ( 0, 6, 0, 8, MX, "AMD mobile Athlon XP (Thoroughbred)");
3757 FMQ ( 0, 6, 0, 8, sA, "AMD Athlon MP (Thoroughbred)");
3758 FMQ ( 0, 6, 0, 8, dX, "AMD Athlon XP (Thoroughbred)");
3759 FMQ ( 0, 6, 0, 8, dA, "AMD Athlon XP (Thoroughbred)");
3760 FM ( 0, 6, 0, 8, "AMD Athlon (unknown type) (Thoroughbred)");
3761 FMSQ( 0, 6, 0,10, 0, dS, "AMD Sempron (Barton A2)");
3762 FMSQ( 0, 6, 0,10, 0, ML, "AMD mobile Athlon XP-M (LV) (Barton A2)");
3763 FMSQ( 0, 6, 0,10, 0, MX, "AMD mobile Athlon XP-M (Barton A2)");
3764 FMSQ( 0, 6, 0,10, 0, dt, "AMD Athlon XP (Thorton A2)");
3765 FMSQ( 0, 6, 0,10, 0, sA, "AMD Athlon MP (Barton A2)");
3766 FMSQ( 0, 6, 0,10, 0, dX, "AMD Athlon XP (Barton A2)");
3767 FMS ( 0, 6, 0,10, 0, "AMD Athlon (unknown type) (Barton A2)");
3768 FMQ ( 0, 6, 0,10, dS, "AMD Sempron (Barton)");
3769 FMQ ( 0, 6, 0,10, ML, "AMD mobile Athlon XP-M (LV) (Barton)");
3770 FMQ ( 0, 6, 0,10, MX, "AMD mobile Athlon XP-M (Barton)");
3771 FMQ ( 0, 6, 0,10, sA, "AMD Athlon MP (Barton)");
3772 FMQ ( 0, 6, 0,10, dX, "AMD Athlon XP (Barton)");
3773 FM ( 0, 6, 0,10, "AMD Athlon (unknown type) (Barton)");
3774 F ( 0, 6, "AMD Athlon (unknown model)");
3775 F ( 0, 7, "AMD Opteron (unknown model)");
3776 FMS ( 0,15, 0, 4, 0, "AMD Athlon 64 (SledgeHammer SH7-B0)");
3777 FMSQ( 0,15, 0, 4, 8, MX, "AMD mobile Athlon XP-M (SledgeHammer SH7-C0)");
3778 FMSQ( 0,15, 0, 4, 8, MA, "AMD mobile Athlon 64 (SledgeHammer SH7-C0)");
3779 FMSQ( 0,15, 0, 4, 8, dA, "AMD Athlon 64 (SledgeHammer SH7-C0)");
3780 FMS ( 0,15, 0, 4, 8, "AMD Athlon 64 (unknown type) (SledgeHammer SH7-C0)");
3781 FMSQ( 0,15, 0, 4, 10, MX, "AMD mobile Athlon XP-M (SledgeHammer SH7-CG)");
3782 FMSQ( 0,15, 0, 4, 10, MA, "AMD mobile Athlon 64 (SledgeHammer SH7-CG)");
3783 FMSQ( 0,15, 0, 4, 10, dA, "AMD Athlon 64 (SledgeHammer SH7-CG)");
3784 FMS ( 0,15, 0, 4, 10, "AMD Athlon 64 (unknown type) (SledgeHammer SH7-CG)");
3785 FMQ ( 0,15, 0, 4, MX, "AMD mobile Athlon XP-M (SledgeHammer SH7)");
3786 FMQ ( 0,15, 0, 4, MA, "AMD mobile Athlon 64 (SledgeHammer SH7)");
3787 FMQ ( 0,15, 0, 4, dA, "AMD Athlon 64 (SledgeHammer SH7)");
3788 FM ( 0,15, 0, 4, "AMD Athlon 64 (unknown type) (SledgeHammer SH7)");
3789 FMS ( 0,15, 0, 5, 0, "AMD Opteron (DP SledgeHammer SH7-B0)");
3790 FMS ( 0,15, 0, 5, 1, "AMD Opteron (DP SledgeHammer SH7-B3)");
3791 FMSQ( 0,15, 0, 5, 8, sO, "AMD Opteron (DP SledgeHammer SH7-C0)");
3792 FMSQ( 0,15, 0, 5, 8, dF, "AMD Athlon 64 FX (DP SledgeHammer SH7-C0)");
3793 FMS ( 0,15, 0, 5, 8, "AMD Athlon 64 (unknown type) (DP SledgeHammer SH7-C0)");
3794 FMSQ( 0,15, 0, 5, 10, sO, "AMD Opteron (DP SledgeHammer SH7-CG)");
3795 FMSQ( 0,15, 0, 5, 10, dF, "AMD Athlon 64 FX (DP SledgeHammer SH7-CG)");
3796 FMS ( 0,15, 0, 5, 10, "AMD Athlon 64 (unknown type) (DP SledgeHammer SH7-CG)");
3797 FMQ ( 0,15, 0, 5, sO, "AMD Opteron (SledgeHammer SH7)");
3798 FMQ ( 0,15, 0, 5, dF, "AMD Athlon 64 FX (SledgeHammer SH7)");
3799 FM ( 0,15, 0, 5, "AMD Athlon 64 (unknown type) (SledgeHammer SH7) FX");
3800 FMSQ( 0,15, 0, 7, 10, dF, "AMD Athlon 64 FX (DP SledgeHammer SH7-CG)");
3801 FMSQ( 0,15, 0, 7, 10, dA, "AMD Athlon 64 (DP SledgeHammer SH7-CG)");
3802 FMS ( 0,15, 0, 7, 10, "AMD Athlon 64 (unknown type) (DP SledgeHammer SH7-CG)");
3803 FMQ ( 0,15, 0, 7, dF, "AMD Athlon 64 FX (DP SledgeHammer SH7)");
3804 FMQ ( 0,15, 0, 7, dA, "AMD Athlon 64 (DP SledgeHammer SH7)");
3805 FM ( 0,15, 0, 7, "AMD Athlon 64 (unknown type) (DP SledgeHammer SH7)");
3806 FMSQ( 0,15, 0, 8, 2, MS, "AMD mobile Sempron (ClawHammer CH7-CG)");
3807 FMSQ( 0,15, 0, 8, 2, MX, "AMD mobile Athlon XP-M (ClawHammer CH7-CG)");
3808 FMSQ( 0,15, 0, 8, 2, MA, "AMD mobile Athlon 64 (Odessa CH7-CG)");
3809 FMSQ( 0,15, 0, 8, 2, dA, "AMD Athlon 64 (ClawHammer CH7-CG)");
3810 FMS ( 0,15, 0, 8, 2, "AMD Athlon 64 (unknown type) (ClawHammer/Odessa CH7-CG)");
3811 FMQ ( 0,15, 0, 8, MS, "AMD mobile Sempron (Odessa CH7)");
3812 FMQ ( 0,15, 0, 8, MX, "AMD mobile Athlon XP-M (Odessa CH7)");
3813 FMQ ( 0,15, 0, 8, MA, "AMD mobile Athlon 64 (Odessa CH7)");
3814 FMQ ( 0,15, 0, 8, dA, "AMD Athlon 64 (ClawHammer CH7)");
3815 FM ( 0,15, 0, 8, "AMD Athlon 64 (unknown type) (ClawHammer/Odessa CH7)");
3816 FMS ( 0,15, 0,11, 2, "AMD Athlon 64 (ClawHammer CH7-CG)");
3817 FM ( 0,15, 0,11, "AMD Athlon 64 (ClawHammer CH7)");
3818 FMSQ( 0,15, 0,12, 0, MS, "AMD mobile Sempron (Dublin DH7-CG)");
3819 FMSQ( 0,15, 0,12, 0, dS, "AMD Sempron (Paris DH7-CG)");
3820 FMSQ( 0,15, 0,12, 0, MX, "AMD mobile Athlon XP-M (ClawHammer/Odessa DH7-CG)");
3821 FMSQ( 0,15, 0,12, 0, MA, "AMD mobile Athlon 64 (ClawHammer/Odessa DH7-CG)");
3822 FMSQ( 0,15, 0,12, 0, dA, "AMD Athlon 64 (NewCastle DH7-CG)");
3823 FMS ( 0,15, 0,12, 0, "AMD Athlon 64 (unknown type) (ClawHammer/Odessa/NewCastle/Paris/Dublin DH7-CG)");
3824 FMQ ( 0,15, 0,12, MS, "AMD mobile Sempron (Dublin DH7)");
3825 FMQ ( 0,15, 0,12, dS, "AMD Sempron (Paris DH7)");
3826 FMQ ( 0,15, 0,12, MX, "AMD mobile Athlon XP-M (NewCastle DH7)");
3827 FMQ ( 0,15, 0,12, MA, "AMD mobile Athlon 64 (ClawHammer/Odessa DH7)");
3828 FMQ ( 0,15, 0,12, dA, "AMD Athlon 64 (NewCastle DH7)");
3829 FM ( 0,15, 0,12, "AMD Athlon 64 (unknown type) (ClawHammer/Odessa/NewCastle/Paris/Dublin DH7)");
3830 FMSQ( 0,15, 0,14, 0, MS, "AMD mobile Sempron (Dublin DH7-CG)");
3831 FMSQ( 0,15, 0,14, 0, dS, "AMD Sempron (Paris DH7-CG)");
3832 FMSQ( 0,15, 0,14, 0, MX, "AMD mobile Athlon XP-M (ClawHammer/Odessa DH7-CG)");
3833 FMSQ( 0,15, 0,14, 0, MA, "AMD mobile Athlon 64 (ClawHammer/Odessa DH7-CG)");
3834 FMSQ( 0,15, 0,14, 0, dA, "AMD Athlon 64 (NewCastle DH7-CG)");
3835 FMS ( 0,15, 0,14, 0, "AMD Athlon 64 (unknown type) (ClawHammer/Odessa/NewCastle/Paris/Dublin DH7-CG)");
3836 FMQ ( 0,15, 0,14, dS, "AMD Sempron (Paris DH7)");
3837 FMQ ( 0,15, 0,14, MS, "AMD mobile Sempron (Dublin DH7)");
3838 FMQ ( 0,15, 0,14, MX, "AMD mobile Athlon XP-M (ClawHammer/Odessa DH7)");
3839 FMQ ( 0,15, 0,14, MA, "AMD mobile Athlon 64 (ClawHammer/Odessa DH7)");
3840 FMQ ( 0,15, 0,14, dA, "AMD Athlon 64 (NewCastle DH7)");
3841 FM ( 0,15, 0,14, "AMD Athlon 64 (unknown type) (ClawHammer/Odessa/NewCastle/Paris/Dublin DH7)");
3842 FMSQ( 0,15, 0,15, 0, dS, "AMD Sempron (Paris DH7-CG)");
3843 FMSQ( 0,15, 0,15, 0, MA, "AMD mobile Athlon 64 (ClawHammer/Odessa DH7-CG)");
3844 FMSQ( 0,15, 0,15, 0, dA, "AMD Athlon 64 (NewCastle DH7-CG)");
3845 FMS ( 0,15, 0,15, 0, "AMD Athlon 64 (unknown type) (ClawHammer/Odessa/NewCastle/Paris DH7-CG)");
3846 FMQ ( 0,15, 0,15, dS, "AMD Sempron (Paris DH7)");
3847 FMQ ( 0,15, 0,15, MA, "AMD mobile Athlon 64 (ClawHammer/Odessa DH7)");
3848 FMQ ( 0,15, 0,15, dA, "AMD Athlon 64 (NewCastle DH7)");
3849 FM ( 0,15, 0,15, "AMD Athlon 64 (unknown type) (ClawHammer/Odessa/NewCastle/Paris DH7)");
3850 FMSQ( 0,15, 1, 4, 0, MX, "AMD mobile Athlon XP-M (Oakville SH7-D0)");
3851 FMSQ( 0,15, 1, 4, 0, MA, "AMD mobile Athlon 64 (Oakville SH7-D0)");
3852 FMSQ( 0,15, 1, 4, 0, dA, "AMD Athlon 64 (Winchester SH7-D0)");
3853 FMS ( 0,15, 1, 4, 0, "AMD Athlon 64 (unknown type) (Winchester/Oakville SH7-D0)");
3854 FMQ ( 0,15, 1, 4, MX, "AMD mobile Athlon XP-M (Oakville SH7)");
3855 FMQ ( 0,15, 1, 4, MA, "AMD mobile Athlon 64 (Oakville SH7)");
3856 FMQ ( 0,15, 1, 4, dA, "AMD Athlon 64 (Winchester SH7)");
3857 FM ( 0,15, 1, 4, "AMD Athlon 64 (unknown type) (Winchester/Oakville SH7)");
3858 FMSQ( 0,15, 1, 5, 0, sO, "AMD Opteron (Winchester SH7-D0)");
3859 FMSQ( 0,15, 1, 5, 0, dF, "AMD Athlon 64 FX (Winchester SH7-D0)");
3860 FMS ( 0,15, 1, 5, 0, "AMD Athlon 64 (unknown type) (Winchester SH7-D0)");
3861 FMQ ( 0,15, 1, 5, sO, "AMD Opteron (Winchester SH7)");
3862 FMQ ( 0,15, 1, 5, dF, "AMD Athlon 64 FX (Winchester SH7)");
3863 FM ( 0,15, 1, 5, "AMD Athlon 64 (unknown type) (Winchester SH7)");
3864 FMSQ( 0,15, 1, 7, 0, dF, "AMD Athlon 64 FX (Winchester SH7-D0)");
3865 FMSQ( 0,15, 1, 7, 0, dA, "AMD Athlon 64 (Winchester SH7-D0)");
3866 FMS ( 0,15, 1, 7, 0, "AMD Athlon 64 (unknown type) (Winchester SH7-D0)");
3867 FMQ ( 0,15, 1, 7, dF, "AMD Athlon 64 FX (Winchester SH7)");
3868 FMQ ( 0,15, 1, 7, dA, "AMD Athlon 64 (Winchester SH7)");
3869 FM ( 0,15, 1, 7, "AMD Athlon 64 (unknown type) (Winchester SH7)");
3870 FMSQ( 0,15, 1, 8, 0, MS, "AMD mobile Sempron (Georgetown/Sonora CH-D0)");
3871 FMSQ( 0,15, 1, 8, 0, MX, "AMD mobile Athlon XP-M (Oakville CH-D0)");
3872 FMSQ( 0,15, 1, 8, 0, MA, "AMD mobile Athlon 64 (Oakville CH-D0)");
3873 FMSQ( 0,15, 1, 8, 0, dA, "AMD Athlon 64 (Winchester CH-D0)");
3874 FMS ( 0,15, 1, 8, 0, "AMD Athlon 64 (unknown type) (Winchester/Oakville/Georgetown/Sonora CH-D0)");
3875 FMQ ( 0,15, 1, 8, MS, "AMD mobile Sempron (Georgetown/Sonora CH)");
3876 FMQ ( 0,15, 1, 8, MX, "AMD mobile Athlon XP-M (Oakville CH)");
3877 FMQ ( 0,15, 1, 8, MA, "AMD mobile Athlon 64 (Oakville CH)");
3878 FMQ ( 0,15, 1, 8, dA, "AMD Athlon 64 (Winchester CH)");
3879 FM ( 0,15, 1, 8, "AMD Athlon 64 (unknown type) (Winchester/Oakville/Georgetown/Sonora CH)");
3880 FMS ( 0,15, 1,11, 0, "AMD Athlon 64 (Winchester CH-D0)");
3881 FM ( 0,15, 1,11, "AMD Athlon 64 (Winchester CH)");
3882 FMSQ( 0,15, 1,12, 0, MS, "AMD mobile Sempron (Georgetown/Sonora DH8-D0)");
3883 FMSQ( 0,15, 1,12, 0, dS, "AMD Sempron (Palermo DH8-D0)");
3884 FMSQ( 0,15, 1,12, 0, MX, "AMD Athlon XP-M (Winchester DH8-D0)");
3885 FMSQ( 0,15, 1,12, 0, MA, "AMD mobile Athlon 64 (Oakville DH8-D0)");
3886 FMSQ( 0,15, 1,12, 0, dA, "AMD Athlon 64 (Winchester DH8-D0)");
3887 FMS ( 0,15, 1,12, 0, "AMD Athlon 64 (unknown type) (Winchester/Oakville/Georgetown/Sonora/Palermo DH8-D0)");
3888 FMQ ( 0,15, 1,12, MS, "AMD mobile Sempron (Georgetown/Sonora DH8)");
3889 FMQ ( 0,15, 1,12, dS, "AMD Sempron (Palermo DH8)");
3890 FMQ ( 0,15, 1,12, MX, "AMD Athlon XP-M (Winchester DH8)");
3891 FMQ ( 0,15, 1,12, MA, "AMD mobile Athlon 64 (Oakville DH8)");
3892 FMQ ( 0,15, 1,12, dA, "AMD Athlon 64 (Winchester DH8)");
3893 FM ( 0,15, 1,12, "AMD Athlon 64 (Winchester/Oakville/Georgetown/Sonora/Palermo DH8)");
3894 FMSQ( 0,15, 1,15, 0, dS, "AMD Sempron (Palermo DH8-D0)");
3895 FMSQ( 0,15, 1,15, 0, dA, "AMD Athlon 64 (Winchester DH8-D0)");
3896 FMS ( 0,15, 1,15, 0, "AMD Athlon 64 (Winchester DH8-D0) / Sempron (Palermo DH8-D0)");
3897 FMQ ( 0,15, 1,15, dS, "AMD Sempron (Palermo DH8)");
3898 FMQ ( 0,15, 1,15, dA, "AMD Athlon 64 (Winchester DH8)");
3899 FM ( 0,15, 1,15, "AMD Athlon 64 (unknown type) (Winchester/Palermo DH8)");
3900 FMSQ( 0,15, 2, 1, 0, s8, "AMD Dual Core Opteron (Egypt JH-E1)");
3901 FMSQ( 0,15, 2, 1, 0, sO, "AMD Dual Core Opteron (Italy JH-E1)");
3902 FMS ( 0,15, 2, 1, 0, "AMD Dual Core Opteron (Italy/Egypt JH-E1)");
3903 FMSQ( 0,15, 2, 1, 2, s8, "AMD Dual Core Opteron (Egypt JH-E6)");
3904 FMSQ( 0,15, 2, 1, 2, sO, "AMD Dual Core Opteron (Italy JH-E6)");
3905 FMS ( 0,15, 2, 1, 2, "AMD Dual Core Opteron (Italy/Egypt JH-E6)");
3906 FMQ ( 0,15, 2, 1, s8, "AMD Dual Core Opteron (Egypt JH)");
3907 FMQ ( 0,15, 2, 1, sO, "AMD Dual Core Opteron (Italy JH)");
3908 FM ( 0,15, 2, 1, "AMD Dual Core Opteron (Italy/Egypt JH)");
3909 FMSQ( 0,15, 2, 3, 2, DO, "AMD Dual Core Opteron (Denmark JH-E6)");
3910 FMSQ( 0,15, 2, 3, 2, dF, "AMD Athlon 64 FX (Toledo JH-E6)");
3911 FMSQ( 0,15, 2, 3, 2, dm, "AMD Athlon 64 X2 (Manchester JH-E6)");
3912 FMSQ( 0,15, 2, 3, 2, dA, "AMD Athlon 64 X2 (Toledo JH-E6)");
3913 FMS ( 0,15, 2, 3, 2, "AMD Athlon 64 (unknown type) (Toledo/Manchester/Denmark JH-E6)");
3914 FMQ ( 0,15, 2, 3, sO, "AMD Dual Core Opteron (Denmark JH)");
3915 FMQ ( 0,15, 2, 3, dF, "AMD Athlon 64 FX (Toledo JH)");
3916 FMQ ( 0,15, 2, 3, dm, "AMD Athlon 64 X2 (Manchester JH)");
3917 FMQ ( 0,15, 2, 3, dA, "AMD Athlon 64 X2 (Toledo JH)");
3918 FM ( 0,15, 2, 3, "AMD Athlon 64 (unknown type) (Toledo/Manchester/Denmark JH)");
3919 FMSQ( 0,15, 2, 4, 2, MA, "AMD mobile Athlon 64 (Newark SH-E5)");
3920 FMSQ( 0,15, 2, 4, 2, MT, "AMD mobile Turion (Lancaster/Richmond SH-E5)");
3921 FMS ( 0,15, 2, 4, 2, "AMD mobile Athlon 64 (unknown type) (Newark/Lancaster/Richmond SH-E5)");
3922 FMQ ( 0,15, 2, 4, MA, "AMD mobile Athlon 64 (Newark SH)");
3923 FMQ ( 0,15, 2, 4, MT, "AMD mobile Turion (Lancaster/Richmond SH)");
3924 FM ( 0,15, 2, 4, "AMD mobile Athlon 64 (unknown type) (Newark/Lancaster/Richmond SH)");
3925 FMQ ( 0,15, 2, 5, s8, "AMD Opteron (Athens SH-E4)");
3926 FMQ ( 0,15, 2, 5, sO, "AMD Opteron (Troy SH-E4)");
3927 FM ( 0,15, 2, 5, "AMD Opteron (Troy/Athens SH-E4)");
3928 FMSQ( 0,15, 2, 7, 1, sO, "AMD Opteron (Venus SH-E4)");
3929 FMSQ( 0,15, 2, 7, 1, dF, "AMD Athlon 64 FX (San Diego SH-E4)");
3930 FMSQ( 0,15, 2, 7, 1, dA, "AMD Athlon 64 (San Diego SH-E4)");
3931 FMS ( 0,15, 2, 7, 1, "AMD Athlon 64 (unknown type) (Venus/San Diego SH-E4)");
3932 FMQ ( 0,15, 2, 7, sO, "AMD Opteron (San Diego SH)");
3933 FMQ ( 0,15, 2, 7, dF, "AMD Athlon 64 FX (San Diego SH)");
3934 FMQ ( 0,15, 2, 7, dA, "AMD Athlon 64 (San Diego SH)");
3935 FM ( 0,15, 2, 7, "AMD Athlon 64 (unknown type) (San Diego SH)");
3936 FM ( 0,15, 2,11, "AMD Athlon 64 X2 (Manchester BH-E4)");
3937 FMS ( 0,15, 2,12, 0, "AMD Sempron (Palermo DH-E3)");
3938 FMSQ( 0,15, 2,12, 2, MS, "AMD mobile Sempron (Albany/Roma DH-E6)");
3939 FMSQ( 0,15, 2,12, 2, dS, "AMD Sempron (Palermo DH-E6)");
3940 FMSQ( 0,15, 2,12, 2, dA, "AMD Athlon 64 (Venice DH-E6)");
3941 FMS ( 0,15, 2,12, 2, "AMD Athlon 64 (Venice/Palermo/Albany/Roma DH-E6)");
3942 FMQ ( 0,15, 2,12, MS, "AMD mobile Sempron (Albany/Roma DH)");
3943 FMQ ( 0,15, 2,12, dS, "AMD Sempron (Palermo DH)");
3944 FMQ ( 0,15, 2,12, dA, "AMD Athlon 64 (Venice DH)");
3945 FM ( 0,15, 2,12, "AMD Athlon 64 (Venice/Palermo/Albany/Roma DH)");
3946 FMSQ( 0,15, 2,15, 0, dS, "AMD Sempron (Palermo DH-E3)");
3947 FMSQ( 0,15, 2,15, 0, dA, "AMD Athlon 64 (Venice DH-E3)");
3948 FMS ( 0,15, 2,15, 0, "AMD Athlon 64 (Venice/Palermo DH-E3)");
3949 FMSQ( 0,15, 2,15, 2, dS, "AMD Sempron (Palermo DH-E6)");
3950 FMSQ( 0,15, 2,15, 2, dA, "AMD Athlon 64 (Venice DH-E6)");
3951 FMS ( 0,15, 2,15, 2, "AMD Athlon 64 (Venice/Palermo DH-E6)");
3952 FMQ ( 0,15, 2,15, dS, "AMD Sempron (Palermo DH)");
3953 FMQ ( 0,15, 2,15, dA, "AMD Athlon 64 (Venice DH)");
3954 FM ( 0,15, 2,15, "AMD Athlon 64 (Venice/Palermo DH)");
3955 FMS ( 0,15, 4, 1, 2, "AMD Dual-Core Opteron (Santa Rosa JH-F2)");
3956 FMS ( 0,15, 4, 1, 3, "AMD Dual-Core Opteron (Santa Rosa JH-F3)");
3957 FM ( 0,15, 4, 1, "AMD Dual-Core Opteron (Santa Rosa)");
3958 FMSQ( 0,15, 4, 3, 2, DO, "AMD Dual-Core Opteron (Santa Rosa JH-F2)");
3959 FMSQ( 0,15, 4, 3, 2, sO, "AMD Opteron (Santa Rosa JH-F2)");
3960 FMSQ( 0,15, 4, 3, 2, dF, "AMD Athlon 64 FX Dual-Core (Windsor JH-F2)");
3961 FMSQ( 0,15, 4, 3, 2, dA, "AMD Athlon 64 X2 Dual-Core (Windsor JH-F2)");
3962 FMS ( 0,15, 4, 3, 2, "AMD Athlon 64 (unknown type) (Windsor JH-F2)");
3963 FMSQ( 0,15, 4, 3, 3, DO, "AMD Dual-Core Opteron (Santa Rosa JH-F3)");
3964 FMSQ( 0,15, 4, 3, 3, sO, "AMD Opteron (Santa Rosa JH-F3)");
3965 FMSQ( 0,15, 4, 3, 3, dF, "AMD Athlon 64 FX Dual-Core (Windsor JH-F3)");
3966 FMSQ( 0,15, 4, 3, 3, dA, "AMD Athlon 64 X2 Dual-Core (Windsor JH-F3)");
3967 FMS ( 0,15, 4, 3, 3, "AMD Athlon 64 (unknown type) (Windsor/Santa Rosa JH-F3)");
3968 FMQ ( 0,15, 4, 3, DO, "AMD Dual-Core Opteron (Santa Rosa)");
3969 FMQ ( 0,15, 4, 3, sO, "AMD Opteron (Santa Rosa)");
3970 FMQ ( 0,15, 4, 3, dF, "AMD Athlon 64 FX Dual-Core (Windsor)");
3971 FMQ ( 0,15, 4, 3, dA, "AMD Athlon 64 X2 Dual-Core (Windsor)");
3972 FM ( 0,15, 4, 3, "AMD Athlon 64 (unknown type) (Windsor/Santa Rosa)");
3973 FMSQ( 0,15, 4, 8, 2, dA, "AMD Athlon 64 X2 Dual-Core (Windsor BH-F2)");
3974 FMSQ( 0,15, 4, 8, 2, Mt, "AMD Turion 64 X2 (Trinidad BH-F2)");
3975 FMSQ( 0,15, 4, 8, 2, MT, "AMD Turion 64 X2 (Taylor BH-F2)");
3976 FMS ( 0,15, 4, 8, 2, "AMD Athlon 64 (unknown type) (Windsor/Taylor/Trinidad BH-F2)");
3977 FMQ ( 0,15, 4, 8, dA, "AMD Athlon 64 X2 Dual-Core (Windsor)");
3978 FMQ ( 0,15, 4, 8, Mt, "AMD Turion 64 X2 (Trinidad)");
3979 FMQ ( 0,15, 4, 8, MT, "AMD Turion 64 X2 (Taylor)");
3980 FM ( 0,15, 4, 8, "AMD Athlon 64 (unknown type) (Windsor/Taylor/Trinidad)");
3981 FMS ( 0,15, 4,11, 2, "AMD Athlon 64 X2 Dual-Core (Windsor BH-F2)");
3982 FM ( 0,15, 4,11, "AMD Athlon 64 X2 Dual-Core (Windsor)");
3983 FMSQ( 0,15, 4,12, 2, MS, "AMD mobile Sempron (Keene BH-F2)");
3984 FMSQ( 0,15, 4,12, 2, dS, "AMD Sempron (Manila BH-F2)");
3985 FMSQ( 0,15, 4,12, 2, Mt, "AMD Turion (Trinidad BH-F2)");
3986 FMSQ( 0,15, 4,12, 2, MT, "AMD Turion (Taylor BH-F2)");
3987 FMSQ( 0,15, 4,12, 2, dA, "AMD Athlon 64 (Orleans BH-F2)");
3988 FMS ( 0,15, 4,12, 2, "AMD Athlon 64 (unknown type) (Orleans/Manila/Keene/Taylor/Trinidad BH-F2)");
3989 FMQ ( 0,15, 4,12, MS, "AMD mobile Sempron (Keene)");
3990 FMQ ( 0,15, 4,12, dS, "AMD Sempron (Manila)");
3991 FMQ ( 0,15, 4,12, Mt, "AMD Turion (Trinidad)");
3992 FMQ ( 0,15, 4,12, MT, "AMD Turion (Taylor)");
3993 FMQ ( 0,15, 4,12, dA, "AMD Athlon 64 (Orleans)");
3994 FM ( 0,15, 4,12, "AMD Athlon 64 (unknown type) (Orleans/Manila/Keene/Taylor/Trinidad)");
3995 FMSQ( 0,15, 4,15, 2, MS, "AMD mobile Sempron (Keene DH-F2)");
3996 FMSQ( 0,15, 4,15, 2, dS, "AMD Sempron (Manila DH-F2)");
3997 FMSQ( 0,15, 4,15, 2, dA, "AMD Athlon 64 (Orleans DH-F2)");
3998 FMS ( 0,15, 4,15, 2, "AMD Athlon 64 (unknown type) (Orleans/Manila/Keene DH-F2)");
3999 FMQ ( 0,15, 4,15, MS, "AMD mobile Sempron (Keene)");
4000 FMQ ( 0,15, 4,15, dS, "AMD Sempron (Manila)");
4001 FMQ ( 0,15, 4,15, dA, "AMD Athlon 64 (Orleans)");
4002 FM ( 0,15, 4,15, "AMD Athlon 64 (unknown type) (Orleans/Manila/Keene)");
4003 FMS ( 0,15, 5,13, 3, "AMD Opteron (Santa Rosa JH-F3)");
4004 FM ( 0,15, 5,13, "AMD Opteron (Santa Rosa)");
4005 FMSQ( 0,15, 5,15, 2, MS, "AMD mobile Sempron (Keene DH-F2)");
4006 FMSQ( 0,15, 5,15, 2, dS, "AMD Sempron (Manila DH-F2)");
4007 FMSQ( 0,15, 5,15, 2, dA, "AMD Athlon 64 (Orleans DH-F2)");
4008 FMS ( 0,15, 5,15, 2, "AMD Athlon 64 (unknown type) (Orleans/Manila/Keene DH-F2)");
4009 FMS ( 0,15, 5,15, 3, "AMD Athlon 64 (Orleans DH-F3)");
4010 FMQ ( 0,15, 5,15, MS, "AMD mobile Sempron (Keene)");
4011 FMQ ( 0,15, 5,15, dS, "AMD Sempron (Manila)");
4012 FMQ ( 0,15, 5,15, dA, "AMD Athlon 64 (Orleans)");
4013 FM ( 0,15, 5,15, "AMD Athlon 64 (unknown type) (Orleans/Manila/Keene)");
4014 FM ( 0,15, 5,15, "AMD Athlon 64 (Orleans)");
4015 FMS ( 0,15, 6, 8, 1, "AMD Turion 64 X2 (Tyler BH-G1)");
4016 FMSQ( 0,15, 6, 8, 2, MT, "AMD Turion 64 X2 (Tyler BH-G2)");
4017 FMSQ( 0,15, 6, 8, 2, dS, "AMD Sempron Dual-Core (Tyler BH-G2)");
4018 FMS ( 0,15, 6, 8, 2, "AMD Turion 64 (unknown type) (Tyler BH-G2)");
4019 FMQ ( 0,15, 6, 8, MT, "AMD Turion 64 X2 (Tyler)");
4020 FMQ ( 0,15, 6, 8, dS, "AMD Sempron Dual-Core (Tyler)");
4021 FM ( 0,15, 6, 8, "AMD Turion 64 (unknown type) (Tyler)");
4022 FMSQ( 0,15, 6,11, 1, dS, "AMD Sempron Dual-Core (Sparta BH-G1)");
4023 FMSQ( 0,15, 6,11, 1, dA, "AMD Athlon 64 X2 Dual-Core (Brisbane BH-G1)");
4024 FMS ( 0,15, 6,11, 1, "AMD Athlon 64 (unknown type) (Brisbane/Sparta BH-G1)");
4025 FMSQ( 0,15, 6,11, 2, dA, "AMD Athlon 64 X2 Dual-Core (Brisbane BH-G2)");
4026 FMSQ( 0,15, 6,11, 2, Mn, "AMD Turion Neo X2 Dual-Core (Huron BH-G2)");
4027 FMSQ( 0,15, 6,11, 2, MN, "AMD Athlon Neo X2 (Huron BH-G2)");
4028 FMS ( 0,15, 6,11, 2, "AMD Athlon 64 (unknown type) (Brisbane/Huron BH-G2)");
4029 FMQ ( 0,15, 6,11, dS, "AMD Sempron Dual-Core (Sparta)");
4030 FMQ ( 0,15, 6,11, Mn, "AMD Turion Neo X2 Dual-Core (Huron)");
4031 FMQ ( 0,15, 6,11, MN, "AMD Athlon Neo X2 (Huron)");
4032 FMQ ( 0,15, 6,11, dA, "AMD Athlon 64 X2 Dual-Core (Brisbane)");
4033 FM ( 0,15, 6,11, "AMD Athlon 64 (unknown type) (Brisbane/Sparta/Huron)");
4034 FMSQ( 0,15, 6,12, 2, MS, "AMD mobile Sempron (Sherman DH-G2)");
4035 FMSQ( 0,15, 6,12, 2, dS, "AMD Sempron (Sparta DH-G2)");
4036 FMSQ( 0,15, 6,12, 2, dA, "AMD Athlon 64 (Lima DH-G2)");
4037 FMS ( 0,15, 6,12, 2, "AMD Athlon 64 (unknown type) (Lima/Sparta/Sherman DH-G2)");
4038 FMQ ( 0,15, 6,12, MS, "AMD mobile Sempron (Sherman)");
4039 FMQ ( 0,15, 6,12, dS, "AMD Sempron (Sparta)");
4040 FMQ ( 0,15, 6,12, dA, "AMD Athlon 64 (Lima)");
4041 FM ( 0,15, 6,12, "AMD Athlon 64 (unknown type) (Lima/Sparta/Sherman)");
4042 FMSQ( 0,15, 6,15, 2, MS, "AMD mobile Sempron (Sherman DH-G2)");
4043 FMSQ( 0,15, 6,15, 2, dS, "AMD Sempron (Sparta DH-G2)");
4044 FMSQ( 0,15, 6,15, 2, MN, "AMD Athlon Neo (Huron DH-G2)");
4045 FMS ( 0,15, 6,15, 2, "AMD Athlon Neo (unknown type) (Huron/Sparta/Sherman DH-G2)");
4046 FMQ ( 0,15, 6,15, MS, "AMD mobile Sempron (Sherman)");
4047 FMQ ( 0,15, 6,15, dS, "AMD Sempron (Sparta)");
4048 FMQ ( 0,15, 6,15, MN, "AMD Athlon Neo (Huron)");
4049 FM ( 0,15, 6,15, "AMD Athlon Neo (unknown type) (Huron/Sparta/Sherman)");
4050 FMSQ( 0,15, 7,12, 2, MS, "AMD mobile Sempron (Sherman DH-G2)");
4051 FMSQ( 0,15, 7,12, 2, dS, "AMD Sempron (Sparta DH-G2)");
4052 FMSQ( 0,15, 7,12, 2, dA, "AMD Athlon (Lima DH-G2)");
4053 FMS ( 0,15, 7,12, 2, "AMD Athlon (unknown type) (Lima/Sparta/Sherman DH-G2)");
4054 FMQ ( 0,15, 7,12, MS, "AMD mobile Sempron (Sherman)");
4055 FMQ ( 0,15, 7,12, dS, "AMD Sempron (Sparta)");
4056 FMQ ( 0,15, 7,12, dA, "AMD Athlon (Lima)");
4057 FM ( 0,15, 7,12, "AMD Athlon (unknown type) (Lima/Sparta/Sherman)");
4058 FMSQ( 0,15, 7,15, 1, MS, "AMD mobile Sempron (Sherman DH-G1)");
4059 FMSQ( 0,15, 7,15, 1, dS, "AMD Sempron (Sparta DH-G1)");
4060 FMSQ( 0,15, 7,15, 1, dA, "AMD Athlon 64 (Lima DH-G1)");
4061 FMS ( 0,15, 7,15, 1, "AMD Athlon 64 (unknown type) (Lima/Sparta/Sherman DH-G1)");
4062 FMSQ( 0,15, 7,15, 2, MS, "AMD mobile Sempron (Sherman DH-G2)");
4063 FMSQ( 0,15, 7,15, 2, dS, "AMD Sempron (Sparta DH-G2)");
4064 FMSQ( 0,15, 7,15, 2, MN, "AMD Athlon Neo (Huron DH-G2)");
4065 FMSQ( 0,15, 7,15, 2, dA, "AMD Athlon 64 (Lima DH-G2)");
4066 FMS ( 0,15, 7,15, 2, "AMD Athlon 64 (unknown type) (Lima/Sparta/Sherman/Huron DH-G2)");
4067 FMQ ( 0,15, 7,15, MS, "AMD mobile Sempron (Sherman)");
4068 FMQ ( 0,15, 7,15, dS, "AMD Sempron (Sparta)");
4069 FMQ ( 0,15, 7,15, MN, "AMD Athlon Neo (Huron)");
4070 FMQ ( 0,15, 7,15, dA, "AMD Athlon 64 (Lima)");
4071 FM ( 0,15, 7,15, "AMD Athlon 64 (unknown type) (Lima/Sparta/Sherman/Huron)");
4072 FMS ( 0,15, 12, 1, 3, "AMD Athlon 64 FX Dual-Core (Windsor JH-F3)");
4073 FM ( 0,15, 12, 1, "AMD Athlon 64 FX Dual-Core (Windsor)");
4074 F ( 0,15, "AMD (unknown model)");
4075 FMS ( 1,15, 0, 0, 0, "AMD (unknown type) (Barcelona DR-A0)"); // sandpile.org
4076 FMS ( 1,15, 0, 0, 1, "AMD (unknown type) (Barcelona DR-A1)"); // sandpile.org
4077 FMS ( 1,15, 0, 0, 2, "AMD (unknown type) (Barcelona DR-A2)"); // sandpile.org
4078 FMS ( 1,15, 0, 2, 0, "AMD (unknown type) (Barcelona DR-B0)"); // sandpile.org
4079 FMSQ( 1,15, 0, 2, 1, sO, "AMD Quad-Core Opteron (Barcelona DR-B1)");
4080 FMS ( 1,15, 0, 2, 1, "AMD (unknown type) (Barcelona DR-B1)");
4081 FMSQ( 1,15, 0, 2, 2, EO, "AMD Embedded Opteron (Barcelona DR-B2)");
4082 FMSQ( 1,15, 0, 2, 2, sO, "AMD Quad-Core Opteron (Barcelona DR-B2)");
4083 FMSQ( 1,15, 0, 2, 2, Tp, "AMD Phenom Triple-Core (Toliman DR-B2)");
4084 FMSQ( 1,15, 0, 2, 2, Qp, "AMD Phenom Quad-Core (Agena DR-B2)");
4085 FMS ( 1,15, 0, 2, 2, "AMD (unknown type) (Barcelona/Toliman/Agena DR-B2)");
4086 FMSQ( 1,15, 0, 2, 3, EO, "AMD Embedded Opteron (Barcelona DR-B3)");
4087 FMSQ( 1,15, 0, 2, 3, sO, "AMD Quad-Core Opteron (Barcelona DR-B3)");
4088 FMSQ( 1,15, 0, 2, 3, Tp, "AMD Phenom Triple-Core (Toliman DR-B3)");
4089 FMSQ( 1,15, 0, 2, 3, Qp, "AMD Phenom Quad-Core (Agena DR-B3)");
4090 FMSQ( 1,15, 0, 2, 3, dA, "AMD Athlon Dual-Core (Kuma DR-B3)");
4091 FMS ( 1,15, 0, 2, 3, "AMD (unknown type) (Barcelona/Toliman/Agena/Kuma DR-B3)");
4092 FMS ( 1,15, 0, 2, 10, "AMD Quad-Core Opteron (Barcelona DR-BA)");
4093 FMQ ( 1,15, 0, 2, EO, "AMD Embedded Opteron (Barcelona)");
4094 FMQ ( 1,15, 0, 2, sO, "AMD Quad-Core Opteron (Barcelona)");
4095 FMQ ( 1,15, 0, 2, Tp, "AMD Phenom Triple-Core (Toliman)");
4096 FMQ ( 1,15, 0, 2, Qp, "AMD Phenom Quad-Core (Agena)");
4097 FMQ ( 1,15, 0, 2, dA, "AMD Athlon Dual-Core (Kuma)");
4098 FM ( 1,15, 0, 2, "AMD (unknown type) (Barcelona/Toliman/Agena/Kuma)");
4099 FMS ( 1,15, 0, 4, 0, "AMD Athlon (unknown type) (Regor/Propus/Shanghai/Callisto/Heka/Deneb RB-C0)"); // sandpile.org
4100 FMS ( 1,15, 0, 4, 1, "AMD Athlon (unknown type) (Regor/Propus/Shanghai/Callisto/Heka/Deneb RB-C1)"); // sandpile.org
4101 FMSQ( 1,15, 0, 4, 2, EO, "AMD Embedded Opteron (Shanghai RB-C2)");
4102 FMSQ( 1,15, 0, 4, 2, sO, "AMD Quad-Core Opteron (Shanghai RB-C2)");
4103 FMSQ( 1,15, 0, 4, 2, dr, "AMD Athlon Dual-Core (Propus RB-C2)");
4104 FMSQ( 1,15, 0, 4, 2, dA, "AMD Athlon Dual-Core (Regor RB-C2)");
4105 FMSQ( 1,15, 0, 4, 2, Dp, "AMD Phenom II X2 (Callisto RB-C2)");
4106 FMSQ( 1,15, 0, 4, 2, Tp, "AMD Phenom II X3 (Heka RB-C2)");
4107 FMSQ( 1,15, 0, 4, 2, Qp, "AMD Phenom II X4 (Deneb RB-C2)");
4108 FMS ( 1,15, 0, 4, 2, "AMD Athlon (unknown type) (Regor/Propus/Shanghai/Callisto/Heka/Deneb RB-C2)");
4109 FMSQ( 1,15, 0, 4, 3, Dp, "AMD Phenom II X2 (Callisto RB-C3)");
4110 FMSQ( 1,15, 0, 4, 3, Tp, "AMD Phenom II X3 (Heka RB-C3)");
4111 FMSQ( 1,15, 0, 4, 3, Qp, "AMD Phenom II X4 (Deneb RB-C3)");
4112 FMS ( 1,15, 0, 4, 3, "AMD Phenom II (unknown type) (Callisto/Heka/Deneb RB-C3)");
4113 FMQ ( 1,15, 0, 4, EO, "AMD Embedded Opteron (Shanghai)");
4114 FMQ ( 1,15, 0, 4, sO, "AMD Quad-Core Opteron (Shanghai)");
4115 FMQ ( 1,15, 0, 4, dr, "AMD Athlon Dual-Core (Propus)");
4116 FMQ ( 1,15, 0, 4, dA, "AMD Athlon Dual-Core (Regor)");
4117 FMQ ( 1,15, 0, 4, Dp, "AMD Phenom II X2 (Callisto)");
4118 FMQ ( 1,15, 0, 4, Tp, "AMD Phenom II X3 (Heka)");
4119 FMQ ( 1,15, 0, 4, Qp, "AMD Phenom II X4 (Deneb)");
4120 FM ( 1,15, 0, 4, "AMD Athlon (unknown type) (Regor/Propus/Shanghai/Callisto/Heka/Deneb)");
4121 FMS ( 1,15, 0, 5, 0, "AMD Athlon (unknown type) (Regor/Rana/Propus BL-C0)"); // sandpile.org
4122 FMS ( 1,15, 0, 5, 1, "AMD Athlon (unknown type) (Regor/Rana/Propus BL-C1)"); // sandpile.org
4123 FMSQ( 1,15, 0, 5, 2, DA, "AMD Athlon II X2 (Regor BL-C2)");
4124 FMSQ( 1,15, 0, 5, 2, TA, "AMD Athlon II X3 (Rana BL-C2)");
4125 FMSQ( 1,15, 0, 5, 2, QA, "AMD Athlon II X4 (Propus BL-C2)");
4126 FMS ( 1,15, 0, 5, 2, "AMD Athlon (unknown type) (Regor/Rana/Propus BL-C2)");
4127 FMSQ( 1,15, 0, 5, 3, TA, "AMD Athlon II X3 (Rana BL-C3)");
4128 FMSQ( 1,15, 0, 5, 3, QA, "AMD Athlon II X4 (Propus BL-C3)");
4129 FMSQ( 1,15, 0, 5, 3, Tp, "AMD Phenom II Triple-Core (Heka BL-C3)");
4130 FMSQ( 1,15, 0, 5, 3, Qp, "AMD Phenom II Quad-Core (Deneb BL-C3)");
4131 FMS ( 1,15, 0, 5, 3, "AMD Athlon (unknown type) (Regor/Rana/Propus/Callisto/Heka/Deneb BL-C3)");
4132 FMQ ( 1,15, 0, 5, DA, "AMD Athlon II X2 (Regor)");
4133 FMQ ( 1,15, 0, 5, TA, "AMD Athlon II X3 (Rana)");
4134 FMQ ( 1,15, 0, 5, QA, "AMD Athlon II X4 (Propus)");
4135 FMQ ( 1,15, 0, 5, Tp, "AMD Phenom II Triple-Core (Heka)");
4136 FMQ ( 1,15, 0, 5, Qp, "AMD Phenom II Quad-Core (Deneb)");
4137 FM ( 1,15, 0, 5, "AMD Athlon (unknown type) (Regor/Rana/Propus/Callisto/Heka/Deneb)");
4138 FMS ( 1,15, 0, 6, 0, "AMD Athlon (unknown type) (Regor/Sargas/Caspain DA-C0)");
4139 FMS ( 1,15, 0, 6, 1, "AMD Athlon (unknown type) (Regor/Sargas/Caspain DA-C1)");
4140 FMSQ( 1,15, 0, 6, 2, MS, "AMD Sempron Mobile (Sargas DA-C2)");
4141 FMSQ( 1,15, 0, 6, 2, dS, "AMD Sempron II (Sargas DA-C2)");
4142 FMSQ( 1,15, 0, 6, 2, MT, "AMD Turion II Dual-Core Mobile (Caspian DA-C2)");
4143 FMSQ( 1,15, 0, 6, 2, MA, "AMD Athlon II Dual-Core Mobile (Regor DA-C2)");
4144 FMSQ( 1,15, 0, 6, 2, DA, "AMD Athlon II X2 (Regor DA-C2)");
4145 FMSQ( 1,15, 0, 6, 2, dA, "AMD Athlon II (Sargas DA-C2)");
4146 FMS ( 1,15, 0, 6, 2, "AMD Athlon (unknown type) (Regor/Sargas/Caspain DA-C2)");
4147 FMSQ( 1,15, 0, 6, 3, Ms, "AMD V-Series Mobile (Champlain DA-C3)");
4148 FMSQ( 1,15, 0, 6, 3, DS, "AMD Sempron II X2 (Regor DA-C3)");
4149 FMSQ( 1,15, 0, 6, 3, dS, "AMD Sempron II (Sargas DA-C3)");
4150 FMSQ( 1,15, 0, 6, 3, MT, "AMD Turion II Dual-Core Mobile (Champlain DA-C3)");
4151 FMSQ( 1,15, 0, 6, 3, Mp, "AMD Phenom II Dual-Core Mobile (Champlain DA-C3)");
4152 FMSQ( 1,15, 0, 6, 3, MA, "AMD Athlon II Dual-Core Mobile (Champlain DA-C3)");
4153 FMSQ( 1,15, 0, 6, 3, DA, "AMD Athlon II X2 (Regor DA-C3)");
4154 FMSQ( 1,15, 0, 6, 3, dA, "AMD Athlon II (Sargas DA-C3)");
4155 FMS ( 1,15, 0, 6, 3, "AMD Athlon (unknown type) (Regor/Sargas/Champlain DA-C3)");
4156 FMQ ( 1,15, 0, 6, Ms, "AMD V-Series Mobile (Champlain)");
4157 FMQ ( 1,15, 0, 6, MS, "AMD Sempron Mobile (Sargas)");
4158 FMQ ( 1,15, 0, 6, DS, "AMD Sempron II X2 (Regor)");
4159 FMQ ( 1,15, 0, 6, dS, "AMD Sempron II (Sargas)");
4160 FMQ ( 1,15, 0, 6, MT, "AMD Turion II Dual-Core Mobile (Caspian / Champlain)");
4161 FMQ ( 1,15, 0, 6, Mp, "AMD Phenom II Dual-Core Mobile (Champlain)");
4162 FMQ ( 1,15, 0, 6, MA, "AMD Athlon II Dual-Core Mobile (Regor / Champlain)");
4163 FMQ ( 1,15, 0, 6, DA, "AMD Athlon II X2 (Regor)");
4164 FMQ ( 1,15, 0, 6, dA, "AMD Athlon II (Sargas)");
4165 FM ( 1,15, 0, 6, "AMD Athlon (unknown type) (Regor/Sargas/Caspian/Champlain)");
4166 FMSQ( 1,15, 0, 8, 0, SO, "AMD Six-Core Opteron (Istanbul HY-D0)");
4167 FMSQ( 1,15, 0, 8, 0, sO, "AMD Opteron 4100 (Lisbon HY-D0)");
4168 FMS ( 1,15, 0, 8, 0, "AMD Opteron (unknown type) (Lisbon/Istanbul HY-D0)");
4169 FMS ( 1,15, 0, 8, 1, "AMD Opteron 4100 (Lisbon HY-D1)");
4170 FMQ ( 1,15, 0, 8, SO, "AMD Six-Core Opteron (Istanbul)");
4171 FMQ ( 1,15, 0, 8, sO, "AMD Opteron 4100 (Lisbon)");
4172 FM ( 1,15, 0, 8, "AMD Opteron (unknown type) (Lisbon/Istanbul)");
4173 FMS ( 1,15, 0, 9, 0, "AMD Opteron 6100 (Magny-Cours HY-D0)"); // sandpile.org
4174 FMS ( 1,15, 0, 9, 1, "AMD Opteron 6100 (Magny-Cours HY-D1)");
4175 FM ( 1,15, 0, 9, "AMD Opteron 6100 (Magny-Cours)");
4176 FMSQ( 1,15, 0,10, 0, Qp, "AMD Phenom II X4 (Zosma PH-E0)");
4177 FMSQ( 1,15, 0,10, 0, Sp, "AMD Phenom II X6 (Thuban PH-E0)");
4178 FMS ( 1,15, 0,10, 0, "AMD Phenom II (unknown type) (Zosma/Thuban PH-E0)");
4179 FMQ ( 1,15, 0,10, Qp, "AMD Phenom II X4 (Zosma)");
4180 FMQ ( 1,15, 0,10, Sp, "AMD Phenom II X6 (Thuban)");
4181 FM ( 1,15, 0,10, "AMD Phenom II (unknown type) (Zosma/Thuban)");
4182 F ( 1,15, "AMD (unknown model)");
4183 FMSQ( 2,15, 0, 3, 1, MU, "AMD Turion X2 Ultra Dual-Core Mobile (Griffin LG-B1)");
4184 FMSQ( 2,15, 0, 3, 1, MT, "AMD Turion X2 Dual-Core Mobile (Lion LG-B1)");
4185 FMSQ( 2,15, 0, 3, 1, DS, "AMD Sempron X2 Dual-Core (Sable LG-B1)");
4186 FMSQ( 2,15, 0, 3, 1, dS, "AMD Sempron (Sable LG-B1)");
4187 FMSQ( 2,15, 0, 3, 1, DA, "AMD Athlon X2 Dual-Core (Lion LG-B1)");
4188 FMSQ( 2,15, 0, 3, 1, dA, "AMD Athlon (Lion LG-B1)");
4189 FMS ( 2,15, 0, 3, 1, "AMD Athlon (unknown type) (Lion/Sable LG-B1)");
4190 FMQ ( 2,15, 0, 3, MU, "AMD Turion X2 Ultra (Griffin)");
4191 FMQ ( 2,15, 0, 3, MT, "AMD Turion X2 (Lion)");
4192 FMQ ( 2,15, 0, 3, DS, "AMD Sempron X2 Dual-Core (Sable)");
4193 FMQ ( 2,15, 0, 3, dS, "AMD Sempron (Sable)");
4194 FMQ ( 2,15, 0, 3, DA, "AMD Athlon X2 Dual-Core (Lion)");
4195 FMQ ( 2,15, 0, 3, dA, "AMD Athlon (Lion)");
4196 FM ( 2,15, 0, 3, "AMD Athlon (unknown type) (Lion/Sable)");
4197 F ( 2,15, "AMD (unknown model)");
4198 FMS ( 3,15, 0, 0, 0, "AMD Athlon (unknown type) (Llano LN-A0)"); // sandpile.org
4199 FMS ( 3,15, 0, 0, 1, "AMD Athlon (unknown type) (Llano LN-A1)"); // sandpile.org
4200 FMSQ( 3,15, 0, 1, 0, dS, "AMD Sempron Dual-Core (Llano LN-B0)");
4201 FMSQ( 3,15, 0, 1, 0, dA, "AMD Athlon II Dual-Core (Llano LN-B0)");
4202 FMSQ( 3,15, 0, 1, 0, Sa, "AMD A-Series (Llano LN-B0)");
4203 FMSQ( 3,15, 0, 1, 0, Se, "AMD E2-Series (Llano LN-B0)");
4204 FMS ( 3,15, 0, 1, 0, "AMD Athlon (unknown type) (Llano LN-B0)");
4205 FMQ ( 3,15, 0, 1, dS, "AMD Sempron Dual-Core (Llano)");
4206 FMQ ( 3,15, 0, 1, dA, "AMD Athlon II Dual-Core (Llano)");
4207 FMQ ( 3,15, 0, 1, Sa, "AMD A-Series (Llano)");
4208 FMQ ( 3,15, 0, 1, Se, "AMD E2-Series (Llano)");
4209 FM ( 3,15, 0, 1, "AMD Athlon (unknown type) (Llano)");
4210 FMS ( 3,15, 0, 2, 0, "AMD Athlon (unknown type) (Llano LN-B0)"); // sandpile.org
4211 F ( 3,15, "AMD (unknown model) (Llano)");
4212 FMSQ( 5,15, 0, 1, 0, Sc, "AMD C-Series (Ontario ON-B0)");
4213 FMSQ( 5,15, 0, 1, 0, Se, "AMD E-Series (Zacate ON-B0)");
4214 FMSQ( 5,15, 0, 1, 0, Sg, "AMD G-Series (Ontario/Zacate ON-B0)");
4215 FMSQ( 5,15, 0, 1, 0, Sz, "AMD Z-Series (Desna ON-B0)");
4216 FMS ( 5,15, 0, 1, 0, "AMD (unknown type) (Ontario/Zacate/Desna ON-B0)");
4217 FM ( 5,15, 0, 1, "AMD (unknown type) (Ontario/Zacate/Desna)");
4218 FMSQ( 5,15, 0, 2, 0, Sc, "AMD C-Series (Ontario ON-C0)");
4219 FMSQ( 5,15, 0, 2, 0, Se, "AMD E-Series (Zacate ON-C0)");
4220 FMSQ( 5,15, 0, 2, 0, Sg, "AMD G-Series (Ontario/Zacate ON-C0)");
4221 FMSQ( 5,15, 0, 2, 0, Sz, "AMD Z-Series (Desna ON-C0)");
4222 FMS ( 5,15, 0, 2, 0, "AMD (unknown type) (Ontario/Zacate/Desna ON-C0)");
4223 FM ( 5,15, 0, 2, "AMD (unknown type) (Ontario/Zacate/Desna)");
4224 F ( 5,15, "AMD (unknown model)");
4225 FMS ( 6,15, 0, 0, 0, "AMD (unknown type) (Interlagos/Valencia/Zurich/Zambezi OR-A0)"); // sandpile.org
4226 FMS ( 6,15, 0, 0, 1, "AMD (unknown type) (Interlagos/Valencia/Zurich/Zambezi OR-A1)"); // sandpile.org
4227 FMS ( 6,15, 0, 1, 0, "AMD (unknown type) (Interlagos/Valencia/Zurich/Zambezi OR-B0)"); // sandpile.org
4228 FMS ( 6,15, 0, 1, 1, "AMD (unknown type) (Interlagos/Valencia/Zurich/Zambezi OR-B1)"); // sandpile.org
4229 FMSQ( 6,15, 0, 1, 2, sO, "AMD Opteron 6200 (Interlagos OR-B2) / Opteron 4200 (Valencia OR-B2) / Opteron 3200 (Zurich OR-B2)");
4230 FMSQ( 6,15, 0, 1, 2, df, "AMD FX-Series (Zambezi OR-B2)");
4231 FMS ( 6,15, 0, 1, 2, "AMD (unknown type) (Interlagos/Valencia/Zurich/Zambezi OR-B2)");
4232 FMQ ( 6,15, 0, 1, sO, "AMD Opteron 6200 (Interlagos) / Opteron 4200 (Valencia) / Opteron 3200 (Zurich)");
4233 FMQ ( 6,15, 0, 1, df, "AMD FX-Series (Zambezi)");
4234 FM ( 6,15, 0, 1, "AMD (unknown type) (Interlagos/Valencia/Zurich/Zambezi)");
4235 FMSQ( 6,15, 0, 2, 0, sO, "AMD Opteron 6300 (Abu Dhabi OR-C0) / Opteron 4300 (Seoul OR-C0) / Opteron 3300 (Delhi OR-C0)");
4236 FMSQ( 6,15, 0, 2, 0, df, "AMD FX-Series (Vishera OR-C0)");
4237 FMS ( 6,15, 0, 2, 0, "AMD (unknown type) (Abu Dhabi/Seoul/Delhi/Vishera OR-C0)");
4238 FMQ ( 6,15, 0, 2, sO, "AMD Opteron 6300 (Abu Dhabi) / Opteron 4300 (Seoul) / Opteron 3300 (Delhi)");
4239 FMQ ( 6,15, 0, 2, df, "AMD FX-Series (Vishera)");
4240 FM ( 6,15, 0, 2, "AMD (unknown type) (Abu Dhabi/Seoul/Delhi/Vishera)");
4241 FMSQ( 6,15, 1, 0, 1, Sa, "AMD A-Series (Trinity TN-A1)");
4242 FMSQ( 6,15, 1, 0, 1, Sr, "AMD R-Series (Trinity TN-A1)");
4243 FMSQ( 6,15, 1, 0, 1, dA, "AMD Athlon Dual-Core / Athlon Quad-Core (Trinity TN-A1)");
4244 FMSQ( 6,15, 1, 0, 1, dS, "AMD Sempron Dual-Core (Trinity TN-A1)");
4245 FMSQ( 6,15, 1, 0, 1, dI, "AMD FirePro (Trinity TN-A1)");
4246 FMS ( 6,15, 1, 0, 1, "AMD (unknown type) (Trinity TN-A1)");
4247 FMQ ( 6,15, 1, 0, Sa, "AMD A-Series (Trinity)");
4248 FMQ ( 6,15, 1, 0, Sr, "AMD R-Series (Trinity)");
4249 FMQ ( 6,15, 1, 0, dA, "AMD Athlon Dual-Core / Athlon Quad-Core (Trinity)");
4250 FMQ ( 6,15, 1, 0, dS, "AMD Sempron Dual-Core (Trinity)");
4251 FMQ ( 6,15, 1, 0, dI, "AMD FirePro (Trinity)");
4252 FM ( 6,15, 1, 0, "AMD (unknown type) (Trinity TN-A1)");
4253 FMSQ( 6,15, 1, 3, 1, Sa, "AMD A-Series (Richland RL-A1)");
4254 FMSQ( 6,15, 1, 3, 1, Sr, "AMD R-Series (Richland RL-A1)");
4255 FMSQ( 6,15, 1, 3, 1, dA, "AMD Athlon Dual-Core / Athlon Quad-Core (Richland RL-A1)");
4256 FMSQ( 6,15, 1, 3, 1, dS, "AMD Sempron Dual-Core (Richland RL-A1)");
4257 FMSQ( 6,15, 1, 3, 1, dI, "AMD FirePro (Richland RL-A1)");
4258 FMS ( 6,15, 1, 3, 1, "AMD (unknown type) (Richland RL-A1)");
4259 FMQ ( 6,15, 1, 3, Sa, "AMD A-Series (Richland)");
4260 FMQ ( 6,15, 1, 3, Sr, "AMD R-Series (Richland)");
4261 FMQ ( 6,15, 1, 3, dA, "AMD Athlon Dual-Core / Athlon Quad-Core (Richland)");
4262 FMQ ( 6,15, 1, 3, dS, "AMD Sempron Dual-Core (Richland)");
4263 FMQ ( 6,15, 1, 3, dI, "AMD FirePro (Richland)");
4264 FM ( 6,15, 1, 3, "AMD (unknown type) (Richland)");
4265 FMS ( 6,15, 3, 0, 0, "AMD (unknown type) (Kaveri KV-A0)");
4266 FMSQ( 6,15, 3, 0, 1, Sa, "AMD Elite Performance A-Series (Kaveri KV-A1)");
4267 FMSQ( 6,15, 3, 0, 1, Mr, "AMD Mobile R-Series (Kaveri KV-A1)");
4268 FMSQ( 6,15, 3, 0, 1, sO, "AMD Opteron X1200 / X2200 (Kaveri KV-A1)");
4269 FMSQ( 6,15, 3, 0, 1, Sr, "AMD R-Series (Bald Eagle KV-A1)"); // undocumented, but instlatx64 example
4270 FMS ( 6,15, 3, 0, 1, "AMD (unknown type) (Kaveri KV-A1)");
4271 FMQ ( 6,15, 3, 0, Sa, "AMD Elite Performance A-Series (Kaveri)");
4272 FMQ ( 6,15, 3, 0, Mr, "AMD Mobile R-Series (Kaveri)");
4273 FMQ ( 6,15, 3, 0, sO, "AMD Opteron X1200 / X2200 (Kaveri)");
4274 FM ( 6,15, 3, 0, "AMD (unknown type) (Kaveri)");
4275 FMSQ( 6,15, 3, 8, 1, Sa, "AMD A-Series (Godavari A1)"); // sandpile.org
4276 FMS ( 6,15, 3, 8, 1, "AMD (unknown type) (Godavari A1)"); // sandpile.org
4277 FMQ ( 6,15, 3, 8, Sa, "AMD A-Series (Godavari)");
4278 FM ( 6,15, 3, 8, "AMD (unknown type) (Godavari)");
4279 FMS ( 6,15, 6, 0, 0, "AMD (unknown type) (Carrizo/Toronto CZ-A0)"); // sandpile.org
4280 FMSQ( 6,15, 6, 0, 1, sO, "AMD Opteron (Toronto CZ-A1)"); // undocumented, but instlatx64 sample
4281 FMSQ( 6,15, 6, 0, 1, df, "AMD FX-Series (Carrizo CZ-A1)"); // undocumented, but instlatx64 sample
4282 FMS ( 6,15, 6, 0, 1, "AMD (unknown type) (Carrizo/Toronto CZ-A1)"); // undocumented, but instlatx64 sample
4283 FMQ ( 6,15, 6, 0, sO, "AMD Opteron (Toronto)"); // undocumented, but instlatx64 sample
4284 FMQ ( 6,15, 6, 0, df, "AMD FX-Series (Carrizo)"); // undocumented, but instlatx64 sample
4285 FM ( 6,15, 6, 0, "AMD (unknown type) (Carrizo/Toronto)"); // undocumented, but instlatx64 sample
4286 FMSQ( 6,15, 6, 5, 1, Sa, "AMD A-Series (Carrizo/Bristol Ridge/Stoney Ridge CZ-A1/BR-A1)"); // undocumented, but samples from Alexandros Couloumbis & instlatx64; sandpile.org stepping
4287 FMSQ( 6,15, 6, 5, 1, Se, "AMD E-Series (Stoney Ridge CZ-A1/BR-A1)"); // undocumented; sandpile.org stepping
4288 FMSQ( 6,15, 6, 5, 1, Sg, "AMD G-Series (Brown Falcon/Prairie Falcon CZ-A1/BR-A1)"); // undocumented; sandpile.org stepping
4289 FMSQ( 6,15, 6, 5, 1, Sr, "AMD R-Series (Merlin Falcon CZ-A1/BR-A1)"); // undocumented; sandpile.org stepping
4290 FMS ( 6,15, 6, 5, 1, "AMD (unknown type) (Carrizo/Bristol Ridge/Stoney Ridge/Toronto/Brown Falcon/Merlin Falcon/Prairie Falcon CZ-A1/BR-A1)"); // sandpile.org
4291 FMQ ( 6,15, 6, 5, Sa, "AMD A-Series (Carrizo/Bristol Ridge/Stoney Ridge)"); // undocumented, but samples from Alexandros Couloumbis & instlatx64
4292 FMQ ( 6,15, 6, 5, Se, "AMD E-Series (Stoney Ridge)"); // undocumented
4293 FMQ ( 6,15, 6, 5, Sg, "AMD G-Series (Brown Falcon/Prairie Falcon)"); // undocumented
4294 FMQ ( 6,15, 6, 5, Sr, "AMD R-Series (Merlin Falcon)"); // undocumented
4295 FM ( 6,15, 6, 5, "AMD (unknown type) (Carrizo/Bristol Ridge/Stoney Ridge/Toronto/Brown Falcon/Merlin Falcon/Prairie Falcon)"); // undocumented, but sample from Alexandros Couloumbis
4296 FMSQ( 6,15, 7, 0, 0, Sa, "AMD A-Series (Carrizo/Bristol Ridge/Stoney Ridge ST-A0)");
4297 FMSQ( 6,15, 7, 0, 0, Se, "AMD E-Series (Stoney Ridge ST-A0)");
4298 FMSQ( 6,15, 7, 0, 0, Sg, "AMD G-Series (Brown Falcon/Prairie Falcon ST-A0)");
4299 FMSQ( 6,15, 7, 0, 0, Sr, "AMD R-Series (Merlin Falcon ST-A0)");
4300 FMS ( 6,15, 7, 0, 0, "AMD (unknown type) (Carrizo/Bristol Ridge/Stoney Ridge/Toronto/Brown Falcon/Merlin Falcon/Prairie Falcon ST-A0)");
4301 FMQ ( 6,15, 7, 0, Sa, "AMD A-Series (Carrizo/Bristol Ridge/Stoney Ridge)");
4302 FMQ ( 6,15, 7, 0, Se, "AMD E-Series (Stoney Ridge)");
4303 FMQ ( 6,15, 7, 0, Sg, "AMD G-Series (Brown Falcon/Prairie Falcon)");
4304 FMQ ( 6,15, 7, 0, Sr, "AMD R-Series (Merlin Falcon)");
4305 FM ( 6,15, 7, 0, "AMD (unknown type) (Carrizo/Bristol Ridge/Stoney Ridge/Toronto/Brown Falcon/Merlin Falcon/Prairie Falcon)");
4306 F ( 6,15, "AMD (unknown model)");
4307 FMS ( 7,15, 0, 0, 0, "AMD (unknown type) (Kabini/Temash/Kyoto KB-A0)"); // sandpile.org
4308 FMSQ( 7,15, 0, 0, 1, dA, "AMD Athlon (Kabini KB-A1)");
4309 FMSQ( 7,15, 0, 0, 1, Sa, "AMD A-Series (Kabini/Temash KB-A1)");
4310 FMSQ( 7,15, 0, 0, 1, Se, "AMD E-Series (Kabini KB-A1)");
4311 FMSQ( 7,15, 0, 0, 1, Sg, "AMD G-Series (Kabini KB-A1)");
4312 FMSQ( 7,15, 0, 0, 1, sO, "AMD Opteron X1100/X2100 Series (Kyoto KB-A1)");
4313 FMS ( 7,15, 0, 0, 1, "AMD (unknown type) (Kabini/Temash/Kyoto KB-A1)");
4314 FMQ ( 7,15, 0, 0, dA, "AMD Athlon (Kabini)");
4315 FMQ ( 7,15, 0, 0, Sa, "AMD A-Series (Kabini/Temash)");
4316 FMQ ( 7,15, 0, 0, Se, "AMD E-Series (Kabini)");
4317 FMQ ( 7,15, 0, 0, Sg, "AMD G-Series (Kabini)");
4318 FMQ ( 7,15, 0, 0, sO, "AMD Opteron X1100/X2100 Series (Kyoto)");
4319 FM ( 7,15, 0, 0, "AMD (unknown type) (Kabini/Temash/Kyoto)");
4320 FM ( 7,15, 2, 6, "AMD (unknown type) (Cato)"); // undocumented; instlatx64 sample; engr sample?
4321 // sandpile.org mentions (7,15),(0,4) Jaguar-esque "BV" cores
4322 // (with stepping 1 = A1), but I have no idea of any such code name.
4323 // The AMD docs (53072) omit the CPUID entirely. But if this sticks to the
4324 // recent AMD pattern, these must be (7,15),(3,0).
4325 FMSQ( 7,15, 3, 0, 1, Sa, "AMD A-Series (Beema ML-A1)");
4326 FMSQ( 7,15, 3, 0, 1, Se, "AMD E-Series (Beema ML-A1)");
4327 FMSQ( 7,15, 3, 0, 1, Sg, "AMD G-Series (Steppe Eagle/Crowned Eagle ML-A1)"); // undocumented; instlatx64 sample
4328 FMSQ( 7,15, 3, 0, 1, Ta, "AMD A-Series Micro (Mullins ML-A1)");
4329 FMSQ( 7,15, 3, 0, 1, Te, "AMD E-Series Micro (Mullins ML-A1)");
4330 FMS ( 7,15, 3, 0, 1, "AMD (unknown type) (Beema/Mullins ML-A1)");
4331 FMQ ( 7,15, 3, 0, Sa, "AMD A-Series (Beema)");
4332 FMQ ( 7,15, 3, 0, Se, "AMD E-Series (Beema)");
4333 FMQ ( 7,15, 3, 0, Sg, "AMD E-Series (Steppe Eagle/Crowned Eagle)");
4334 FMQ ( 7,15, 3, 0, Ta, "AMD A-Series Micro (Mullins)");
4335 FMQ ( 7,15, 3, 0, Te, "AMD E-Series Micro (Mullins)");
4336 FM ( 7,15, 3, 0, "AMD (unknown type) (Beema/Mullins/Steppe Eagle/Crowned Eagle)");
4337 // sandpile.org mentions (7,15),(6,0) Puma-esque "NL" cores
4338 // (with stepping 1 = A1), but I have no idea of any such code name.
4339 F ( 7,15, "AMD (unknown model)");
4340 FMS ( 8,15, 0, 0, 1, "AMD (unknown type) (Summit Ridge/Naples ZP-A1)"); // sandpile.org
4341 FMSQ( 8,15, 0, 1, 0, EE, "AMD EPYC (Snowy Owl ZP-B0)");
4342 FMSQ( 8,15, 0, 1, 0, sE, "AMD EPYC (Naples ZP-B0)");
4343 FMSQ( 8,15, 0, 1, 0, dR, "AMD Ryzen (Summit Ridge ZP-B0)");
4344 FMS ( 8,15, 0, 1, 0, "AMD (unknown type) (Summit Ridge/Naples ZP-B0)");
4345 FMSQ( 8,15, 0, 1, 1, EE, "AMD EPYC (Snowy Owl ZP-B1)");
4346 FMSQ( 8,15, 0, 1, 1, sE, "AMD EPYC (Naples ZP-B1)");
4347 FMSQ( 8,15, 0, 1, 1, dR, "AMD Ryzen (Summit Ridge ZP-B1)");
4348 FMS ( 8,15, 0, 1, 1, "AMD (unknown type) (Summit Ridge/Naples ZP-B1)");
4349 FMSQ( 8,15, 0, 1, 2, EE, "AMD EPYC (Snowy Owl ZP-B2)");
4350 FMSQ( 8,15, 0, 1, 2, sE, "AMD EPYC (Naples ZP-B2)");
4351 FMSQ( 8,15, 0, 1, 2, dR, "AMD Ryzen (Summit Ridge ZP-B2)");
4352 FMS ( 8,15, 0, 1, 2, "AMD (unknown type) (Summit Ridge/Naples ZP-B2)");
4353 FMQ ( 8,15, 0, 1, EE, "AMD EPYC (Snowy Owl)");
4354 FMQ ( 8,15, 0, 1, sE, "AMD EPYC (Naples)");
4355 FMQ ( 8,15, 0, 1, dR, "AMD Ryzen (Summit Ridge)");
4356 FM ( 8,15, 0, 1, "AMD (unknown type) (Summit Ridge/Naples)");
4357 FMS ( 8,15, 0, 8, 2, "AMD Ryzen (Pinnacle Ridge PiR-B2)");
4358 FM ( 8,15, 0, 8, "AMD Ryzen (Pinnacle Ridge)");
4359 FMS ( 8,15, 1, 0, 1, "AMD Ryzen (unknown type) (Raven Ridge/Snowy Owl/Great Horned Owl/Banded Kestrel RV-A1)"); // found only on en.wikichip.org & instlatx64 examples; sandpile.org
4360 FMSQ( 8,15, 1, 1, 0, dA, "AMD Athlon Pro 200 (Raven Ridge RV-A1)");
4361 FMSQ( 8,15, 1, 1, 0, ER, "AMD Ryzen Embedded (Great Horned Owl/Banded Kestrel RV-B0)"); // only instlatx64 example; stepping from usual pattern
4362 FMSQ( 8,15, 1, 1, 0, AR, "AMD Ryzen (Raven Ridge RV-B0)"); // found only on en.wikichip.org & instlatx64 examples; stepping from usual pattern
4363 FMS ( 8,15, 1, 1, 0, "AMD Ryzen (unknown type) (Raven Ridge/Snowy Owl/Great Horned Owl/Banded Kestrel RV-B0)"); // found only on en.wikichip.org & instlatx64 examples; stepping from usual pattern
4364 FMQ ( 8,15, 1, 1, dA, "AMD Athlon Pro 200 (Raven Ridge)");
4365 FMQ ( 8,15, 1, 1, ER, "AMD Ryzen Embedded (Great Horned Owl/Banded Kestrel)"); // only instlatx64 example
4366 FMQ ( 8,15, 1, 1, AR, "AMD Ryzen (Raven Ridge)"); // found only on en.wikichip.org & instlatx64 examples
4367 FM ( 8,15, 1, 1, "AMD Ryzen (unknown type) (Raven Ridge/Snowy Owl/Great Horned Owl/Banded Kestrel)"); // found only on en.wikichip.org & instlatx64 examples
4368 FMSQ( 8,15, 1, 8, 1, dA, "AMD Athlon Pro 300 (Picasso A1)"); // only instlatx64 example
4369 FMSQ( 8,15, 1, 8, 1, AR, "AMD Ryzen (Picasso A1)");
4370 FMS ( 8,15, 1, 8, 1, "AMD (unknown type) (Picasso A1)");
4371 FMQ ( 8,15, 1, 8, dA, "AMD Athlon Pro 300 (Picasso)");
4372 FMQ ( 8,15, 1, 8, AR, "AMD Ryzen (Picasso)");
4373 FM ( 8,15, 1, 8, "AMD Ryzen (Picasso)");
4374 FMS ( 8,15, 2, 0, 1, "AMD Ryzen (Dali A1)");
4375 FM ( 8,15, 2, 0, "AMD Ryzen (Dali)");
4376 FMSQ( 8,15, 3, 1, 0, dR, "AMD Ryzen (Castle Peak B0)");
4377 FMQ ( 8,15, 3, 1, dR, "AMD Ryzen (Castle Peak)");
4378 FMSQ( 8,15, 3, 1, 0, sE, "AMD EPYC (Rome B0)");
4379 FMQ ( 8,15, 3, 1, sE, "AMD EPYC (Rome)");
4380 FMS ( 8,15, 3, 1, 0, "AMD Ryzen (Castle Peak B0) / EPYC (Rome B0)");
4381 FM ( 8,15, 3, 1, "AMD Ryzen (Castle Peak) / EPYC (Rome)");
4382 FM ( 8,15, 4, 7, "AMD 4700S Desktop Kit (Oberon)"); // undocumented; instlatx64 sample; engr sample?
4383 FM ( 8,15, 5, 0, "AMD DG02SRTBP4MFA (Fenghuang 15FF)"); // internal model, only instlatx64 example
4384 FMS ( 8,15, 6, 0, 1, "AMD Ryzen (Renoir A1)");
4385 FM ( 8,15, 6, 0, "AMD Ryzen (Renoir)");
4386 FM ( 8,15, 6, 8, "AMD Ryzen (Lucienne)"); // undocumented, but instlatx64 samples
4387 FMS ( 8,15, 7, 1, 0, "AMD Ryzen (Matisse B0)"); // undocumented, but samples from Steven Noonan
4388 FM ( 8,15, 7, 1, "AMD Ryzen (Matisse)"); // undocumented, but samples from Steven Noonan
4389 F ( 8,15, "AMD (unknown model)");
4390 FMS (10,15, 0, 1, 1, "AMD EPYC (Milan B1)");
4391 FM (10,15, 0, 1, "AMD EPYC (Milan)");
4392 FMS (10,15, 2, 1, 0, "AMD Ryzen (Vermeer B0)"); // undocumented, but instlatx64 samples
4393 FMS (10,15, 2, 1, 1, "AMD Ryzen (Vermeer B1)");
4394 FM (10,15, 2, 1, "AMD Ryzen (Vermeer)");
4395 FMS (10,15, 5, 0, 0, "AMD Ryzen (Cezanne A0)"); // undocumented, but instlatx64 samples
4396 FM (10,15, 5, 0, "AMD Ryzen (Cezanne)"); // undocumented, but instlatx64 samples
4397 FMS (10,15, 5, 1, 1, "AMD Ryzen (Cezanne B1)");
4398 FM (10,15, 5, 1, "AMD Ryzen (Cezanne)");
4399 F (10,15, "AMD (unknown model)"); // undocumented, but samples from Steven Noonan
4400 DEFAULT ("unknown");
4401
4402 const char* brand_pre;
4403 const char* brand_post;
4404 char proc[96];
4405 decode_amd_model(stash, &brand_pre, &brand_post, proc);
4406 if (proc[0] != '\0') {
4407 static char buffer[1024];
4408 sprintf(buffer, "%s %s", result, proc);
4409 return buffer;
4410 }
4411
4412 return result;
4413 }
4414
4415 static cstring
decode_synth_cyrix(unsigned int val,const code_stash_t * stash)4416 decode_synth_cyrix(unsigned int val,
4417 const code_stash_t* stash)
4418 {
4419 cstring result = NULL;
4420
4421 START;
4422 FM (0,4, 0,4, "Cyrix MediaGX/GXi");
4423 FM (0,4, 0,9, "Cyrix 5x86");
4424 F (0,4, "Cyrix 5x86 (unknown model)");
4425 FM (0,5, 0,2, "Cyrix M1 6x86");
4426 FM (0,5, 0,3, "Cyrix M1 6x86"); // M1-6
4427 FMQ(0,5, 0,4, cm, "Cyrix MediaGXm");
4428 FM (0,5, 0,4, "NSC Geode GX1/GXLV/GXm");
4429 F (0,5, "Cyrix M1 / MediaGX / NSC Geode (unknown model)");
4430 FM (0,6, 0,0, "Cyrix M2 6x86MX");
4431 FM (0,6, 0,5, "Cyrix M2");
4432 F (0,6, "Cyrix M2 (unknown model)");
4433 DEFAULT ("unknown");
4434
4435 return result;
4436 }
4437
4438 static cstring
decode_synth_via(unsigned int val,const code_stash_t * stash)4439 decode_synth_via(unsigned int val,
4440 const code_stash_t* stash)
4441 {
4442 cstring result = NULL;
4443
4444 START;
4445 FM (0, 5, 0, 4, "VIA WinChip (C6)");
4446 FM (0, 5, 0, 8, "VIA WinChip 2 (C6-2)");
4447 FM (0, 5, 0, 9, "VIA WinChip 3 (C6-3)");
4448 FM (0, 6, 0, 6, "VIA C3 (Samuel C5A)");
4449 FMS (0, 6, 0, 7, 0, "VIA C3 (Samuel 2 C5B) / Eden ESP 4000/5000/6000, .15um");
4450 FMS (0, 6, 0, 7, 1, "VIA C3 (Samuel 2 C5B) / Eden ESP 4000/5000/6000, .15um");
4451 FMS (0, 6, 0, 7, 2, "VIA C3 (Samuel 2 C5B) / Eden ESP 4000/5000/6000, .15um");
4452 FMS (0, 6, 0, 7, 3, "VIA C3 (Samuel 2 C5B) / Eden ESP 4000/5000/6000, .15um");
4453 FMS (0, 6, 0, 7, 4, "VIA C3 (Samuel 2 C5B) / Eden ESP 4000/5000/6000, .15um");
4454 FMS (0, 6, 0, 7, 5, "VIA C3 (Samuel 2 C5B) / Eden ESP 4000/5000/6000, .15um");
4455 FMS (0, 6, 0, 7, 6, "VIA C3 (Samuel 2 C5B) / Eden ESP 4000/5000/6000, .15um");
4456 FMS (0, 6, 0, 7, 7, "VIA C3 (Samuel 2 C5B) / Eden ESP 4000/5000/6000, .15um");
4457 FM (0, 6, 0, 7, "VIA C3 (Ezra C5C), .13um");
4458 FM (0, 6, 0, 8, "VIA C3 (Ezra-T C5N)");
4459 FMS (0, 6, 0, 9, 0, "VIA C3 / Eden ESP 7000/8000/10000 (Nehemiah C5XL)");
4460 FMS (0, 6, 0, 9, 1, "VIA C3 / Eden ESP 7000/8000/10000 (Nehemiah C5XL)");
4461 FMS (0, 6, 0, 9, 2, "VIA C3 / Eden ESP 7000/8000/10000 (Nehemiah C5XL)");
4462 FMS (0, 6, 0, 9, 3, "VIA C3 / Eden ESP 7000/8000/10000 (Nehemiah C5XL)");
4463 FMS (0, 6, 0, 9, 4, "VIA C3 / Eden ESP 7000/8000/10000 (Nehemiah C5XL)");
4464 FMS (0, 6, 0, 9, 5, "VIA C3 / Eden ESP 7000/8000/10000 (Nehemiah C5XL)");
4465 FMS (0, 6, 0, 9, 6, "VIA C3 / Eden ESP 7000/8000/10000 (Nehemiah C5XL)");
4466 FMS (0, 6, 0, 9, 7, "VIA C3 / Eden ESP 7000/8000/10000 (Nehemiah C5XL)");
4467 FM (0, 6, 0, 9, "VIA C3 / C3-M / Eden-N (Antaur C5P)");
4468 // VIA unpublished BIOS Guide for C7-D.
4469 FM (0, 6, 0,10, "VIA C7 / C7-M / C7-D / Eden (Esther C5J Model A)");
4470 // VIA unpublished BIOS Guide for C7-D.
4471 // Brand string can be used to differentiate model D CPUs.
4472 FMQ (0, 6, 0,13, vM, "VIA C7-M (Esther C5J Model D)");
4473 FMQ (0, 6, 0,13, vD, "VIA C7-D (Esther C5J Model D)");
4474 FMQ (0, 6, 0,13, v7, "VIA C7 (Esther C5J Model D)");
4475 FMQ (0, 6, 0,13, vE, "VIA Eden (Esther C5J Model D)");
4476 FM (0, 6, 0,13, "VIA (unknown type) (Esther C5J Model D)");
4477 // VIA unpublished BIOS Guide for Nano, Eden (for steppings 3-14, other than
4478 // Zhaoxin).
4479 //
4480 // Steppings 0-2 for Isaiah come from this post by "redray", circa Apr 2013:
4481 // https://forum.osdev.org/viewtopic.php?f=1&t=26351
4482 // It presents an excerpt from "VIA Nano Processor X2X4 BIOS Guide 2.47".
4483 //
4484 // Die size depends on core, but it's unclear which cores are which:
4485 // Isaiah = 65nm, 40nm
4486 // Isaiah II = 28nm
4487 // ZhangJiang (Zhaoxin) = 28nm ?
4488 FMS (0, 6, 0,15, 0, "VIA Nano 1000/2000 (Isaiah CNA A0)"); // redray; instlatx64 example
4489 FMS (0, 6, 0,15, 1, "VIA Nano 1000/2000 (Isaiah CNA A1)"); // redray; model numbers assumed because of bracketing between 0 & 3
4490 FMS (0, 6, 0,15, 2, "VIA Nano 1000/2000 (Isaiah CNA A2)"); // redray; model numbers assumed because of bracketing between 0 & 3
4491 FMS (0, 6, 0,15, 3, "VIA Nano 1000/2000 (Isaiah CNA A3)");
4492 FMS (0, 6, 0,15, 8, "VIA Nano 3000 (Isaiah CNB A1)");
4493 FMS (0, 6, 0,15, 10, "VIA Nano 3000 (Isaiah CNC A2)");
4494 FMS (0, 6, 0,15, 12, "VIA Nano X2 4000 / QuadCore 4000 (Isaiah CNQ A1)");
4495 FMS (0, 6, 0,15, 13, "VIA Nano X2 4000 / QuadCore 4000 (Isaiah CNQ A2)");
4496 FMSQ(0, 6, 0,15, 14, vZ, "Zhaoxin KaiXian/Kaisheng ZX-C/ZX-C+");
4497 FMS (0, 6, 0,15, 14, "VIA Eden X4 4000 (Isaiah CNR)");
4498 FM (0, 6, 0,15, "VIA Nano / Eden (unknown type) (Isaiah)");
4499 F (0, 6, "VIA C3 / C3-M / C7 / C7-M / Eden / Eden ESP 7000/8000/10000 / Nano (unknown model)");
4500 FM (0, 7, 0,11, "Zhaoxin KaiXian KX-5000 / Kaisheng KH-20000 (WuDaoKou)"); // geekbench.com example
4501 FMQ (0, 7, 3,11, vZ, "Zhaoxin KaiXian KX-6000 / Kaisheng KH-30000 (LuJiaZui)"); // instlatx64 example with CentaurHauls vendor!
4502 DEFAULT ("unknown");
4503
4504 return result;
4505 }
4506
4507 static cstring
decode_synth_umc(unsigned int val)4508 decode_synth_umc(unsigned int val)
4509 {
4510 cstring result = NULL;
4511
4512 START;
4513 FM (0,4, 0,1, "UMC U5D (486DX)");
4514 FMS(0,4, 0,2, 3, "UMC U5S (486SX)");
4515 FM (0,4, 0,2, "UMC U5S (486SX) (unknown stepping)");
4516 DEFAULT ("unknown");
4517
4518 return result;
4519 }
4520
4521 static cstring
decode_synth_nexgen(unsigned int val)4522 decode_synth_nexgen(unsigned int val)
4523 {
4524 cstring result = NULL;
4525
4526 START;
4527 FMS(0,5, 0,0, 4, "NexGen P100");
4528 FMS(0,5, 0,0, 6, "NexGen P120 (E2/C0)");
4529 DEFAULT ("unknown");
4530
4531 return result;
4532 }
4533
4534 static cstring
decode_synth_rise(unsigned int val)4535 decode_synth_rise(unsigned int val)
4536 {
4537 cstring result = NULL;
4538
4539 START;
4540 FM (0,5, 0,0, "Rise mP6 iDragon, .25u");
4541 FM (0,5, 0,2, "Rise mP6 iDragon, .18u");
4542 FM (0,5, 0,8, "Rise mP6 iDragon II, .25u");
4543 FM (0,5, 0,9, "Rise mP6 iDragon II, .18u");
4544 DEFAULT ("unknown");
4545
4546 return result;
4547 }
4548
4549 static cstring
decode_synth_transmeta(unsigned int val,const code_stash_t * stash)4550 decode_synth_transmeta(unsigned int val,
4551 const code_stash_t* stash)
4552 {
4553 cstring result = NULL;
4554
4555 /* TODO: Add code-based detail for Transmeta Crusoe TM5700/TM5900 */
4556 /* TODO: Add code-based detail for Transmeta Efficeon */
4557 START;
4558 FMSQ(0, 5, 0,4, 2, t2, "Transmeta Crusoe TM3200");
4559 FMS (0, 5, 0,4, 2, "Transmeta Crusoe TM3x00 (unknown model)");
4560 FMSQ(0, 5, 0,4, 3, t4, "Transmeta Crusoe TM5400");
4561 FMSQ(0, 5, 0,4, 3, t5, "Transmeta Crusoe TM5500 / Crusoe SE TM55E");
4562 FMSQ(0, 5, 0,4, 3, t6, "Transmeta Crusoe TM5600");
4563 FMSQ(0, 5, 0,4, 3, t8, "Transmeta Crusoe TM5800 / Crusoe SE TM58E");
4564 FMS (0, 5, 0,4, 3, "Transmeta Crusoe TM5x00 (unknown model)");
4565 FM (0, 5, 0,4, "Transmeta Crusoe");
4566 F (0, 5, "Transmeta Crusoe (unknown model)");
4567 FM (0,15, 0,2, "Transmeta Efficeon TM8x00");
4568 FM (0,15, 0,3, "Transmeta Efficeon TM8x00");
4569 F (0,15, "Transmeta Efficeon (unknown model)");
4570 DEFAULT ("unknown");
4571
4572 return result;
4573 }
4574
4575 static cstring
decode_synth_sis(unsigned int val)4576 decode_synth_sis(unsigned int val)
4577 {
4578 cstring result = NULL;
4579
4580 START;
4581 FM (0, 5, 0, 0, "SiS 55x");
4582 DEFAULT ("unknown");
4583
4584 return result;
4585 }
4586
4587 static cstring
decode_synth_nsc(unsigned int val)4588 decode_synth_nsc(unsigned int val)
4589 {
4590 cstring result = NULL;
4591
4592 START;
4593 FM (0, 5, 0, 4, "NSC Geode GX1/GXLV/GXm");
4594 FM (0, 5, 0, 5, "NSC Geode GX2");
4595 FM (0, 5, 0,10, "NSC Geode LX"); // sandpile.org
4596 F (0, 5, "NSC Geode (unknown model)");
4597 DEFAULT ("unknown");
4598
4599 return result;
4600 }
4601
4602 static cstring
decode_synth_vortex(unsigned int val)4603 decode_synth_vortex(unsigned int val)
4604 {
4605 cstring result = NULL;
4606
4607 START;
4608 FM (0, 5, 0, 2, "Vortex86DX");
4609 FM (0, 5, 0, 8, "Vortex86MX");
4610 FM (0, 6, 0, 0, "Vortex86EX2"); // undocumented; /proc/cpuinfo seen in wild
4611 FM (0, 6, 0, 1, "Vortex86DX3"); // undocumented; only instlatx64 example
4612 DEFAULT ("unknown");
4613
4614 return result;
4615 }
4616
4617 static cstring
decode_synth_rdc(unsigned int val)4618 decode_synth_rdc(unsigned int val)
4619 {
4620 cstring result = NULL;
4621
4622 START;
4623 FM (0, 5, 0, 8, "RDC IAD 100");
4624 DEFAULT ("unknown");
4625
4626 return result;
4627 }
4628
4629 static cstring
decode_synth_hygon(unsigned int val)4630 decode_synth_hygon(unsigned int val)
4631 {
4632 cstring result = NULL;
4633
4634 START;
4635 FMS (9,15, 0, 0, 1, "Hygon Dhyana (A1)");
4636 FMS (9,15, 0, 0, 2, "Hygon Dhyana (A2)");
4637 DEFAULT ("unknown");
4638
4639 return result;
4640 }
4641
4642 static cstring
decode_synth_zhaoxin(unsigned int val)4643 decode_synth_zhaoxin(unsigned int val)
4644 {
4645 cstring result = NULL;
4646
4647 START;
4648 FM (0, 7, 1,11, "Zhaoxin KaiXian KX-5000 / Kaisheng KH-20000 (WuDaoKou)");
4649 FM (0, 7, 1,15, "Zhaoxin KaiXian ZX-D (WuDaoKou)"); // geekbench.com example (steppings 12 & 14)
4650 FM (0, 7, 3,11, "Zhaoxin KaiXian KX-6000 / Kaisheng KH-30000 (LuJiaZui)"); // /proc/cpuinfo screenshot: KX-6840@3000MHz (stepping 0)
4651 DEFAULT ("unknown");
4652
4653 return result;
4654 }
4655
4656 static cstring
decode_x_synth_amd(unsigned int val)4657 decode_x_synth_amd(unsigned int val)
4658 {
4659 cstring result;
4660
4661 START;
4662 FM (0, 5, 0, 0, "AMD SSA5 (PR75, PR90, PR100)");
4663 FM (0, 5, 0, 1, "AMD 5k86 (PR120, PR133)");
4664 FM (0, 5, 0, 2, "AMD 5k86 (PR166)");
4665 FM (0, 5, 0, 3, "AMD 5k86 (PR200)");
4666 F (0, 5, "AMD 5k86 (unknown model)");
4667 FM (0, 6, 0, 6, "AMD K6, .30um");
4668 FM (0, 6, 0, 7, "AMD K6 (Little Foot), .25um");
4669 FMS (0, 6, 0, 8, 0, "AMD K6-2 (Chomper A)");
4670 FMS (0, 6, 0, 8, 12, "AMD K6-2 (Chomper A)");
4671 FM (0, 6, 0, 8, "AMD K6-2 (Chomper)");
4672 FMS (0, 6, 0, 9, 1, "AMD K6-III (Sharptooth B)");
4673 FM (0, 6, 0, 9, "AMD K6-III (Sharptooth)");
4674 FM (0, 6, 0,13, "AMD K6-2+, K6-III+");
4675 F (0, 6, "AMD K6 (unknown model)");
4676 FM (0, 7, 0, 1, "AMD Athlon, .25um");
4677 FM (0, 7, 0, 2, "AMD Athlon (K75 / Pluto / Orion), .18um");
4678 FMS (0, 7, 0, 3, 0, "AMD Duron / mobile Duron (Spitfire A0)");
4679 FMS (0, 7, 0, 3, 1, "AMD Duron / mobile Duron (Spitfire A2)");
4680 FM (0, 7, 0, 3, "AMD Duron / mobile Duron (Spitfire)");
4681 FMS (0, 7, 0, 4, 2, "AMD Athlon (Thunderbird A4-A7)");
4682 FMS (0, 7, 0, 4, 4, "AMD Athlon (Thunderbird A9)");
4683 FM (0, 7, 0, 4, "AMD Athlon (Thunderbird)");
4684 FMS (0, 7, 0, 6, 0, "AMD Athlon / Athlon MP mobile Athlon 4 / mobile Duron (Palomino A0)");
4685 FMS (0, 7, 0, 6, 1, "AMD Athlon / Athlon MP / Duron / mobile Athlon / mobile Duron (Palomino A2)");
4686 FMS (0, 7, 0, 6, 2, "AMD Athlon MP / Athlon XP / Duron / Duron MP / mobile Athlon / mobile Duron (Palomino A5)");
4687 FM (0, 7, 0, 6, "AMD Athlon / Athlon MP / Athlon XP / Duron / Duron MP / mobile Athlon / mobile Duron (Palomino)");
4688 FMS (0, 7, 0, 7, 0, "AMD Duron / Duron MP / mobile Duron (Morgan A0)");
4689 FMS (0, 7, 0, 7, 1, "AMD Duron / Duron MP / mobile Duron (Morgan A1)");
4690 FM (0, 7, 0, 7, "AMD Duron / Duron MP / mobile Duron (Morgan)");
4691 FMS (0, 7, 0, 8, 0, "AMD Athlon XP / Athlon MP / Sempron / Duron / Duron MP (Thoroughbred A0)");
4692 FMS (0, 7, 0, 8, 1, "AMD Athlon XP / Athlon MP / Sempron / Duron / Duron MP (Thoroughbred B0)");
4693 FM (0, 7, 0, 8, "AMD Athlon XP / Athlon MP / Sempron / Duron / Duron MP (Thoroughbred)");
4694 FMS (0, 7, 0,10, 0, "AMD Athlon XP / Athlon MP / Sempron / mobile Athlon XP-M / mobile Athlon XP-M (LV) (Barton A2)");
4695 FM (0, 7, 0,10, "AMD Athlon XP / Athlon MP / Sempron / mobile Athlon XP-M / mobile Athlon XP-M (LV) (Barton)");
4696 F (0, 7, "AMD Athlon XP / Athlon MP / Sempron / Duron / Duron MP / mobile Athlon / mobile Athlon XP-M / mobile Athlon XP-M (LV) / mobile Duron (unknown model)");
4697 FALLBACK({ result = append_uarch(decode_synth_amd(val, NULL), val, VENDOR_AMD, NULL); })
4698
4699 return result;
4700 }
4701
4702 static void
print_x_synth_amd(unsigned int val)4703 print_x_synth_amd(unsigned int val)
4704 {
4705 ccstring synth = decode_x_synth_amd(val);
4706
4707 printf(" (simple synth) = ");
4708 if (synth != NULL) {
4709 printf("%s", synth);
4710 }
4711 printf("\n");
4712 }
4713
4714 static cstring
decode_x_synth_hygon(unsigned int val)4715 decode_x_synth_hygon(unsigned int val)
4716 {
4717 cstring result;
4718
4719 START;
4720 FALLBACK({ result = append_uarch(decode_synth_hygon(val), val, VENDOR_HYGON, NULL); })
4721
4722 return result;
4723 }
4724
4725 static void
print_x_synth_hygon(unsigned int val)4726 print_x_synth_hygon(unsigned int val)
4727 {
4728 ccstring synth = decode_x_synth_hygon(val);
4729
4730 printf(" (simple synth) = ");
4731 if (synth != NULL) {
4732 printf("%s", synth);
4733 }
4734 printf("\n");
4735 }
4736
4737 static cstring
decode_x_synth_via(unsigned int val)4738 decode_x_synth_via(unsigned int val)
4739 {
4740 cstring result;
4741
4742 START;
4743 FM (0,6, 0,6, "VIA C3 (WinChip C5A)");
4744 FM (0,6, 0,6, "VIA C3 (WinChip C5A)");
4745 FMS(0,6, 0,7, 0, "VIA C3 (WinChip C5B)");
4746 FMS(0,6, 0,7, 1, "VIA C3 (WinChip C5B)");
4747 FMS(0,6, 0,7, 2, "VIA C3 (WinChip C5B)");
4748 FMS(0,6, 0,7, 3, "VIA C3 (WinChip C5B)");
4749 FMS(0,6, 0,7, 4, "VIA C3 (WinChip C5B)");
4750 FMS(0,6, 0,7, 5, "VIA C3 (WinChip C5B)");
4751 FMS(0,6, 0,7, 6, "VIA C3 (WinChip C5B)");
4752 FMS(0,6, 0,7, 7, "VIA C3 (WinChip C5B)");
4753 FM (0,6, 0,7, "VIA C3 (WinChip C5C)");
4754 FM (0,6, 0,8, "VIA C3 (WinChip C5N)");
4755 FM (0,6, 0,9, "VIA C3 (WinChip C5XL)");
4756 F (0,6, "VIA C3 (unknown model)");
4757 DEFAULT ("unknown");
4758
4759 return append_uarch(result, val, VENDOR_VIA, NULL);
4760 }
4761
4762 static void
print_x_synth_via(unsigned int val)4763 print_x_synth_via(unsigned int val)
4764 {
4765 ccstring synth = decode_x_synth_via(val);
4766
4767 printf(" (simple synth) = ");
4768 if (synth != NULL) {
4769 printf("%s", synth);
4770 }
4771 printf("\n");
4772 }
4773
4774 #undef ACT
4775
4776 static cstring
decode_synth(unsigned int val_eax,vendor_t vendor,const code_stash_t * stash)4777 decode_synth(unsigned int val_eax,
4778 vendor_t vendor,
4779 const code_stash_t* stash)
4780 {
4781 cstring synth = NULL;
4782
4783 switch (vendor) {
4784 case VENDOR_INTEL:
4785 synth = decode_synth_intel(val_eax, stash);
4786 break;
4787 case VENDOR_AMD:
4788 synth = decode_synth_amd(val_eax, stash);
4789 break;
4790 case VENDOR_CYRIX:
4791 synth = decode_synth_cyrix(val_eax, stash);
4792 break;
4793 case VENDOR_VIA:
4794 synth = decode_synth_via(val_eax, stash);
4795 break;
4796 case VENDOR_TRANSMETA:
4797 synth = decode_synth_transmeta(val_eax, stash);
4798 break;
4799 case VENDOR_UMC:
4800 synth = decode_synth_umc(val_eax);
4801 break;
4802 case VENDOR_NEXGEN:
4803 synth = decode_synth_nexgen(val_eax);
4804 break;
4805 case VENDOR_RISE:
4806 synth = decode_synth_rise(val_eax);
4807 break;
4808 case VENDOR_SIS:
4809 synth = decode_synth_sis(val_eax);
4810 break;
4811 case VENDOR_NSC:
4812 synth = decode_synth_nsc(val_eax);
4813 break;
4814 case VENDOR_VORTEX:
4815 synth = decode_synth_vortex(val_eax);
4816 break;
4817 case VENDOR_RDC:
4818 synth = decode_synth_rdc(val_eax);
4819 break;
4820 case VENDOR_HYGON:
4821 synth = decode_synth_hygon(val_eax);
4822 break;
4823 case VENDOR_ZHAOXIN:
4824 synth = decode_synth_zhaoxin(val_eax);
4825 break;
4826 case VENDOR_UNKNOWN:
4827 /* DO NOTHING */
4828 break;
4829 }
4830
4831 return append_uarch(synth, val_eax, vendor, stash);
4832 }
4833
4834 static void
print_synth_simple(unsigned int val_eax,vendor_t vendor)4835 print_synth_simple(unsigned int val_eax,
4836 vendor_t vendor)
4837 {
4838 ccstring synth = decode_synth(val_eax, vendor, NULL);
4839 if (synth != NULL) {
4840 printf(" (simple synth) = %s", synth);
4841 }
4842 printf("\n");
4843 }
4844
4845 static void
print_synth(const code_stash_t * stash)4846 print_synth(const code_stash_t* stash)
4847 {
4848 ccstring synth = decode_synth(stash->val_1_eax, stash->vendor, stash);
4849 if (synth != NULL) {
4850 printf(" (synth) = %s\n", synth);
4851 }
4852 }
4853
4854 #define Synth_Family(value) \
4855 (BIT_EXTRACT_LE(value, 20, 28) \
4856 + BIT_EXTRACT_LE(value, 8, 12))
4857 #define Synth_Model(value) \
4858 ((BIT_EXTRACT_LE(value, 16, 20) << 4) \
4859 + BIT_EXTRACT_LE(value, 4, 8))
4860
4861 #define GET_ApicIdCoreIdSize(val_80000008_ecx) \
4862 (BIT_EXTRACT_LE((val_80000008_ecx), 0, 4))
4863 #define GET_LogicalProcessorCount(val_1_ebx) \
4864 (BIT_EXTRACT_LE((val_1_ebx), 16, 24))
4865 #define IS_HTT(val_1_edx) \
4866 (BIT_EXTRACT_LE((val_1_edx), 28, 29))
4867 #define IS_CmpLegacy(val_80000001_ecx) \
4868 (BIT_EXTRACT_LE((val_80000001_ecx), 1, 2))
4869 #define GET_NC_INTEL(val_4_eax) \
4870 (BIT_EXTRACT_LE((val_4_eax), 26, 32))
4871 #define GET_NC_AMD(val_80000008_ecx) \
4872 (BIT_EXTRACT_LE((val_80000008_ecx), 0, 8))
4873 #define GET_X2APIC_PROCESSORS(val_b_ebx) \
4874 (BIT_EXTRACT_LE((val_b_ebx), 0, 16))
4875 #define GET_V2_TOPO_LEVEL(val_1f_ecx) \
4876 (BIT_EXTRACT_LE((val_1f_ecx), 8, 16))
4877 #define GET_V2_TOPO_PROCESSORS(val_1f_ebx) \
4878 (BIT_EXTRACT_LE((val_1f_ebx), 0, 16))
4879 #define GET_CoresPerComputeUnit_AMD(val_8000001e_ebx) \
4880 (BIT_EXTRACT_LE((val_8000001e_ebx), 8, 16))
4881
4882 #define V2_TOPO_SMT 1
4883 #define V2_TOPO_CORE 2
4884
decode_mp_synth(code_stash_t * stash)4885 static void decode_mp_synth(code_stash_t* stash)
4886 {
4887 switch (stash->vendor) {
4888 case VENDOR_INTEL:
4889 /*
4890 ** Logic derived from information in:
4891 ** Detecting Multi-Core Processor Topology in an IA-32 Platform
4892 ** by Khang Nguyen and Shihjong Kuo
4893 ** and:
4894 ** Intel 64 Architecture Processor Topology Enumeration (Whitepaper)
4895 ** by Shih Kuo
4896 ** Extension to the 0x1f leaf was obvious.
4897 */
4898 if (stash->saw_1f) {
4899 stash->mp.method = "Intel leaf 0x1f";
4900 unsigned int try;
4901 for (try = 0; try < LENGTH(stash->val_1f_ecx); try++) {
4902 if (GET_V2_TOPO_LEVEL(stash->val_1f_ecx[try]) == V2_TOPO_SMT) {
4903 stash->mp.hyperthreads
4904 = GET_V2_TOPO_PROCESSORS(stash->val_1f_ebx[try]);
4905 } else if (GET_V2_TOPO_LEVEL(stash->val_1f_ecx[try]) == V2_TOPO_CORE) {
4906 stash->mp.cores = GET_V2_TOPO_PROCESSORS(stash->val_1f_ebx[try]);
4907 }
4908 }
4909 } else if (stash->saw_b) {
4910 unsigned int ht = GET_X2APIC_PROCESSORS(stash->val_b_ebx[0]);
4911 unsigned int tc = GET_X2APIC_PROCESSORS(stash->val_b_ebx[1]);
4912 stash->mp.method = "Intel leaf 0xb";
4913 if (ht == 0) {
4914 ht = 1;
4915 }
4916 stash->mp.cores = tc / ht;
4917 stash->mp.hyperthreads = ht;
4918 } else if (stash->saw_4) {
4919 unsigned int tc = GET_LogicalProcessorCount(stash->val_1_ebx);
4920 unsigned int c;
4921 if ((stash->val_4_eax & 0x1f) != 0) {
4922 c = GET_NC_INTEL(stash->val_4_eax) + 1;
4923 stash->mp.method = "Intel leaf 1/4";
4924 } else {
4925 /* Workaround for older 'cpuid -r' dumps with incomplete 4 data */
4926 c = tc / 2;
4927 stash->mp.method = "Intel leaf 1/4 (zero fallback)";
4928 }
4929 stash->mp.cores = c;
4930 stash->mp.hyperthreads = tc / c;
4931 } else {
4932 stash->mp.method = "Intel leaf 1";
4933 stash->mp.cores = 1;
4934 if (IS_HTT(stash->val_1_edx)) {
4935 unsigned int tc = GET_LogicalProcessorCount(stash->val_1_ebx);
4936 stash->mp.hyperthreads = (tc >= 2 ? tc : 2);
4937 } else {
4938 stash->mp.hyperthreads = 1;
4939 }
4940 }
4941 break;
4942 case VENDOR_AMD:
4943 case VENDOR_HYGON:
4944 /*
4945 ** Logic from:
4946 ** AMD CPUID Specification (25481 Rev. 2.16),
4947 ** 3. LogicalProcessorCount, CmpLegacy, HTT, and NC
4948 ** AMD CPUID Specification (25481 Rev. 2.28),
4949 ** 3. Multiple Core Calculation
4950 */
4951 if (IS_HTT(stash->val_1_edx)) {
4952 unsigned int tc = GET_LogicalProcessorCount(stash->val_1_ebx);
4953 unsigned int c;
4954 if (GET_ApicIdCoreIdSize(stash->val_80000008_ecx) != 0) {
4955 unsigned int size = GET_ApicIdCoreIdSize(stash->val_80000008_ecx);
4956 unsigned int mask = (1 << size) - 1;
4957 c = (GET_NC_AMD(stash->val_80000008_ecx) & mask) + 1;
4958 } else {
4959 c = GET_NC_AMD(stash->val_80000008_ecx) + 1;
4960 }
4961 if ((tc == c) == IS_CmpLegacy(stash->val_80000001_ecx)) {
4962 stash->mp.method = (stash->vendor == VENDOR_AMD ? "AMD"
4963 : "Hygon");
4964 if (c > 1) {
4965 stash->mp.cores = c;
4966 stash->mp.hyperthreads = tc / c;
4967 } else {
4968 stash->mp.cores = 1;
4969 stash->mp.hyperthreads = (tc >= 2 ? tc : 2);
4970 }
4971 } else {
4972 /*
4973 ** Rev 2.28 leaves out mention that this case is nonsensical, but
4974 ** I'm leaving it in here as an "unknown" case.
4975 */
4976 }
4977 } else {
4978 stash->mp.method = (stash->vendor == VENDOR_AMD ? "AMD" : "Hygon");
4979 stash->mp.cores = 1;
4980 stash->mp.hyperthreads = 1;
4981 }
4982 break;
4983 default:
4984 if (!IS_HTT(stash->val_1_edx)) {
4985 stash->mp.method = "Generic leaf 1 no multi-threading";
4986 stash->mp.cores = 1;
4987 stash->mp.hyperthreads = 1;
4988 }
4989 break;
4990 }
4991 }
4992
print_mp_synth(const struct mp * mp)4993 static void print_mp_synth(const struct mp* mp)
4994 {
4995 printf(" (multi-processing synth) = ");
4996 if (mp->method == NULL) {
4997 printf("?");
4998 } else if (mp->cores > 1) {
4999 if (mp->hyperthreads > 1) {
5000 printf("multi-core (c=%u), hyper-threaded (t=%u)",
5001 mp->cores, mp->hyperthreads);
5002 } else {
5003 printf("multi-core (c=%u)", mp->cores);
5004 }
5005 } else if (mp->hyperthreads > 1) {
5006 printf("hyper-threaded (t=%u)", mp->hyperthreads);
5007 } else {
5008 printf("none");
5009 }
5010 printf("\n");
5011
5012 printf(" (multi-processing method) = %s\n", mp->method);
5013 }
5014
bits_needed(unsigned long v)5015 static int bits_needed(unsigned long v)
5016 {
5017 #if __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ >= 30400
5018 return v <= 1 ? 0 : (8 * sizeof(long) - __builtin_clzl(v-1));
5019 #else
5020 if (v == 0) return 0;
5021 int result;
5022 #if defined(__x86_64) && !defined(__ILP32__)
5023 asm("movq %[v],%%rax;"
5024 "movq $0,%%rcx;"
5025 "movl $0,%[result];"
5026 "decq %%rax;"
5027 "bsr %%ax,%%cx;"
5028 "jz 1f;"
5029 "incq %%rcx;"
5030 "movl %%ecx,%[result];"
5031 "1:"
5032 : [result] "=rm" (result)
5033 : [v] "irm" (v)
5034 : "eax", "ecx");
5035 #else
5036 asm("movl %[v],%%eax;"
5037 "movl $0,%%ecx;"
5038 "movl $0,%[result];"
5039 "decl %%eax;"
5040 "bsr %%ax,%%cx;"
5041 "jz 1f;"
5042 "incl %%ecx;"
5043 "movl %%ecx,%[result];"
5044 "1:"
5045 : [result] "=rm" (result)
5046 : [v] "irm" (v)
5047 : "eax", "ecx");
5048 #endif
5049 return result;
5050 #endif
5051 }
5052
5053 #define GET_X2APIC_WIDTH(val_b_eax) \
5054 (BIT_EXTRACT_LE((val_b_eax), 0, 5))
5055 #define GET_V2_TOPO_WIDTH(val_1f_eax) \
5056 (BIT_EXTRACT_LE((val_1f_eax), 0, 5))
5057
print_apic_synth(code_stash_t * stash)5058 static void print_apic_synth (code_stash_t* stash)
5059 {
5060 unsigned int smt_width = 0;
5061 unsigned int core_width = 0;
5062 unsigned int cu_width = 0;
5063
5064 switch (stash->vendor) {
5065 case VENDOR_INTEL:
5066 /*
5067 ** Logic derived from information in:
5068 ** Detecting Multi-Core Processor Topology in an IA-32 Platform
5069 ** by Khang Nguyen and Shihjong Kuo
5070 ** and:
5071 ** Intel 64 Architecture Processor Topology Enumeration (Whitepaper)
5072 ** by Shih Kuo
5073 ** Extension to the 0x1f leaf was obvious.
5074 */
5075 if (stash->saw_1f) {
5076 unsigned int try;
5077 for (try = 0; try < LENGTH(stash->val_1f_ecx); try++) {
5078 unsigned int level = GET_V2_TOPO_LEVEL(stash->val_1f_ecx[try]);
5079 if (level == V2_TOPO_SMT) {
5080 smt_width = GET_V2_TOPO_WIDTH(stash->val_1f_eax[try]);
5081 } else if (level == V2_TOPO_CORE) {
5082 core_width = GET_V2_TOPO_WIDTH(stash->val_1f_eax[try]);
5083 }
5084 }
5085 } else if (stash->saw_b) {
5086 smt_width = GET_X2APIC_WIDTH(stash->val_b_eax[0]);
5087 core_width = GET_X2APIC_WIDTH(stash->val_b_eax[1]);
5088 } else if (stash->saw_4 && (stash->val_4_eax & 0x1f) != 0) {
5089 unsigned int core_count = GET_NC_INTEL(stash->val_4_eax) + 1;
5090 unsigned int smt_count = (GET_LogicalProcessorCount(stash->val_1_ebx)
5091 / core_count);
5092 smt_width = bits_needed(smt_count);
5093 core_width = bits_needed(core_count);
5094 } else {
5095 return;
5096 }
5097 break;
5098 case VENDOR_AMD:
5099 /*
5100 ** Logic deduced by analogy: As Intel's decode_mp_synth code is to AMD's
5101 ** decode_mp_synth code, so is Intel's APIC synth code to this.
5102 **
5103 ** For Families 10h-16h, the CU (CMT "compute unit") logic was a
5104 ** logical extension.
5105 **
5106 ** For Families 17h and later, terminology changed to reflect that
5107 ** the Family 10h-16h cores had been sharing resources significantly,
5108 ** similarly to (but less drastically than) SMT threads:
5109 ** Family 10h-16h => Family 17h
5110 ** ----------------------------
5111 ** CU => core
5112 ** core => thread
5113 ** And leaf 0x8000001e/ebx is used for smt_count, because 1/ebx is
5114 ** unreliable.
5115 */
5116 if (IS_HTT(stash->val_1_edx)
5117 && GET_ApicIdCoreIdSize(stash->val_80000008_ecx) != 0) {
5118 unsigned int size = GET_ApicIdCoreIdSize(stash->val_80000008_ecx);
5119 unsigned int mask = (1 << size) - 1;
5120 unsigned int core_count = ((GET_NC_AMD(stash->val_80000008_ecx) & mask)
5121 + 1);
5122 unsigned int smt_count = (GET_LogicalProcessorCount(stash->val_1_ebx)
5123 / core_count);
5124 unsigned int cu_count = 1;
5125 if (GET_CoresPerComputeUnit_AMD(stash->val_8000001e_ebx) != 0) {
5126 if (Synth_Family(stash->val_80000001_eax) > 0x16) {
5127 unsigned int threads_per_core
5128 = GET_CoresPerComputeUnit_AMD(stash->val_8000001e_ebx) + 1;
5129 smt_count = threads_per_core;
5130 core_count /= threads_per_core;
5131 } else {
5132 unsigned int cores_per_cu
5133 = GET_CoresPerComputeUnit_AMD(stash->val_8000001e_ebx) + 1;
5134 cu_count = (core_count / cores_per_cu);
5135 core_count = cores_per_cu;
5136 }
5137 }
5138 smt_width = bits_needed(smt_count);
5139 core_width = bits_needed(core_count);
5140 cu_width = bits_needed(cu_count);
5141 } else {
5142 return;
5143 }
5144 break;
5145 default:
5146 return;
5147 }
5148
5149 // Possibly this should be expanded with Intel leaf 1f's module, tile, and
5150 // die levels. They could be made into hidden architectural levels unless
5151 // actually present, much like the CU level.
5152
5153 printf(" (APIC widths synth):");
5154 if (cu_width != 0) {
5155 printf(" CU_width=%u", cu_width);
5156 }
5157 printf(" CORE_width=%u", core_width);
5158 printf(" SMT_width=%u", smt_width);
5159 printf("\n");
5160
5161 unsigned int smt_off = 24;
5162 unsigned int smt_tail = smt_off + smt_width;
5163 unsigned int core_off = smt_tail;
5164 unsigned int core_tail = core_off + core_width;
5165 unsigned int cu_off = core_tail;
5166 unsigned int cu_tail = cu_off + cu_width;
5167 unsigned int pkg_off = cu_tail;
5168 unsigned int pkg_tail = 32;
5169
5170 printf(" (APIC synth):");
5171 printf(" PKG_ID=%d", (pkg_off < pkg_tail
5172 ? BIT_EXTRACT_LE(stash->val_1_ebx, pkg_off, pkg_tail)
5173 : 0));
5174 if (cu_width != 0) {
5175 printf(" CU_ID=%d", BIT_EXTRACT_LE(stash->val_1_ebx, cu_off, cu_tail));
5176 }
5177 printf(" CORE_ID=%d", BIT_EXTRACT_LE(stash->val_1_ebx, core_off, core_tail));
5178 printf(" SMT_ID=%d", BIT_EXTRACT_LE(stash->val_1_ebx, smt_off, smt_tail));
5179 printf("\n");
5180 }
5181
print_instr_synth_amd(code_stash_t * stash)5182 static void print_instr_synth_amd (code_stash_t* stash)
5183 {
5184 boolean cmpxchg8b = (BIT_EXTRACT_LE(stash->val_80000001_edx, 8, 9)
5185 || BIT_EXTRACT_LE(stash->val_1_edx, 8, 9));
5186 boolean cond = (BIT_EXTRACT_LE(stash->val_80000001_edx, 15, 16)
5187 || BIT_EXTRACT_LE(stash->val_1_edx, 15, 16));
5188 boolean prefetch = (BIT_EXTRACT_LE(stash->val_80000001_ecx, 8, 9)
5189 || BIT_EXTRACT_LE(stash->val_80000001_edx, 29, 30)
5190 || BIT_EXTRACT_LE(stash->val_80000001_edx, 31, 32));
5191
5192 printf(" (instruction supported synth):\n");
5193 printf(" CMPXCHG8B = %s\n", bools[cmpxchg8b]);
5194 printf(" conditional move/compare = %s\n", bools[cond]);
5195 printf(" PREFETCH/PREFETCHW = %s\n", bools[prefetch]);
5196 }
5197
print_instr_synth(code_stash_t * stash)5198 static void print_instr_synth (code_stash_t* stash)
5199 {
5200 switch (stash->vendor) {
5201 case VENDOR_AMD:
5202 case VENDOR_HYGON:
5203 print_instr_synth_amd(stash);
5204 break;
5205 default:
5206 break;
5207 }
5208 }
5209
do_final(boolean raw,boolean debug,code_stash_t * stash)5210 static void do_final (boolean raw,
5211 boolean debug,
5212 code_stash_t* stash)
5213 {
5214 if (!raw) {
5215 print_instr_synth(stash);
5216 decode_mp_synth(stash);
5217 print_mp_synth(&stash->mp);
5218 print_apic_synth(stash);
5219 decode_override_brand(stash);
5220 print_override_brand(stash);
5221 decode_brand_id_stash(stash);
5222 decode_brand_stash(stash);
5223 if (debug) {
5224 debug_queries(stash);
5225 }
5226 print_uarch(stash);
5227 print_synth(stash);
5228 }
5229 }
5230
5231 static void
print_1_eax(unsigned int value,vendor_t vendor)5232 print_1_eax(unsigned int value,
5233 vendor_t vendor)
5234 {
5235 static ccstring processor[1<<2] = { "primary processor (0)",
5236 "Intel OverDrive (1)",
5237 "secondary processor (2)" };
5238 static named_item names[]
5239 = { { "processor type" , 12, 13, processor },
5240 { "family" , 8, 11, NIL_IMAGES },
5241 { "model" , 4, 7, NIL_IMAGES },
5242 { "stepping id" , 0, 3, NIL_IMAGES },
5243 { "extended family" , 20, 27, NIL_IMAGES },
5244 { "extended model" , 16, 19, NIL_IMAGES },
5245 };
5246
5247 printf(" version information (1/eax):\n");
5248 print_names(value, names, LENGTH(names),
5249 /* max_len => */ 15);
5250
5251 unsigned int synth_family = Synth_Family(value);
5252 unsigned int synth_model = Synth_Model(value);
5253 printf(" (family synth) = 0x%x (%u)\n", synth_family, synth_family);
5254 printf(" (model synth) = 0x%x (%u)\n", synth_model, synth_model);
5255
5256 print_synth_simple(value, vendor);
5257 }
5258
5259 #define B(b,str) \
5260 else if ( __B(val_ebx) == _B(b)) \
5261 ACT(str)
5262 #define FMB(xf,f,xm,m,b,str) \
5263 else if ( __FM(val_eax) == _FM(xf,f,xm,m) \
5264 && __B(val_ebx) == _B(b)) \
5265 ACT(str)
5266 #define FMSB(xf,f,xm,m,s,b,str) \
5267 else if ( __FMS(val_eax) == _FMS(xf,f,xm,m,s) \
5268 && __B(val_ebx) == _B(b)) \
5269 ACT(str)
5270
5271 #define ACT(str) (printf(str))
5272
5273 static void
print_brand(unsigned int val_eax,unsigned int val_ebx)5274 print_brand(unsigned int val_eax,
5275 unsigned int val_ebx)
5276 {
5277 printf(" brand id = 0x%02x (%u): ", __B(val_ebx), __B(val_ebx));
5278 START;
5279 B ( 1, "Intel Celeron, .18um");
5280 B ( 2, "Intel Pentium III, .18um");
5281 FMSB(0, 6, 0,11, 1, 3, "Intel Celeron, .13um");
5282 B ( 3, "Intel Pentium III Xeon, .18um");
5283 B ( 4, "Intel Pentium III, .13um");
5284 B ( 6, "Mobile Intel Pentium III, .13um");
5285 B ( 7, "Mobile Intel Celeron, .13um");
5286 FMB (0,15, 0, 0, 8, "Intel Pentium 4, .18um");
5287 FMSB(0,15, 0, 1, 0, 8, "Intel Pentium 4, .18um");
5288 FMSB(0,15, 0, 1, 1, 8, "Intel Pentium 4, .18um");
5289 FMSB(0,15, 0, 1, 2, 8, "Intel Pentium 4, .18um");
5290 B ( 8, "Mobile Intel Celeron 4, .13um");
5291 B ( 9, "Intel Pentium 4, .13um");
5292 B ( 10, "Intel Celeron 4, .18um");
5293 FMB (0,15, 0, 0, 11, "Intel Xeon MP, .18um");
5294 FMSB(0,15, 0, 1, 0, 11, "Intel Xeon MP, .18um");
5295 FMSB(0,15, 0, 1, 1, 11, "Intel Xeon MP, .18um");
5296 FMSB(0,15, 0, 1, 2, 11, "Intel Xeon MP, .18um");
5297 B ( 11, "Intel Xeon, .13um");
5298 B ( 12, "Intel Xeon MP, .13um");
5299 FMB (0,15, 0, 0, 14, "Intel Xeon, .18um");
5300 FMSB(0,15, 0, 1, 0, 14, "Intel Xeon, .18um");
5301 FMSB(0,15, 0, 1, 1, 14, "Intel Xeon, .18um");
5302 FMSB(0,15, 0, 1, 2, 14, "Intel Xeon, .18um");
5303 FMB (0,15, 0, 2, 14, "Mobile Intel Pentium 4 Processor-M");
5304 B ( 14, "Mobile Intel Xeon, .13um");
5305 FMB (0,15, 0, 2, 15, "Mobile Intel Pentium 4 Processor-M");
5306 B ( 15, "Mobile Intel Celeron 4");
5307 B ( 17, "Mobile Genuine Intel");
5308 B ( 18, "Intel Celeron M");
5309 B ( 19, "Mobile Intel Celeron");
5310 B ( 20, "Intel Celeron");
5311 B ( 21, "Mobile Genuine Intel");
5312 B ( 22, "Intel Pentium M, .13um");
5313 B ( 23, "Mobile Intel Celeron");
5314 DEFAULT ("unknown");
5315 printf("\n");
5316 }
5317
5318 #undef ACT
5319
5320 static void
print_1_ebx(unsigned int value)5321 print_1_ebx(unsigned int value)
5322 {
5323 static named_item names[]
5324 = { { "process local APIC physical ID" , 24, 31, NIL_IMAGES },
5325 { "maximum IDs for CPUs in pkg" , 16, 23, NIL_IMAGES },
5326 { "CLFLUSH line size" , 8, 15, NIL_IMAGES },
5327 { "brand index" , 0, 7, NIL_IMAGES },
5328 };
5329
5330 printf(" miscellaneous (1/ebx):\n");
5331 print_names(value, names, LENGTH(names),
5332 /* max_len => */ 0);
5333 }
5334
5335 static void
print_1_ecx(unsigned int value)5336 print_1_ecx(unsigned int value)
5337 {
5338 static named_item names[]
5339 = { { "PNI/SSE3: Prescott New Instructions" , 0, 0, bools },
5340 { "PCLMULDQ instruction" , 1, 1, bools },
5341 { "DTES64: 64-bit debug store" , 2, 2, bools },
5342 { "MONITOR/MWAIT" , 3, 3, bools },
5343 { "CPL-qualified debug store" , 4, 4, bools },
5344 { "VMX: virtual machine extensions" , 5, 5, bools },
5345 { "SMX: safer mode extensions" , 6, 6, bools },
5346 { "Enhanced Intel SpeedStep Technology" , 7, 7, bools },
5347 { "TM2: thermal monitor 2" , 8, 8, bools },
5348 { "SSSE3 extensions" , 9, 9, bools },
5349 { "context ID: adaptive or shared L1 data" , 10, 10, bools },
5350 { "SDBG: IA32_DEBUG_INTERFACE" , 11, 11, bools },
5351 { "FMA instruction" , 12, 12, bools },
5352 { "CMPXCHG16B instruction" , 13, 13, bools },
5353 { "xTPR disable" , 14, 14, bools },
5354 { "PDCM: perfmon and debug" , 15, 15, bools },
5355 { "PCID: process context identifiers" , 17, 17, bools },
5356 { "DCA: direct cache access" , 18, 18, bools },
5357 { "SSE4.1 extensions" , 19, 19, bools },
5358 { "SSE4.2 extensions" , 20, 20, bools },
5359 { "x2APIC: extended xAPIC support" , 21, 21, bools },
5360 { "MOVBE instruction" , 22, 22, bools },
5361 { "POPCNT instruction" , 23, 23, bools },
5362 { "time stamp counter deadline" , 24, 24, bools },
5363 { "AES instruction" , 25, 25, bools },
5364 { "XSAVE/XSTOR states" , 26, 26, bools },
5365 { "OS-enabled XSAVE/XSTOR" , 27, 27, bools },
5366 { "AVX: advanced vector extensions" , 28, 28, bools },
5367 { "F16C half-precision convert instruction" , 29, 29, bools },
5368 { "RDRAND instruction" , 30, 30, bools },
5369 { "hypervisor guest status" , 31, 31, bools },
5370 };
5371
5372 printf(" feature information (1/ecx):\n");
5373 print_names(value, names, LENGTH(names),
5374 /* max_len => */ 0);
5375 }
5376
5377 static void
print_1_edx(unsigned int value)5378 print_1_edx(unsigned int value)
5379 {
5380 static named_item names[]
5381 = { { "x87 FPU on chip" , 0, 0, bools },
5382 { "VME: virtual-8086 mode enhancement" , 1, 1, bools },
5383 { "DE: debugging extensions" , 2, 2, bools },
5384 { "PSE: page size extensions" , 3, 3, bools },
5385 { "TSC: time stamp counter" , 4, 4, bools },
5386 { "RDMSR and WRMSR support" , 5, 5, bools },
5387 { "PAE: physical address extensions" , 6, 6, bools },
5388 { "MCE: machine check exception" , 7, 7, bools },
5389 { "CMPXCHG8B inst." , 8, 8, bools },
5390 { "APIC on chip" , 9, 9, bools },
5391 { "SYSENTER and SYSEXIT" , 11, 11, bools },
5392 { "MTRR: memory type range registers" , 12, 12, bools },
5393 { "PTE global bit" , 13, 13, bools },
5394 { "MCA: machine check architecture" , 14, 14, bools },
5395 { "CMOV: conditional move/compare instr" , 15, 15, bools },
5396 { "PAT: page attribute table" , 16, 16, bools },
5397 { "PSE-36: page size extension" , 17, 17, bools },
5398 { "PSN: processor serial number" , 18, 18, bools },
5399 { "CLFLUSH instruction" , 19, 19, bools },
5400 { "DS: debug store" , 21, 21, bools },
5401 { "ACPI: thermal monitor and clock ctrl" , 22, 22, bools },
5402 { "MMX Technology" , 23, 23, bools },
5403 { "FXSAVE/FXRSTOR" , 24, 24, bools },
5404 { "SSE extensions" , 25, 25, bools },
5405 { "SSE2 extensions" , 26, 26, bools },
5406 { "SS: self snoop" , 27, 27, bools },
5407 { "hyper-threading / multi-core supported" , 28, 28, bools },
5408 { "TM: therm. monitor" , 29, 29, bools },
5409 { "IA64" , 30, 30, bools },
5410 { "PBE: pending break event" , 31, 31, bools },
5411 };
5412
5413 printf(" feature information (1/edx):\n");
5414 print_names(value, names, LENGTH(names),
5415 /* max_len => */ 0);
5416 }
5417
print_2_byte(unsigned char value,vendor_t vendor,unsigned int val_1_eax)5418 static void print_2_byte(unsigned char value,
5419 vendor_t vendor,
5420 unsigned int val_1_eax)
5421 {
5422 if (value == 0x00) return;
5423
5424 printf(" 0x%02x: ", value);
5425 #define CONT "\n "
5426
5427 if (vendor == VENDOR_CYRIX || vendor == VENDOR_VIA) {
5428 switch (value) {
5429 case 0x70: printf("TLB: 4K pages, 4-way, 32 entries\n"); return;
5430 case 0x74: printf("Cyrix-specific: ?\n"); return;
5431 case 0x77: printf("Cyrix-specific: ?\n"); return;
5432 case 0x80: printf("L1 cache: 16K, 4-way, 16 byte lines\n"); return;
5433 case 0x82: printf("Cyrix-specific: ?\n"); return;
5434 case 0x84: printf("L2 cache: 1M, 8-way, 32 byte lines\n"); return;
5435 }
5436 }
5437
5438 switch (value) {
5439 case 0x01: printf("instruction TLB: 4K pages, 4-way, 32 entries"); break;
5440 case 0x02: printf("instruction TLB: 4M pages, 4-way, 2 entries"); break;
5441 case 0x03: printf("data TLB: 4K pages, 4-way, 64 entries"); break;
5442 case 0x04: printf("data TLB: 4M pages, 4-way, 8 entries"); break;
5443 case 0x05: printf("data TLB: 4M pages, 4-way, 32 entries"); break;
5444 case 0x06: printf("L1 instruction cache: 8K, 4-way, 32 byte lines"); break;
5445 case 0x08: printf("L1 instruction cache: 16K, 4-way, 32 byte lines"); break;
5446 case 0x09: printf("L1 instruction cache: 32K, 4-way, 64-byte lines"); break;
5447 case 0x0a: printf("L1 data cache: 8K, 2-way, 32 byte lines"); break;
5448 case 0x0b: printf("instruction TLB: 4M pages, 4-way, 4 entries"); break;
5449 case 0x0c: printf("L1 data cache: 16K, 4-way, 32 byte lines"); break;
5450 case 0x0d: printf("L1 data cache: 16K, 4-way, 64-byte lines"); break;
5451 case 0x0e: printf("L1 data cache: 24K, 6-way, 64 byte lines"); break;
5452 case 0x10: printf("L1 data cache: 16K, 4-way, 32 byte lines"); break;
5453 case 0x15: printf("L1 instruction cache: 16K, 4-way, 32 byte lines"); break;
5454 case 0x1d: printf("L2 cache: 128K, 2-way, 64 byte lines"); break;
5455 case 0x1a: printf("L2 cache: 96K, 6-way, 64 byte lines"); break;
5456 case 0x21: printf("L2 cache: 256K MLC, 8-way, 64 byte lines"); break;
5457 case 0x22: printf("L3 cache: 512K, 4-way, 64 byte lines"); break;
5458 case 0x23: printf("L3 cache: 1M, 8-way, 64 byte lines"); break;
5459 case 0x24: printf("L2 cache: 1M, 16-way, 64 byte lines"); break;
5460 case 0x25: printf("L3 cache: 2M, 8-way, 64 byte lines"); break;
5461 case 0x29: printf("L3 cache: 4M, 8-way, 64 byte lines"); break;
5462 case 0x2c: printf("L1 data cache: 32K, 8-way, 64 byte lines"); break;
5463 case 0x30: printf("L1 cache: 32K, 8-way, 64 byte lines"); break;
5464 case 0x39: printf("L2 cache: 128K, 4-way, sectored, 64 byte lines"); break;
5465 case 0x3a: printf("L2 cache: 192K, 6-way, sectored, 64 byte lines"); break;
5466 case 0x3b: printf("L2 cache: 128K, 2-way, sectored, 64 byte lines"); break;
5467 case 0x3c: printf("L2 cache: 256K, 4-way, sectored, 64 byte lines"); break;
5468 case 0x3d: printf("L2 cache: 384K, 6-way, sectored, 64 byte lines"); break;
5469 case 0x3e: printf("L2 cache: 512K, 4-way, sectored, 64 byte lines"); break;
5470 case 0x40: if (__F(val_1_eax) <= _XF(0) + _F(6)) {
5471 printf("No L2 cache");
5472 } else {
5473 printf("No L3 cache");
5474 }
5475 break;
5476 case 0x41: printf("L2 cache: 128K, 4-way, 32 byte lines"); break;
5477 case 0x42: printf("L2 cache: 256K, 4-way, 32 byte lines"); break;
5478 case 0x43: printf("L2 cache: 512K, 4-way, 32 byte lines"); break;
5479 case 0x44: printf("L2 cache: 1M, 4-way, 32 byte lines"); break;
5480 case 0x45: printf("L2 cache: 2M, 4-way, 32 byte lines"); break;
5481 case 0x46: printf("L3 cache: 4M, 4-way, 64 byte lines"); break;
5482 case 0x47: printf("L3 cache: 8M, 8-way, 64 byte lines"); break;
5483 case 0x48: printf("L2 cache: 3M, 12-way, 64 byte lines"); break;
5484 case 0x49: if (__FM(val_1_eax) == _XF(0) + _F(15) + _XM(0) + _M(6)) {
5485 printf("L3 cache: 4M, 16-way, 64 byte lines");
5486 } else {
5487 printf("L2 cache: 4M, 16-way, 64 byte lines");
5488 }
5489 break;
5490 case 0x4a: printf("L3 cache: 6M, 12-way, 64 byte lines"); break;
5491 case 0x4b: printf("L3 cache: 8M, 16-way, 64 byte lines"); break;
5492 case 0x4c: printf("L3 cache: 12M, 12-way, 64 byte lines"); break;
5493 case 0x4d: printf("L3 cache: 16M, 16-way, 64 byte lines"); break;
5494 case 0x4e: printf("L2 cache: 6M, 24-way, 64 byte lines"); break;
5495 case 0x4f: printf("instruction TLB: 4K pages, 32 entries"); break;
5496 case 0x50: printf("instruction TLB: 4K & 2M/4M pages, 64 entries"); break;
5497 case 0x51: printf("instruction TLB: 4K & 2M/4M pages, 128 entries"); break;
5498 case 0x52: printf("instruction TLB: 4K & 2M/4M pages, 256 entries"); break;
5499 case 0x55: printf("instruction TLB: 2M/4M pages, fully, 7 entries"); break;
5500 case 0x56: printf("L1 data TLB: 4M pages, 4-way, 16 entries"); break;
5501 case 0x57: printf("L1 data TLB: 4K pages, 4-way, 16 entries"); break;
5502 case 0x59: printf("data TLB: 4K pages, 16 entries"); break;
5503 case 0x5a: printf("data TLB: 2M/4M pages, 4-way, 32 entries"); break;
5504 case 0x5b: printf("data TLB: 4K & 4M pages, 64 entries"); break;
5505 case 0x5c: printf("data TLB: 4K & 4M pages, 128 entries"); break;
5506 case 0x5d: printf("data TLB: 4K & 4M pages, 256 entries"); break;
5507 case 0x60: printf("L1 data cache: 16K, 8-way, 64 byte lines"); break;
5508 case 0x61: printf("instruction TLB: 4K pages, 48 entries"); break;
5509 case 0x63: printf("data TLB: 2M/4M pages, 4-way, 32 entries");
5510 printf(CONT "data TLB: 1G pages, 4-way, 4 entries"); break;
5511 case 0x64: printf("data TLB: 4K pages, 4-way, 512 entries"); break;
5512 case 0x66: printf("L1 data cache: 8K, 4-way, 64 byte lines"); break;
5513 case 0x67: printf("L1 data cache: 16K, 4-way, 64 byte lines"); break;
5514 case 0x68: printf("L1 data cache: 32K, 4-way, 64 byte lines"); break;
5515 case 0x6a: printf("micro-data TLB: 4K pages, 8-way, 64 entries"); break;
5516 case 0x6b: printf("data TLB: 4K pages, 8-way, 256 entries"); break;
5517 case 0x6c: printf("data TLB: 2M/4M pages, 8-way, 128 entries"); break;
5518 case 0x6d: printf("data TLB: 1G pages, fully, 16 entries"); break;
5519 case 0x70: printf("Trace cache: 12K-uop, 8-way"); break;
5520 case 0x71: printf("Trace cache: 16K-uop, 8-way"); break;
5521 case 0x72: printf("Trace cache: 32K-uop, 8-way"); break;
5522 case 0x73: printf("Trace cache: 64K-uop, 8-way"); break;
5523 case 0x76: printf("instruction TLB: 2M/4M pages, fully, 8 entries"); break;
5524 case 0x77: printf("L1 instruction cache: 16K, 4-way, sectored,"
5525 " 64 byte lines"); break;
5526 case 0x78: printf("L2 cache: 1M, 4-way, 64 byte lines"); break;
5527 case 0x79: printf("L2 cache: 128K, 8-way, sectored, 64 byte lines"); break;
5528 case 0x7a: printf("L2 cache: 256K, 8-way, sectored, 64 byte lines"); break;
5529 case 0x7b: printf("L2 cache: 512K, 8-way, sectored, 64 byte lines"); break;
5530 case 0x7c: printf("L2 cache: 1M, 8-way, sectored, 64 byte lines"); break;
5531 case 0x7d: printf("L2 cache: 2M, 8-way, 64 byte lines"); break;
5532 case 0x7e: printf("L2 cache: 256K, 8-way, sectored, 128 byte lines"); break;
5533 case 0x7f: printf("L2 cache: 512K, 2-way, 64 byte lines"); break;
5534 case 0x80: printf("L2 cache: 512K, 8-way, 64 byte lines"); break;
5535 case 0x81: printf("L2 cache: 128K, 8-way, 32 byte lines"); break;
5536 case 0x82: printf("L2 cache: 256K, 8-way, 32 byte lines"); break;
5537 case 0x83: printf("L2 cache: 512K, 8-way, 32 byte lines"); break;
5538 case 0x84: printf("L2 cache: 1M, 8-way, 32 byte lines"); break;
5539 case 0x85: printf("L2 cache: 2M, 8-way, 32 byte lines"); break;
5540 case 0x86: printf("L2 cache: 512K, 4-way, 64 byte lines"); break;
5541 case 0x87: printf("L2 cache: 1M, 8-way, 64 byte lines"); break;
5542 case 0x88: printf("L3 cache: 2M, 4-way, 64 byte lines"); break;
5543 case 0x89: printf("L3 cache: 4M, 4-way, 64 byte lines"); break;
5544 case 0x8a: printf("L3 cache: 8M, 4-way, 64 byte lines"); break;
5545 case 0x8d: printf("L3 cache: 3M, 12-way, 128 byte lines"); break;
5546 case 0x90: printf("instruction TLB: 4K-256M, fully, 64 entries"); break;
5547 case 0x96: printf("instruction TLB: 4K-256M, fully, 32 entries"); break;
5548 case 0x9b: printf("instruction TLB: 4K-256M, fully, 96 entries"); break;
5549 case 0xa0: printf("data TLB: 4K pages, fully, 32 entries"); break;
5550 case 0xb0: printf("instruction TLB: 4K, 4-way, 128 entries"); break;
5551 case 0xb1: printf("instruction TLB: 2M/4M, 4-way, 4/8 entries"); break;
5552 case 0xb2: printf("instruction TLB: 4K, 4-way, 64 entries"); break;
5553 case 0xb3: printf("data TLB: 4K pages, 4-way, 128 entries"); break;
5554 case 0xb4: printf("data TLB: 4K pages, 4-way, 256 entries"); break;
5555 case 0xb5: printf("instruction TLB: 4K, 8-way, 64 entries"); break;
5556 case 0xb6: printf("instruction TLB: 4K, 8-way, 128 entries"); break;
5557 case 0xba: printf("data TLB: 4K pages, 4-way, 64 entries"); break;
5558 case 0xc0: printf("data TLB: 4K & 4M pages, 4-way, 8 entries"); break;
5559 case 0xc1: printf("L2 TLB: 4K/2M pages, 8-way, 1024 entries"); break;
5560 case 0xc2: printf("data TLB: 4K & 2M pages, 4-way, 16 entries"); break;
5561 case 0xc3: printf("L2 TLB: 4K/2M pages, 6-way, 1536 entries"); break;
5562 case 0xc4: printf("data TLB: 2M/4M pages, 4-way, 32 entries"); break;
5563 case 0xca: printf("L2 TLB: 4K pages, 4-way, 512 entries"); break;
5564 case 0xd0: printf("L3 cache: 512K, 4-way, 64 byte lines"); break;
5565 case 0xd1: printf("L3 cache: 1M, 4-way, 64 byte lines"); break;
5566 case 0xd2: printf("L3 cache: 2M, 4-way, 64 byte lines"); break;
5567 case 0xd6: printf("L3 cache: 1M, 8-way, 64 byte lines"); break;
5568 case 0xd7: printf("L3 cache: 2M, 8-way, 64 byte lines"); break;
5569 case 0xd8: printf("L3 cache: 4M, 8-way, 64 byte lines"); break;
5570 case 0xdc: printf("L3 cache: 1.5M, 12-way, 64 byte lines"); break;
5571 case 0xdd: printf("L3 cache: 3M, 12-way, 64 byte lines"); break;
5572 case 0xde: printf("L3 cache: 6M, 12-way, 64 byte lines"); break;
5573 case 0xe2: printf("L3 cache: 2M, 16-way, 64 byte lines"); break;
5574 case 0xe3: printf("L3 cache: 4M, 16-way, 64 byte lines"); break;
5575 case 0xe4: printf("L3 cache: 8M, 16-way, 64 byte lines"); break;
5576 case 0xea: printf("L3 cache: 12M, 24-way, 64 byte lines"); break;
5577 case 0xeb: printf("L3 cache: 18M, 24-way, 64 byte lines"); break;
5578 case 0xec: printf("L3 cache: 24M, 24-way, 64 byte lines"); break;
5579 case 0xf0: printf("64 byte prefetching"); break;
5580 case 0xf1: printf("128 byte prefetching"); break;
5581 case 0xfe: printf("TLB data is in CPUID leaf 0x18"); break;
5582 case 0xff: printf("cache data is in CPUID leaf 4"); break;
5583 default: printf("unknown"); break;
5584 }
5585
5586 /*
5587 ** WARNING: If you add values here, you probably need to update the code in
5588 ** stash_intel_cache, too.
5589 */
5590
5591 printf("\n");
5592 #undef CONT
5593 }
5594
5595 static void
print_4_eax(unsigned int value)5596 print_4_eax(unsigned int value)
5597 {
5598 static ccstring cache_type[1<<5] = { "no more caches (0)",
5599 "data cache (1)",
5600 "instruction cache (2)",
5601 "unified cache (3)" };
5602 static named_item names[]
5603 = { { "cache type" , 0, 4, cache_type },
5604 { "cache level" , 5, 7, NIL_IMAGES },
5605 { "self-initializing cache level" , 8, 8, bools },
5606 { "fully associative cache" , 9, 9, bools },
5607 { "maximum IDs for CPUs sharing cache" , 14, 25, NIL_IMAGES },
5608 { "maximum IDs for cores in pkg" , 26, 31, NIL_IMAGES },
5609 };
5610
5611 print_names(value, names, LENGTH(names),
5612 /* max_len => */ 36);
5613 }
5614
5615 static void
print_4_ebx(unsigned int value)5616 print_4_ebx(unsigned int value)
5617 {
5618 static named_item names[]
5619 = { { "system coherency line size" , 0, 11, MINUS1_IMAGES },
5620 { "physical line partitions" , 12, 21, MINUS1_IMAGES },
5621 { "ways of associativity" , 22, 31, MINUS1_IMAGES },
5622 };
5623
5624 print_names(value, names, LENGTH(names),
5625 /* max_len => */ 36);
5626 }
5627
5628 static void
print_4_ecx(unsigned int value)5629 print_4_ecx(unsigned int value)
5630 {
5631 static named_item names[]
5632 = { { "number of sets" , 0, 31, MINUS1_IMAGES },
5633 };
5634
5635 print_names(value, names, LENGTH(names),
5636 /* max_len => */ 36);
5637 }
5638
5639 static void
print_4_edx(unsigned int value)5640 print_4_edx(unsigned int value)
5641 {
5642 static named_item names[]
5643 = { { "WBINVD/INVD acts on lower caches" , 0, 0, bools },
5644 { "inclusive to lower caches" , 1, 1, bools },
5645 { "complex cache indexing" , 2, 2, bools },
5646 };
5647
5648 print_names(value, names, LENGTH(names),
5649 /* max_len => */ 36);
5650 }
5651
5652 static void
print_4_synth(const unsigned int words[])5653 print_4_synth(const unsigned int words[])
5654 {
5655 unsigned int ways_assoc = BIT_EXTRACT_LE(words[WORD_EBX], 22, 32) + 1;
5656 unsigned int parts = BIT_EXTRACT_LE(words[WORD_EBX], 12, 22) + 1;
5657 unsigned int line_size = BIT_EXTRACT_LE(words[WORD_EBX], 0, 12) + 1;
5658 unsigned int sets = words[WORD_ECX] + 1;
5659 unsigned int size = (ways_assoc * parts * line_size * sets);
5660
5661 printf(" (size synth) = %u", size);
5662 if (size > 1048576) {
5663 if ((size % 1048576) == 0) {
5664 printf(" (%u MB)", size / 1048576);
5665 } else {
5666 printf(" (%3.1f MB)", ((float)size) / 1048576.0);
5667 }
5668 } else if (size > 1024) {
5669 if ((size % 1024) == 0) {
5670 printf(" (%u KB)", size / 1024);
5671 } else {
5672 printf(" (%3.1f KB)", ((float)size) / 1024.0);
5673 }
5674 }
5675 printf("\n");
5676 }
5677
5678 static void
print_5_eax(unsigned int value)5679 print_5_eax(unsigned int value)
5680 {
5681 static named_item names[]
5682 = { { "smallest monitor-line size (bytes)" , 0, 15, NIL_IMAGES },
5683 };
5684
5685 print_names(value, names, LENGTH(names),
5686 /* max_len => */ 40);
5687 }
5688
5689 static void
print_5_ebx(unsigned int value)5690 print_5_ebx(unsigned int value)
5691 {
5692 static named_item names[]
5693 = { { "largest monitor-line size (bytes)" , 0, 15, NIL_IMAGES },
5694 };
5695
5696 print_names(value, names, LENGTH(names),
5697 /* max_len => */ 40);
5698 }
5699
5700 static void
print_5_ecx(unsigned int value)5701 print_5_ecx(unsigned int value)
5702 {
5703 static named_item names[]
5704 = { { "enum of Monitor-MWAIT exts supported" , 0, 0, bools },
5705 { "supports intrs as break-event for MWAIT" , 1, 1, bools },
5706 };
5707
5708 print_names(value, names, LENGTH(names),
5709 /* max_len => */ 40);
5710 }
5711
5712 static void
print_5_edx(unsigned int value)5713 print_5_edx(unsigned int value)
5714 {
5715 static named_item names[]
5716 = { { "number of C0 sub C-states using MWAIT" , 0, 3, NIL_IMAGES },
5717 { "number of C1 sub C-states using MWAIT" , 4, 7, NIL_IMAGES },
5718 { "number of C2 sub C-states using MWAIT" , 8, 11, NIL_IMAGES },
5719 { "number of C3 sub C-states using MWAIT" , 12, 15, NIL_IMAGES },
5720 { "number of C4 sub C-states using MWAIT" , 16, 19, NIL_IMAGES },
5721 { "number of C5 sub C-states using MWAIT" , 20, 23, NIL_IMAGES },
5722 { "number of C6 sub C-states using MWAIT" , 24, 27, NIL_IMAGES },
5723 { "number of C7 sub C-states using MWAIT" , 28, 31, NIL_IMAGES },
5724 };
5725
5726 print_names(value, names, LENGTH(names),
5727 /* max_len => */ 40);
5728 }
5729
5730 static void
print_6_eax(unsigned int value)5731 print_6_eax(unsigned int value)
5732 {
5733 static named_item names[]
5734 = { { "digital thermometer" , 0, 0, bools },
5735 { "Intel Turbo Boost Technology" , 1, 1, bools },
5736 { "ARAT always running APIC timer" , 2, 2, bools },
5737 { "PLN power limit notification" , 4, 4, bools },
5738 { "ECMD extended clock modulation duty" , 5, 5, bools },
5739 { "PTM package thermal management" , 6, 6, bools },
5740 { "HWP base registers" , 7, 7, bools },
5741 { "HWP notification" , 8, 8, bools },
5742 { "HWP activity window" , 9, 9, bools },
5743 { "HWP energy performance preference" , 10, 10, bools },
5744 { "HWP package level request" , 11, 11, bools },
5745 { "HDC base registers" , 13, 13, bools },
5746 { "Intel Turbo Boost Max Technology 3.0" , 14, 14, bools },
5747 { "HWP capabilities" , 15, 15, bools },
5748 { "HWP PECI override" , 16, 16, bools },
5749 { "flexible HWP" , 17, 17, bools },
5750 { "IA32_HWP_REQUEST MSR fast access mode" , 18, 18, bools },
5751 { "HW_FEEDBACK MSRs supported" , 19, 19, bools },
5752 { "ignoring idle logical processor HWP req" , 20, 20, bools },
5753 { "enhanced hardware feedback interface" , 23, 23, bools },
5754 };
5755
5756 print_names(value, names, LENGTH(names),
5757 /* max_len => */ 39);
5758 }
5759
5760 static void
print_6_ebx(unsigned int value)5761 print_6_ebx(unsigned int value)
5762 {
5763 static named_item names[]
5764 = { { "digital thermometer thresholds" , 0, 3, NIL_IMAGES },
5765 };
5766
5767 print_names(value, names, LENGTH(names),
5768 /* max_len => */ 39);
5769 }
5770
5771 static void
print_6_ecx(unsigned int value)5772 print_6_ecx(unsigned int value)
5773 {
5774 static named_item names[]
5775 = { { "hardware coordination feedback" , 0, 0, bools },
5776 { "ACNT2 available" , 1, 1, bools },
5777 { "performance-energy bias capability" , 3, 3, bools },
5778 { "number of enh hardware feedback classes" , 8, 11, NIL_IMAGES },
5779 };
5780
5781 print_names(value, names, LENGTH(names),
5782 /* max_len => */ 39);
5783 }
5784
5785 static void
print_6_edx(unsigned int value)5786 print_6_edx(unsigned int value)
5787 {
5788 static named_item names[]
5789 = { { "performance capability reporting" , 0, 0, bools },
5790 { "energy efficiency capability reporting" , 1, 1, bools },
5791 { "size of feedback struct (4KB pages)" , 8, 11, MINUS1_IMAGES },
5792 { "index of CPU's row in feedback struct" , 16, 31, NIL_IMAGES },
5793 };
5794
5795 print_names(value, names, LENGTH(names),
5796 /* max_len => */ 39);
5797 }
5798
5799 static void
print_7_0_ebx(unsigned int value)5800 print_7_0_ebx(unsigned int value)
5801 {
5802 static named_item names[]
5803 = { { "FSGSBASE instructions" , 0, 0, bools },
5804 { "IA32_TSC_ADJUST MSR supported" , 1, 1, bools },
5805 { "SGX: Software Guard Extensions supported", 2, 2, bools },
5806 { "BMI1 instructions" , 3, 3, bools },
5807 { "HLE hardware lock elision" , 4, 4, bools },
5808 { "AVX2: advanced vector extensions 2" , 5, 5, bools },
5809 { "FDP_EXCPTN_ONLY" , 6, 6, bools },
5810 { "SMEP supervisor mode exec protection" , 7, 7, bools },
5811 { "BMI2 instructions" , 8, 8, bools },
5812 { "enhanced REP MOVSB/STOSB" , 9, 9, bools },
5813 { "INVPCID instruction" , 10, 10, bools },
5814 { "RTM: restricted transactional memory" , 11, 11, bools },
5815 { "RDT-CMT/PQoS cache monitoring" , 12, 12, bools },
5816 { "deprecated FPU CS/DS" , 13, 13, bools },
5817 { "MPX: intel memory protection extensions" , 14, 14, bools },
5818 { "RDT-CAT/PQE cache allocation" , 15, 15, bools },
5819 { "AVX512F: AVX-512 foundation instructions", 16, 16, bools },
5820 { "AVX512DQ: double & quadword instructions", 17, 17, bools },
5821 { "RDSEED instruction" , 18, 18, bools },
5822 { "ADX instructions" , 19, 19, bools },
5823 { "SMAP: supervisor mode access prevention" , 20, 20, bools },
5824 { "AVX512IFMA: fused multiply add" , 21, 21, bools },
5825 { "PCOMMIT instruction" , 22, 22, bools },
5826 { "CLFLUSHOPT instruction" , 23, 23, bools },
5827 { "CLWB instruction" , 24, 24, bools },
5828 { "Intel processor trace" , 25, 25, bools },
5829 { "AVX512PF: prefetch instructions" , 26, 26, bools },
5830 { "AVX512ER: exponent & reciprocal instrs" , 27, 27, bools },
5831 { "AVX512CD: conflict detection instrs" , 28, 28, bools },
5832 { "SHA instructions" , 29, 29, bools },
5833 { "AVX512BW: byte & word instructions" , 30, 30, bools },
5834 { "AVX512VL: vector length" , 31, 31, bools },
5835 };
5836
5837 print_names(value, names, LENGTH(names),
5838 /* max_len => */ 40);
5839 }
5840
5841 static void
print_7_0_ecx(unsigned int value)5842 print_7_0_ecx(unsigned int value)
5843 {
5844 static named_item names[]
5845 = { { "PREFETCHWT1" , 0, 0, bools },
5846 { "AVX512VBMI: vector byte manipulation" , 1, 1, bools },
5847 { "UMIP: user-mode instruction prevention" , 2, 2, bools },
5848 { "PKU protection keys for user-mode" , 3, 3, bools },
5849 { "OSPKE CR4.PKE and RDPKRU/WRPKRU" , 4, 4, bools },
5850 { "WAITPKG instructions" , 5, 5, bools },
5851 { "AVX512_VBMI2: byte VPCOMPRESS, VPEXPAND" , 6, 6, bools },
5852 { "CET_SS: CET shadow stack" , 7, 7, bools },
5853 { "GFNI: Galois Field New Instructions" , 8, 8, bools },
5854 { "VAES instructions" , 9, 9, bools },
5855 { "VPCLMULQDQ instruction" , 10, 10, bools },
5856 { "AVX512_VNNI: neural network instructions", 11, 11, bools },
5857 { "AVX512_BITALG: bit count/shiffle" , 12, 12, bools },
5858 { "TME: Total Memory Encryption" , 13, 13, bools },
5859 { "AVX512: VPOPCNTDQ instruction" , 14, 14, bools },
5860 { "LA57: 57-bit addrs & 5-level paging" , 16, 16, bools },
5861 { "BNDLDX/BNDSTX MAWAU value in 64-bit mode", 17, 21, NIL_IMAGES },
5862 { "RDPID: read processor D supported" , 22, 22, bools },
5863 { "KL: key locker" , 23, 23, bools },
5864 { "bus lock detection" , 24, 24, bools }, // LX*, Qemu*
5865 { "CLDEMOTE supports cache line demote" , 25, 25, bools },
5866 { "MOVDIRI instruction" , 27, 27, bools },
5867 { "MOVDIR64B instruction" , 28, 28, bools },
5868 { "ENQCMD instruction" , 29, 29, bools },
5869 { "SGX_LC: SGX launch config supported" , 30, 30, bools },
5870 { "PKS: supervisor protection keys" , 31, 31, bools },
5871 };
5872
5873 print_names(value, names, LENGTH(names),
5874 /* max_len => */ 40);
5875 }
5876
5877 static void
print_7_0_edx(unsigned int value)5878 print_7_0_edx(unsigned int value)
5879 {
5880 static named_item names[]
5881 = { { "AVX512_4VNNIW: neural network instrs" , 2, 2, bools },
5882 { "AVX512_4FMAPS: multiply acc single prec" , 3, 3, bools },
5883 { "fast short REP MOV" , 4, 4, bools },
5884 { "UINTR: user interrupts" , 5, 5, bools },
5885 { "AVX512_VP2INTERSECT: intersect mask regs", 8, 8, bools },
5886 { "SRBDS mitigation MSR available" , 9, 9, bools }, // LX*
5887 { "VERW MD_CLEAR microcode support" , 10, 10, bools },
5888 { "RTM transaction always aborts" , 11, 11, bools }, // LX*
5889 { "TSX_FORCE_ABORT" , 13, 13, bools }, // LX*
5890 { "SERIALIZE instruction" , 14, 14, bools },
5891 { "hybrid part" , 15, 15, bools },
5892 { "TSXLDTRK: TSX suspend load addr tracking", 16, 16, bools },
5893 { "PCONFIG instruction" , 18, 18, bools },
5894 { "LBR: architectural last branch records" , 19, 19, bools },
5895 { "CET_IBT: CET indirect branch tracking" , 20, 20, bools },
5896 { "AMX-BF16: tile bfloat16 support" , 22, 22, bools },
5897 { "AVX512_FP16: fp16 support" , 23, 23, bools },
5898 { "AMX-TILE: tile architecture support" , 24, 24, bools },
5899 { "AMX-INT8: tile 8-bit integer support" , 25, 25, bools },
5900 { "IBRS/IBPB: indirect branch restrictions" , 26, 26, bools },
5901 { "STIBP: 1 thr indirect branch predictor" , 27, 27, bools },
5902 { "L1D_FLUSH: IA32_FLUSH_CMD MSR" , 28, 28, bools },
5903 { "IA32_ARCH_CAPABILITIES MSR" , 29, 29, bools },
5904 { "IA32_CORE_CAPABILITIES MSR" , 30, 30, bools },
5905 { "SSBD: speculative store bypass disable" , 31, 31, bools },
5906 };
5907 print_names(value, names, LENGTH(names),
5908 /* max_len => */ 40);
5909 }
5910
5911 static void
print_7_1_eax(unsigned int value)5912 print_7_1_eax(unsigned int value)
5913 {
5914 static named_item names[]
5915 = { { "AVX-VNNI: AVX VNNI neural network instrs", 4, 4, bools },
5916 { "AVX512_BF16: bfloat16 instructions" , 5, 5, bools },
5917 { "zero-length MOVSB" , 10, 10, bools },
5918 { "fast short STOSB" , 11, 11, bools },
5919 { "fast short CMPSB, SCASB" , 12, 12, bools },
5920 { "HRESET: history reset support" , 22, 22, bools },
5921 { "LAM: linear address masking" , 26, 26, bools },
5922 };
5923 print_names(value, names, LENGTH(names),
5924 /* max_len => */ 40);
5925 }
5926
5927 static void
print_a_eax(unsigned int value)5928 print_a_eax(unsigned int value)
5929 {
5930 static named_item names[]
5931 = { { "version ID" , 0, 7, NIL_IMAGES },
5932 { "number of counters per logical processor", 8, 15, NIL_IMAGES },
5933 { "bit width of counter" , 16, 23, NIL_IMAGES },
5934 { "length of EBX bit vector" , 24, 31, NIL_IMAGES },
5935 };
5936
5937 print_names(value, names, LENGTH(names),
5938 /* max_len => */ 40);
5939 }
5940
5941 static void
print_a_ebx(unsigned int value,unsigned int val_eax)5942 print_a_ebx(unsigned int value,
5943 unsigned int val_eax)
5944 {
5945 // Bits >= EAX[31:24] are ignored and assumed to be not available
5946 value |= ~RIGHTMASK(BIT_EXTRACT_LE(val_eax, 24, 32));
5947
5948 static ccstring notavails[] = { "available",
5949 "not available" };
5950
5951 static named_item names[]
5952 = { { "core cycle event" , 0, 0, notavails },
5953 { "instruction retired event" , 1, 1, notavails },
5954 { "reference cycles event" , 2, 2, notavails },
5955 { "last-level cache ref event" , 3, 3, notavails },
5956 { "last-level cache miss event" , 4, 4, notavails },
5957 { "branch inst retired event" , 5, 5, notavails },
5958 { "branch mispred retired event" , 6, 6, notavails },
5959 { "top-down slots event" , 7, 7, notavails },
5960 };
5961
5962 print_names(value, names, LENGTH(names),
5963 /* max_len => */ 40);
5964 }
5965
5966 static void
print_a_ecx(unsigned int value)5967 print_a_ecx(unsigned int value)
5968 {
5969 unsigned int bit;
5970 for (bit = 0; bit < sizeof(value)*8; bit++) {
5971 unsigned int field = BIT_EXTRACT_LE(value, bit, bit+1);
5972 printf(" fixed counter %2u supported = %s\n",
5973 bit, bools[field]);
5974 }
5975 }
5976
5977 static void
print_a_edx(unsigned int value)5978 print_a_edx(unsigned int value)
5979 {
5980 static named_item names[]
5981 = { { "number of contiguous fixed counters" , 0, 4, NIL_IMAGES },
5982 { "bit width of fixed counters" , 5, 12, NIL_IMAGES },
5983 { "anythread deprecation" , 15, 15, bools },
5984 };
5985
5986 print_names(value, names, LENGTH(names),
5987 /* max_len => */ 40);
5988 }
5989
5990 static void
print_b_1f_eax(unsigned int value)5991 print_b_1f_eax(unsigned int value)
5992 {
5993 static named_item names[]
5994 = { { "bit width of level" , 0, 4, NIL_IMAGES },
5995 };
5996
5997 print_names(value, names, LENGTH(names),
5998 /* max_len => */ 37);
5999 }
6000
6001 static void
print_b_1f_ebx(unsigned int value)6002 print_b_1f_ebx(unsigned int value)
6003 {
6004 static named_item names[]
6005 = { { "number of logical processors at level" , 0, 15, NIL_IMAGES },
6006 };
6007
6008 print_names(value, names, LENGTH(names),
6009 /* max_len => */ 37);
6010 }
6011
6012 static void
print_b_1f_ecx(unsigned int value)6013 print_b_1f_ecx(unsigned int value)
6014 {
6015 static ccstring level_type[1<<8] = { "invalid (0)",
6016 "thread (1)",
6017 "core (2)",
6018 "module (3)",
6019 "tile (4)",
6020 "die (5)" };
6021
6022 static named_item names[]
6023 = { { "level number" , 0, 7, NIL_IMAGES },
6024 { "level type" , 8, 15, level_type },
6025 };
6026
6027 print_names(value, names, LENGTH(names),
6028 /* max_len => */ 37);
6029 }
6030
6031 static void
print_d_0_eax(unsigned int value)6032 print_d_0_eax(unsigned int value)
6033 {
6034
6035 // State component bitmaps in general are described in 325462: Intel 64 and
6036 // IA-32 Architectures Software Developer's Manual Combined Volumes: 1, 2A,
6037 // 2B, 2C, 3A, 3B, and 3C, Volume 1: Basic Architecture, section 13.1:
6038 // XSAVE-Supported Features and State-Component Bitmaps. This leaf describes
6039 // which of the bits are actually supported by the hardware, and is described
6040 // better in 13.2: Enumeration of CPU Support for XSAVE Instructions and
6041 // XSAVE-Supported Features.
6042 //
6043 // These align with the supported features[] in print_d_n() for values > 1.
6044 //
6045 // See also print_12_1_ecx().
6046
6047 static named_item names[]
6048 = { { " XCR0 supported: x87 state" , 0, 0, bools },
6049 { " XCR0 supported: SSE state" , 1, 1, bools },
6050 { " XCR0 supported: AVX state" , 2, 2, bools },
6051 { " XCR0 supported: MPX BNDREGS" , 3, 3, bools },
6052 { " XCR0 supported: MPX BNDCSR" , 4, 4, bools },
6053 { " XCR0 supported: AVX-512 opmask" , 5, 5, bools },
6054 { " XCR0 supported: AVX-512 ZMM_Hi256" , 6, 6, bools },
6055 { " XCR0 supported: AVX-512 Hi16_ZMM" , 7, 7, bools },
6056 { " IA32_XSS supported: PT state" , 8, 8, bools },
6057 { " XCR0 supported: PKRU state" , 9, 9, bools },
6058 { " XCR0 supported: CET_U state" , 11, 11, bools },
6059 { " XCR0 supported: CET_S state" , 12, 12, bools },
6060 { " IA32_XSS supported: HDC state" , 13, 13, bools },
6061 { " IA32_XSS supported: UINTR state" , 14, 14, bools },
6062 { " LBR supported" , 15, 15, bools },
6063 { " IA32_XSS supported: HWP state" , 16, 16, bools },
6064 { " XTILECFG supported" , 17, 17, bools },
6065 { " XTILEDATA supported" , 18, 18, bools },
6066 };
6067
6068 print_names(value, names, LENGTH(names),
6069 /* max_len => */ 39);
6070 }
6071
6072 static void
print_d_0_edx(unsigned int value UNUSED)6073 print_d_0_edx(unsigned int value UNUSED)
6074 {
6075 // Upper 32 bits of XCR0: Currently all bits reserved.
6076
6077 // See also print_12_1_edx().
6078 }
6079
6080 static void
print_d_1_eax(unsigned int value)6081 print_d_1_eax(unsigned int value)
6082 {
6083 static named_item names[]
6084 = { { "XSAVEOPT instruction" , 0, 0, bools },
6085 { "XSAVEC instruction" , 1, 1, bools },
6086 { "XGETBV instruction" , 2, 2, bools },
6087 { "XSAVES/XRSTORS instructions" , 3, 3, bools },
6088 { "XFD: extended feature disable supported" , 4, 4, bools },
6089 };
6090
6091 print_names(value, names, LENGTH(names),
6092 /* max_len => */ 43);
6093 }
6094
6095 static void
print_d_n_ecx(unsigned int value)6096 print_d_n_ecx(unsigned int value)
6097 {
6098 static ccstring which[] = { "XCR0 (user state)",
6099 "IA32_XSS (supervisor state)" };
6100
6101 static named_item names[]
6102 = { { "supported in IA32_XSS or XCR0" , 0, 0, which },
6103 { "64-byte alignment in compacted XSAVE" , 1, 1, bools },
6104 { "XFD faulting supported" , 2, 2, bools },
6105 };
6106
6107 print_names(value, names, LENGTH(names),
6108 /* max_len => */ 40);
6109 }
6110
6111 static void
print_d_n(const unsigned int words[WORD_NUM],unsigned int try)6112 print_d_n(const unsigned int words[WORD_NUM],
6113 unsigned int try)
6114 {
6115 // The XSAVE areas are explained in 325462: Intel 64 and IA-32 Architectures
6116 // Software Developer's Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B, and
6117 // 3C, Volume 1: Basic Architecture, section 13.1: XSAVE-Supported Features
6118 // and State-Component Bitmaps.
6119 //
6120 // These align with the supported feature names[] in print_d_0_eax() for
6121 // values > 1.
6122
6123 static ccstring features[64] = { /* 0 => */ "internal error",
6124 /* 1 => */ "internal error",
6125 /* 2 => */ "AVX/YMM",
6126 /* 3 => */ "MPX BNDREGS",
6127 /* 4 => */ "MPX BNDCSR",
6128 /* 5 => */ "AVX-512 opmask",
6129 /* 6 => */ "AVX-512 ZMM_Hi256",
6130 /* 7 => */ "AVX-512 Hi16_ZMM",
6131 /* 8 => */ "PT",
6132 /* 9 => */ "PKRU",
6133 /* 10 => */ "unknown",
6134 /* 11 => */ "CET_U state",
6135 /* 12 => */ "CET_S state",
6136 /* 13 => */ "HDC",
6137 /* 14 => */ "UINTR",
6138 /* 15 => */ "LBR",
6139 /* 16 => */ "HWP state",
6140 /* 17 => */ "XTILECFG",
6141 /* 18 => */ "XTILEDATA",
6142 /* 19 => */ "unknown",
6143 /* 20 => */ "unknown",
6144 /* 21 => */ "unknown",
6145 /* 22 => */ "unknown",
6146 /* 23 => */ "unknown",
6147 /* 24 => */ "unknown",
6148 /* 25 => */ "unknown",
6149 /* 26 => */ "unknown",
6150 /* 27 => */ "unknown",
6151 /* 28 => */ "unknown",
6152 /* 29 => */ "unknown",
6153 /* 30 => */ "unknown",
6154 /* 31 => */ "unknown",
6155 /* 32 => */ "unknown",
6156 /* 33 => */ "unknown",
6157 /* 34 => */ "unknown",
6158 /* 35 => */ "unknown",
6159 /* 36 => */ "unknown",
6160 /* 37 => */ "unknown",
6161 /* 38 => */ "unknown",
6162 /* 39 => */ "unknown",
6163 /* 40 => */ "unknown",
6164 /* 41 => */ "unknown",
6165 /* 42 => */ "unknown",
6166 /* 43 => */ "unknown",
6167 /* 44 => */ "unknown",
6168 /* 45 => */ "unknown",
6169 /* 46 => */ "unknown",
6170 /* 47 => */ "unknown",
6171 /* 48 => */ "unknown",
6172 /* 49 => */ "unknown",
6173 /* 50 => */ "unknown",
6174 /* 51 => */ "unknown",
6175 /* 52 => */ "unknown",
6176 /* 53 => */ "unknown",
6177 /* 54 => */ "unknown",
6178 /* 55 => */ "unknown",
6179 /* 56 => */ "unknown",
6180 /* 57 => */ "unknown",
6181 /* 58 => */ "unknown",
6182 /* 59 => */ "unknown",
6183 /* 60 => */ "unknown",
6184 /* 61 => */ "unknown",
6185 /* 62 => */ "LWP", // AMD only
6186 /* 63 => */ "unknown" };
6187
6188 ccstring feature = features[try];
6189 int feature_pad = 17-strlen(feature);
6190
6191 if (try > 9) {
6192 printf(" %s features (0xd/0x%x):\n", feature, try);
6193 } else {
6194 printf(" %s features (0xd/%d):\n", feature, try);
6195 }
6196 printf(" %s save state byte size%*s = 0x%08x (%u)\n",
6197 feature, feature_pad, "",
6198 words[WORD_EAX], words[WORD_EAX]);
6199 printf(" %s save state byte offset%*s = 0x%08x (%u)\n",
6200 feature, feature_pad, "",
6201 words[WORD_EBX], words[WORD_EBX]);
6202 print_d_n_ecx(words[WORD_ECX]);
6203 }
6204
6205 static void
print_f_0_edx(unsigned int value)6206 print_f_0_edx(unsigned int value)
6207 {
6208 static named_item names[]
6209 = { { "supports L3 cache QoS monitoring" , 1, 1, bools },
6210 };
6211
6212 print_names(value, names, LENGTH(names),
6213 /* max_len => */ 0);
6214 }
6215
6216 static void
print_f_1_eax(unsigned int value)6217 print_f_1_eax(unsigned int value)
6218 {
6219 static named_item names[]
6220 = { { "IA32_QM_CTR bit 61 is overflow" , 8, 8, bools },
6221 };
6222
6223 print_names(value, names, LENGTH(names),
6224 /* max_len => */ 43);
6225 }
6226
6227 static void
print_f_1_edx(unsigned int value)6228 print_f_1_edx(unsigned int value)
6229 {
6230 static named_item names[]
6231 = { { "supports L3 occupancy monitoring" , 0, 0, bools },
6232 { "supports L3 total bandwidth monitoring" , 1, 1, bools },
6233 { "supports L3 local bandwidth monitoring" , 2, 2, bools },
6234 };
6235
6236 print_names(value, names, LENGTH(names),
6237 /* max_len => */ 43);
6238 }
6239
6240 static void
print_10_0_ebx(unsigned int value)6241 print_10_0_ebx(unsigned int value)
6242 {
6243 static named_item names[]
6244 = { { "L3 cache allocation technology supported", 1, 1, bools },
6245 { "L2 cache allocation technology supported", 2, 2, bools },
6246 { "memory bandwidth allocation supported" , 3, 3, bools },
6247 };
6248
6249 print_names(value, names, LENGTH(names),
6250 /* max_len => */ 0);
6251 }
6252
6253 static void
print_10_n_eax(unsigned int value)6254 print_10_n_eax(unsigned int value)
6255 {
6256 static named_item names[]
6257 = { { "length of capacity bit mask" , 0, 4, MINUS1_IMAGES },
6258 };
6259
6260 print_names(value, names, LENGTH(names),
6261 /* max_len => */ 40);
6262 }
6263
6264 static void
print_10_n_ecx(unsigned int value)6265 print_10_n_ecx(unsigned int value)
6266 {
6267 static named_item names[]
6268 = { { "infrequent updates of COS" , 1, 1, bools },
6269 { "code and data prioritization supported" , 2, 2, bools },
6270 };
6271
6272 print_names(value, names, LENGTH(names),
6273 /* max_len => */ 40);
6274 }
6275
6276 static void
print_10_n_edx(unsigned int value)6277 print_10_n_edx(unsigned int value)
6278 {
6279 static named_item names[]
6280 = { { "highest COS number supported" , 0, 15, NIL_IMAGES },
6281 };
6282
6283 print_names(value, names, LENGTH(names),
6284 /* max_len => */ 40);
6285 }
6286
6287 static void
print_10_3_eax(unsigned int value)6288 print_10_3_eax(unsigned int value)
6289 {
6290 static named_item names[]
6291 = { { "maximum throttling value" , 0, 11, MINUS1_IMAGES },
6292 };
6293
6294 print_names(value, names, LENGTH(names),
6295 /* max_len => */ 40);
6296 }
6297
6298 static void
print_10_3_ecx(unsigned int value)6299 print_10_3_ecx(unsigned int value)
6300 {
6301 static named_item names[]
6302 = { { "per-thread MBA control" , 0, 0, bools },
6303 { "delay values are linear" , 2, 2, bools },
6304 };
6305
6306 print_names(value, names, LENGTH(names),
6307 /* max_len => */ 40);
6308 }
6309
6310 static void
print_12_0_eax(unsigned int value)6311 print_12_0_eax(unsigned int value)
6312 {
6313 static named_item names[]
6314 = { { "SGX1 supported" , 0, 0, bools },
6315 { "SGX2 supported" , 1, 1, bools },
6316 { "SGX ENCLV E*VIRTCHILD, ESETCONTEXT" , 5, 5, bools },
6317 { "SGX ENCLS ETRACKC, ERDINFO, ELDBC, ELDUC", 6, 6, bools },
6318 };
6319
6320 print_names(value, names, LENGTH(names),
6321 /* max_len => */ 38);
6322 }
6323
6324 static void
print_12_0_ebx(unsigned int value)6325 print_12_0_ebx(unsigned int value)
6326 {
6327 // MISCSELECT is described in Table 38-4: Bit Vector Layout of MISCSELECT
6328 // Field of Extended Information.
6329
6330 static named_item names[]
6331 = { { "MISCSELECT.EXINFO supported: #PF & #GP" , 0, 0, bools },
6332 { "MISCSELECT.CPINFO supported: #CP" , 1, 1, bools },
6333 };
6334
6335 print_names(value, names, LENGTH(names),
6336 /* max_len => */ 38);
6337 }
6338
6339 static void
print_12_0_edx(unsigned int value)6340 print_12_0_edx(unsigned int value)
6341 {
6342 static named_item names[]
6343 = { { "MaxEnclaveSize_Not64 (log2)" , 0, 7, NIL_IMAGES },
6344 { "MaxEnclaveSize_64 (log2)" , 8, 15, NIL_IMAGES },
6345 };
6346
6347 print_names(value, names, LENGTH(names),
6348 /* max_len => */ 38);
6349 }
6350
6351 static void
print_12_1_eax(unsigned int value)6352 print_12_1_eax(unsigned int value)
6353 {
6354 // SECS.ATTRIBUTES are described in 325462: Intel 64 and IA-32 Architectures
6355 // Software Developer's Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B, 3C,
6356 // 3D, and 4, Volume 3: System Programming Guide, section 33.7.1: ATTRIBUTES.
6357 //
6358 // eax contains ATTRIBUTES[31:0].
6359
6360 static named_item names[]
6361 = { { "enclave initialized by EINIT" , 0, 0, bools },
6362 { "enclave debugger read/write permission" , 1, 1, bools },
6363 { "enclave 64-bit mode" , 2, 2, bools },
6364 { "provisioning key available" , 4, 4, bools },
6365 { "EINIT token key available" , 5, 5, bools },
6366 { "CET attributes enabled" , 6, 6, bools },
6367 { "KSS key separation & sharing enabled" , 7, 7, bools },
6368 };
6369
6370 print_names(value, names, LENGTH(names),
6371 /* max_len => */ 38);
6372 }
6373
6374 static void
print_12_1_ebx(unsigned int value UNUSED)6375 print_12_1_ebx(unsigned int value UNUSED)
6376 {
6377 // SECS.ATTRIBUTES are described in 325462: Intel 64 and IA-32 Architectures
6378 // Software Developer's Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B, 3C,
6379 // 3D, and 4, Volume 3: System Programming Guide, section 33.7.1: ATTRIBUTES.
6380 //
6381 // ebx contains ATTRIBUTES[63:32].
6382
6383 // Currently all bits reserved.
6384 }
6385
6386 static void
print_12_1_ecx(unsigned int value)6387 print_12_1_ecx(unsigned int value)
6388 {
6389 // SECS.ATTRIBUTES are described in 325462: Intel 64 and IA-32 Architectures
6390 // Software Developer's Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B, 3C,
6391 // 3D, and 4, Volume 3: System Programming Guide, section 33.7.1: ATTRIBUTES.
6392 //
6393 // ebx contains ATTRIBUTES[95:64], which is XFRM[31:0] (described in Volume
6394 // 3, 37.7.2.1 SECS.ATTRIBUTES.XFVM), which is equivalent to XCR0[31:0]
6395 // (described in Volume 1, 13.1 XSAVE-Supported Features and State-Component
6396 // Bitmaps).
6397 //
6398 // See also print_d_0_eax().
6399
6400 static named_item names[]
6401 = { { " XCR0 supported: x87 state" , 0, 0, bools },
6402 { " XCR0 supported: SSE state" , 1, 1, bools },
6403 { " XCR0 supported: AVX state" , 2, 2, bools },
6404 { " XCR0 supported: MPX BNDREGS" , 3, 3, bools },
6405 { " XCR0 supported: MPX BNDCSR" , 4, 4, bools },
6406 { " XCR0 supported: AVX-512 opmask" , 5, 5, bools },
6407 { " XCR0 supported: AVX-512 ZMM_Hi256" , 6, 6, bools },
6408 { " XCR0 supported: AVX-512 Hi16_ZMM" , 7, 7, bools },
6409 { " IA32_XSS supported: PT state" , 8, 8, bools },
6410 { " XCR0 supported: PKRU state" , 9, 9, bools },
6411 { " XCR0 supported: CET_U state" , 11, 11, bools },
6412 { " XCR0 supported: CET_S state" , 12, 12, bools },
6413 { " IA32_XSS supported: HDC state" , 13, 13, bools },
6414 { " IA32_XSS supported: UINTR state" , 14, 14, bools },
6415 { " LBR supported" , 15, 15, bools },
6416 { " IA32_XSS supported: HWP state" , 16, 16, bools },
6417 { " XTILECFG supported" , 17, 17, bools },
6418 { " XTILEDATA supported" , 18, 18, bools },
6419 };
6420
6421 print_names(value, names, LENGTH(names),
6422 /* max_len => */ 38);
6423 }
6424
6425 static void
print_12_1_edx(unsigned int value UNUSED)6426 print_12_1_edx(unsigned int value UNUSED)
6427 {
6428 // SECS.ATTRIBUTES are described in 325462: Intel 64 and IA-32 Architectures
6429 // Software Developer's Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B, 3C,
6430 // 3D, and 4, Volume 3: System Programming Guide, section 33.7.1: ATTRIBUTES.
6431 //
6432 // ebx contains ATTRIBUTES[95:64], which is XFRM[63:32] (described in Volume
6433 // 3, 37.7.2.1 SECS.ATTRIBUTES.XFVM), which is equivalent to XCR0[63:32]
6434 // (described in Volume 1, 13.1 XSAVE-Supported Features and State-Component
6435 // Bitmaps).
6436 //
6437 // See also print_d_0_edx().
6438
6439 // Currently all bits reserved.
6440 }
6441
6442 static void
print_12_n_ecx(unsigned int value)6443 print_12_n_ecx(unsigned int value)
6444 {
6445 static ccstring props[1<<4]
6446 = { /* 0 => */ "enumerated as 0",
6447 /* 1 => */ "confidentiality & integrity protection",
6448 /* 2 => */ "confidentiality protection only" };
6449
6450 static named_item names[]
6451 = { { "section property" , 0, 3, props },
6452 };
6453
6454 print_names(value, names, LENGTH(names),
6455 /* max_len => */ 23);
6456 }
6457
6458 static void
print_14_0_ebx(unsigned int value)6459 print_14_0_ebx(unsigned int value)
6460 {
6461 static named_item names[]
6462 = { { "IA32_RTIT_CR3_MATCH is accessible" , 0, 0, bools },
6463 { "configurable PSB & cycle-accurate" , 1, 1, bools },
6464 { "IP & TraceStop filtering; PT preserve" , 2, 2, bools },
6465 { "MTC timing packet; suppress COFI-based" , 3, 3, bools },
6466 { "PTWRITE support" , 4, 4, bools },
6467 { "power event trace support" , 5, 5, bools },
6468 { "PSB/PMI preservation support" , 6, 6, bools },
6469 };
6470
6471 print_names(value, names, LENGTH(names),
6472 /* max_len => */ 38);
6473 }
6474
6475 static void
print_14_0_ecx(unsigned int value)6476 print_14_0_ecx(unsigned int value)
6477 {
6478 static named_item names[]
6479 = { { "ToPA output scheme support" , 0, 0, bools },
6480 { "ToPA can hold many output entries" , 1, 1, bools },
6481 { "single-range output scheme support" , 2, 2, bools },
6482 { "output to trace transport" , 3, 3, bools },
6483 { "IP payloads have LIP values & CS" , 31, 31, bools },
6484 };
6485
6486 print_names(value, names, LENGTH(names),
6487 /* max_len => */ 38);
6488 }
6489
6490 static void
print_14_1_eax(unsigned int value)6491 print_14_1_eax(unsigned int value)
6492 {
6493 static named_item names[]
6494 = { { "configurable address ranges" , 0, 2, NIL_IMAGES },
6495 { "supported MTC periods bitmask" , 16, 31, NIL_IMAGES },
6496 };
6497
6498 print_names(value, names, LENGTH(names),
6499 /* max_len => */ 38);
6500 }
6501
6502 static void
print_14_1_ebx(unsigned int value)6503 print_14_1_ebx(unsigned int value)
6504 {
6505 static named_item names[]
6506 = { { "supported cycle threshold bitmask" , 0, 15, NIL_IMAGES },
6507 { "supported config PSB freq bitmask" , 16, 31, NIL_IMAGES },
6508 };
6509
6510 print_names(value, names, LENGTH(names),
6511 /* max_len => */ 38);
6512 }
6513
6514 static void
print_16_eax(unsigned int value)6515 print_16_eax(unsigned int value)
6516 {
6517 static named_item names[]
6518 = { { "Core Base Frequency (MHz)" , 0, 15, NIL_IMAGES },
6519 };
6520
6521 print_names(value, names, LENGTH(names),
6522 /* max_len => */ 0);
6523 }
6524
6525 static void
print_16_ebx(unsigned int value)6526 print_16_ebx(unsigned int value)
6527 {
6528 static named_item names[]
6529 = { { "Core Maximum Frequency (MHz)" , 0, 15, NIL_IMAGES },
6530 };
6531
6532 print_names(value, names, LENGTH(names),
6533 /* max_len => */ 0);
6534 }
6535
6536 static void
print_16_ecx(unsigned int value)6537 print_16_ecx(unsigned int value)
6538 {
6539 static named_item names[]
6540 = { { "Bus (Reference) Frequency (MHz)" , 0, 15, NIL_IMAGES },
6541 };
6542
6543 print_names(value, names, LENGTH(names),
6544 /* max_len => */ 0);
6545 }
6546
6547 static void
print_17_0_ebx(unsigned int value)6548 print_17_0_ebx(unsigned int value)
6549 {
6550 static ccstring schemes[] = { /* 0 => */ "assigned by intel",
6551 /* 1 => */ "industry standard" };
6552
6553 static named_item names[]
6554 = { { "vendor id" , 0, 15, NIL_IMAGES },
6555 { "vendor scheme" , 16, 16, schemes },
6556 };
6557
6558 print_names(value, names, LENGTH(names),
6559 /* max_len => */ 0);
6560 }
6561
6562 static void
print_18_n_ebx(unsigned int value)6563 print_18_n_ebx(unsigned int value)
6564 {
6565 static ccstring parts[1<<3] = { /* 0 => */ "soft between logical processors",
6566 /* 1 => */ NULL,
6567 /* 2 => */ NULL,
6568 /* 3 => */ NULL,
6569 /* 4 => */ NULL,
6570 /* 5 => */ NULL,
6571 /* 6 => */ NULL,
6572 /* 7 => */ NULL };
6573
6574 static named_item names[]
6575 = { { "4KB page size entries supported" , 0, 0, bools },
6576 { "2MB page size entries supported" , 1, 1, bools },
6577 { "4MB page size entries supported" , 2, 2, bools },
6578 { "1GB page size entries supported" , 3, 3, bools },
6579 { "partitioning" , 8, 10, parts },
6580 { "ways of associativity" , 16, 31, NIL_IMAGES },
6581 };
6582
6583 print_names(value, names, LENGTH(names),
6584 /* max_len => */ 0);
6585 }
6586
6587 static void
print_18_n_edx(unsigned int value)6588 print_18_n_edx(unsigned int value)
6589 {
6590 static ccstring tlbs[1<<5] = { /* 00000b => */ "invalid (0)",
6591 /* 00001b => */ "data TLB",
6592 /* 00010b => */ "instruction TLB",
6593 /* 00011b => */ "unified TLB",
6594 /* 00100b => */ "load-only TLB",
6595 /* 00101b => */ "store-only TLB" };
6596
6597 static named_item names[]
6598 = { { "translation cache type" , 0, 4, tlbs },
6599 { "translation cache level" , 5, 7, MINUS1_IMAGES },
6600 { "fully associative" , 8, 8, bools },
6601 { "maximum number of addressible IDs" , 14, 25, NIL_IMAGES },
6602 };
6603
6604 print_names(value, names, LENGTH(names),
6605 /* max_len => */ 0);
6606 }
6607
6608 static void
print_19_eax(unsigned int value)6609 print_19_eax(unsigned int value)
6610 {
6611 static named_item names[]
6612 = { { "CPL0-only restriction supported" , 0, 0, bools },
6613 { "no-encrypt restriction supported" , 1, 1, bools },
6614 { "no-decrypt restriction supported" , 2, 2, bools },
6615 };
6616
6617 print_names(value, names, LENGTH(names),
6618 /* max_len => */ 32);
6619 }
6620
6621 static void
print_19_ebx(unsigned int value)6622 print_19_ebx(unsigned int value)
6623 {
6624 static named_item names[]
6625 = { { "AESKLE: AES instructions" , 0, 0, bools },
6626 { "AES wide instructions" , 2, 2, bools },
6627 { "MSRs & IWKEY backups" , 4, 4, bools },
6628 };
6629
6630 print_names(value, names, LENGTH(names),
6631 /* max_len => */ 32);
6632 }
6633
6634 static void
print_19_ecx(unsigned int value)6635 print_19_ecx(unsigned int value)
6636 {
6637 static named_item names[]
6638 = { { "LOADIWKEY NoBackup parameter" , 0, 0, bools },
6639 { "IWKEY randomization supported" , 1, 1, bools },
6640 };
6641
6642 print_names(value, names, LENGTH(names),
6643 /* max_len => */ 32);
6644 }
6645
6646 static void
print_1a_0_eax(unsigned int value)6647 print_1a_0_eax(unsigned int value)
6648 {
6649 static ccstring coretypes[1<<8] = { /* 00h-0fh => */ NULL, NULL, NULL, NULL,
6650 NULL, NULL, NULL, NULL,
6651 NULL, NULL, NULL, NULL,
6652 NULL, NULL, NULL, NULL,
6653 /* 10h-1fh => */ NULL, NULL, NULL, NULL,
6654 NULL, NULL, NULL, NULL,
6655 NULL, NULL, NULL, NULL,
6656 NULL, NULL, NULL, NULL,
6657 /* 20h => */ "Intel Atom",
6658 /* 21h-2fh => */ NULL, NULL, NULL,
6659 NULL, NULL, NULL, NULL,
6660 NULL, NULL, NULL, NULL,
6661 NULL, NULL, NULL, NULL,
6662 /* 30h-3fh => */ NULL, NULL, NULL, NULL,
6663 NULL, NULL, NULL, NULL,
6664 NULL, NULL, NULL, NULL,
6665 NULL, NULL, NULL, NULL,
6666 /* 40h => */ "Intel Core" };
6667
6668 static named_item names[]
6669 = { { "native model ID of core" , 0, 23, NIL_IMAGES },
6670 { "core type" , 24, 31, coretypes },
6671 };
6672
6673 print_names(value, names, LENGTH(names),
6674 /* max_len => */ 0);
6675 }
6676
6677 static void
print_1b_n_eax(unsigned int value)6678 print_1b_n_eax(unsigned int value)
6679 {
6680 static ccstring types[1<<12] = { /* 0 => */ "invalid (0)",
6681 /* 1 => */ "target identifier (1)" };
6682
6683 static named_item names[]
6684 = { { "sub-leaf type" , 0, 11, types },
6685 };
6686
6687 print_names(value, names, LENGTH(names),
6688 /* max_len => */ 0);
6689 }
6690
6691 static void
print_1c_eax(unsigned int value)6692 print_1c_eax(unsigned int value)
6693 {
6694 static ccstring ipvs[1<<1] = { /* 0 => */ "EIP (0)",
6695 /* 1 => */ "LIP (1)" };
6696
6697 static named_item names[]
6698 = { { "IA32_LBR_DEPTH.DEPTH 8 supported" , 0, 0, bools },
6699 { "IA32_LBR_DEPTH.DEPTH 16 supported" , 1, 1, bools },
6700 { "IA32_LBR_DEPTH.DEPTH 24 supported" , 2, 2, bools },
6701 { "IA32_LBR_DEPTH.DEPTH 32 supported" , 3, 3, bools },
6702 { "IA32_LBR_DEPTH.DEPTH 40 supported" , 4, 4, bools },
6703 { "IA32_LBR_DEPTH.DEPTH 48 supported" , 5, 5, bools },
6704 { "IA32_LBR_DEPTH.DEPTH 56 supported" , 6, 6, bools },
6705 { "IA32_LBR_DEPTH.DEPTH 64 supported" , 7, 7, bools },
6706 { "deep C-state reset supported" , 30, 30, bools },
6707 { "LBR IP values contain" , 31, 31, ipvs },
6708 };
6709
6710 print_names(value, names, LENGTH(names),
6711 /* max_len => */ 33);
6712 }
6713
6714 static void
print_1c_ebx(unsigned int value)6715 print_1c_ebx(unsigned int value)
6716 {
6717 static named_item names[]
6718 = { { "CPL filtering supported" , 0, 0, bools },
6719 { "branch filtering supported" , 1, 1, bools },
6720 { "call-stack mode supported" , 2, 2, bools },
6721 };
6722
6723 print_names(value, names, LENGTH(names),
6724 /* max_len => */ 33);
6725 }
6726
6727 static void
print_1c_ecx(unsigned int value)6728 print_1c_ecx(unsigned int value)
6729 {
6730 static named_item names[]
6731 = { { "mispredict bit supported" , 0, 0, bools },
6732 { "timed LBRs supported" , 1, 1, bools },
6733 { "branch type field supported" , 2, 2, bools },
6734 };
6735
6736 print_names(value, names, LENGTH(names),
6737 /* max_len => */ 33);
6738 }
6739
6740 static void
print_1d_n_eax(unsigned int value)6741 print_1d_n_eax(unsigned int value)
6742 {
6743 static named_item names[]
6744 = { { "total_tile_bytes" , 0, 15, NIL_IMAGES },
6745 { "bytes_per_tile" , 16, 31, NIL_IMAGES },
6746 };
6747
6748 print_names(value, names, LENGTH(names),
6749 /* max_len => */ 16);
6750 }
6751
6752 static void
print_1d_n_ebx(unsigned int value)6753 print_1d_n_ebx(unsigned int value)
6754 {
6755 static named_item names[]
6756 = { { "bytes_per_row" , 0, 15, NIL_IMAGES },
6757 { "max_names" , 16, 31, NIL_IMAGES },
6758 };
6759
6760 print_names(value, names, LENGTH(names),
6761 /* max_len => */ 16);
6762 }
6763
6764 static void
print_1d_n_ecx(unsigned int value)6765 print_1d_n_ecx(unsigned int value)
6766 {
6767 static named_item names[]
6768 = { { "max_rows" , 0, 15, NIL_IMAGES },
6769 };
6770
6771 print_names(value, names, LENGTH(names),
6772 /* max_len => */ 16);
6773 }
6774
6775 static void
print_1e_ebx(unsigned int value)6776 print_1e_ebx(unsigned int value)
6777 {
6778 static named_item names[]
6779 = { { "tmul_maxk" , 0, 7, NIL_IMAGES },
6780 { "tmul_maxn" , 8, 23, NIL_IMAGES },
6781 };
6782
6783 print_names(value, names, LENGTH(names),
6784 /* max_len => */ 0);
6785 }
6786
6787 static void
print_20_ebx(unsigned int value)6788 print_20_ebx(unsigned int value)
6789 {
6790 /*
6791 ** The meanings of the bits correlate with the IA32_HRESET_ENABLE MSR bits.
6792 */
6793 static named_item names[]
6794 = { { "HRESET supported: EHFI history" , 0, 0, bools },
6795 };
6796
6797 print_names(value, names, LENGTH(names),
6798 /* max_len => */ 0);
6799 }
6800
6801 static void
print_20000001_edx(unsigned int value)6802 print_20000001_edx(unsigned int value)
6803 {
6804 // I found a vague reference to this leaf in Intel Xeon Phi Coprocessor
6805 // System Developers Guide, 4.2.17 CPUID: "0x20000001 for graphics function
6806 // information." But I found no document that specifies that information.
6807 // sandpile.org had the following bit.
6808
6809 static named_item names[]
6810 = { { "k1om" , 0, 0, bools },
6811 };
6812
6813 printf(" Xeon Phi graphics function features (0x20000001/edx):\n");
6814 print_names(value, names, LENGTH(names),
6815 /* max_len => */ 0);
6816 }
6817
6818 static void
print_hypervisor_1_eax_kvm(unsigned int reg,unsigned int value)6819 print_hypervisor_1_eax_kvm(unsigned int reg,
6820 unsigned int value)
6821 {
6822 // See Linux Documentation/virt/kvm/cpuid.rst.
6823
6824 static named_item names[]
6825 = { { "kvmclock available at MSR 0x11" , 0, 0, bools },
6826 { "delays unnecessary for PIO ops" , 1, 1, bools },
6827 { "mmu_op" , 2, 2, bools },
6828 { "kvmclock available at MSR 0x4b564d00" , 3, 3, bools },
6829 { "async pf enable available by MSR" , 4, 4, bools },
6830 { "steal clock supported" , 5, 5, bools },
6831 { "guest EOI optimization enabled" , 6, 6, bools },
6832 { "guest spinlock optimization enabled" , 7, 7, bools },
6833 { "guest TLB flush optimization enabled" , 9, 9, bools },
6834 { "async PF VM exit enable available by MSR", 10, 10, bools },
6835 { "guest send IPI optimization enabled" , 11, 11, bools },
6836 { "host HLT poll disable at MSR 0x4b564d05" , 12, 12, bools },
6837 { "guest sched yield optimization enabled" , 13, 13, bools },
6838 { "guest uses intrs for page ready APF evs" , 14, 14, bools },
6839 { "extended destination ID" , 15, 15, bools },
6840 { "map gpa range hypercall supported" , 16, 16, bools },
6841 { "MSR_KVM_MIGRATION_CONTROL supported" , 17, 17, bools },
6842 { "stable: no guest per-cpu warps expected" , 24, 24, bools },
6843 };
6844
6845 printf(" hypervisor features (0x%08x/eax):\n", reg);
6846 print_names(value, names, LENGTH(names),
6847 /* max_len => */ 0);
6848 }
6849
6850 static void
print_hypervisor_1_edx_kvm(unsigned int reg,unsigned int value)6851 print_hypervisor_1_edx_kvm(unsigned int reg,
6852 unsigned int value)
6853 {
6854 static named_item names[]
6855 = { { "realtime hint: no unbound preemption" , 0, 0, bools },
6856 };
6857
6858 printf(" hypervisor features (0x%08x/edx):\n", reg);
6859 print_names(value, names, LENGTH(names),
6860 /* max_len => */ 0);
6861 }
6862
6863 static void
print_hypervisor_1_eax_acrn(unsigned int reg,unsigned int value)6864 print_hypervisor_1_eax_acrn(unsigned int reg,
6865 unsigned int value)
6866 {
6867 // See Linux Documentation/virt/acrn/cpuid.rst.
6868
6869 static named_item names[]
6870 = { { "guest VM is a privileged VM" , 0, 0, bools },
6871 };
6872
6873 printf(" hypervisor features (0x%08x/eax):\n", reg);
6874 print_names(value, names, LENGTH(names),
6875 /* max_len => */ 0);
6876 }
6877
6878 static void
print_hypervisor_2_ecx_xen(unsigned int value)6879 print_hypervisor_2_ecx_xen(unsigned int value)
6880 {
6881 static named_item names[]
6882 = { { "MMU_PT_UPDATE_PRESERVE_AD supported" , 0, 0, bools },
6883 };
6884
6885 print_names(value, names, LENGTH(names),
6886 /* max_len => */ 0);
6887 }
6888
6889 static void
print_hypervisor_3_eax_xen(unsigned int value)6890 print_hypervisor_3_eax_xen(unsigned int value)
6891 {
6892 static named_item names[]
6893 = { { "vtsc" , 0, 0, bools },
6894 { "host tsc is safe" , 1, 1, bools },
6895 { "boot cpu has RDTSCP" , 2, 2, bools },
6896 };
6897
6898 print_names(value, names, LENGTH(names),
6899 /* max_len => */ 0);
6900 }
6901
6902 static void
print_hypervisor_3_eax_microsoft(unsigned int reg,unsigned int value)6903 print_hypervisor_3_eax_microsoft(unsigned int reg,
6904 unsigned int value)
6905 {
6906 // Bits correspond to the HV_PARTITION_PRIVILEGE_MASK.
6907 // See: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/datatypes/hv_partition_privilege_mask
6908 static named_item names[]
6909 = { { "VP run time" , 0, 0, bools },
6910 { "partition reference counter" , 1, 1, bools },
6911 { "basic synIC MSRs" , 2, 2, bools },
6912 { "synthetic timer MSRs" , 3, 3, bools },
6913 { "APIC access MSRs" , 4, 4, bools },
6914 { "hypercall MSRs" , 5, 5, bools },
6915 { "access virtual process index MSR" , 6, 6, bools },
6916 { "virtual system reset MSR" , 7, 7, bools },
6917 { "map/unmap statistics pages MSR" , 8, 8, bools },
6918 { "reference TSC access" , 9, 9, bools },
6919 { "guest idle state MSR" , 10, 10, bools },
6920 { "TSC/APIC frequency MSRs" , 11, 11, bools },
6921 { "guest debugging MSRs" , 12, 12, bools },
6922 { "reenlightenment MSRs" , 13, 13, bools },
6923 { "invariant TSC MSR" , 15, 15, bools }, // LX*
6924 };
6925
6926 printf(" hypervisor feature identification (0x%08x/eax):\n", reg);
6927 print_names(value, names, LENGTH(names),
6928 /* max_len => */ 0);
6929 }
6930
6931 static void
print_hypervisor_3_ebx_microsoft(unsigned int reg,unsigned int value)6932 print_hypervisor_3_ebx_microsoft(unsigned int reg,
6933 unsigned int value)
6934 {
6935 static named_item names[]
6936 = { { "CreatePartitions" , 0, 0, bools },
6937 { "AccessPartitionId" , 1, 1, bools },
6938 { "AccessMemoryPool" , 2, 2, bools },
6939 { "AdjustMessageBuffers" , 3, 3, bools },
6940 { "PostMessages" , 4, 4, bools },
6941 { "SignalEvents" , 5, 5, bools },
6942 { "CreatePort" , 6, 6, bools },
6943 { "ConnectPort" , 7, 7, bools },
6944 { "AccessStats" , 8, 8, bools },
6945 { "Debugging" , 11, 11, bools },
6946 { "CPUManagement" , 12, 12, bools },
6947 { "ConfigureProfiler" , 13, 13, bools },
6948 { "AccessVSM" , 16, 16, bools },
6949 { "AccessVpRegisters" , 17, 17, bools },
6950 { "EnableExtendedHypercalls" , 20, 20, bools },
6951 { "StartVirtualProcessor" , 21, 21, bools },
6952 };
6953
6954 printf(" hypervisor partition creation flags (0x%08x/ebx):\n", reg);
6955 print_names(value, names, LENGTH(names),
6956 /* max_len => */ 0);
6957 }
6958
6959 static void
print_hypervisor_3_ecx_microsoft(unsigned int reg,unsigned int value)6960 print_hypervisor_3_ecx_microsoft(unsigned int reg,
6961 unsigned int value)
6962 {
6963 static named_item names[]
6964 = { { "maximum process power state" , 0, 3, NIL_IMAGES },
6965 };
6966
6967 printf(" hypervisor power management features (0x%08x/ecx):\n", reg);
6968 print_names(value, names, LENGTH(names),
6969 /* max_len => */ 0);
6970 }
6971
6972 static void
print_hypervisor_3_edx_microsoft(unsigned int reg,unsigned int value)6973 print_hypervisor_3_edx_microsoft(unsigned int reg,
6974 unsigned int value)
6975 {
6976 static named_item names[]
6977 = { { "MWAIT available" , 0, 0, bools },
6978 { "guest debugging support available" , 1, 1, bools },
6979 { "performance monitor support available" , 2, 2, bools },
6980 { "CPU dynamic partitioning events avail" , 3, 3, bools },
6981 { "hypercall XMM input parameters available", 4, 4, bools },
6982 { "virtual guest idle state available" , 5, 5, bools },
6983 { "hypervisor sleep state available" , 6, 6, bools },
6984 { "query NUMA distance available" , 7, 7, bools },
6985 { "determine timer frequency available" , 8, 8, bools },
6986 { "inject synthetic machine check available", 9, 9, bools },
6987 { "guest crash MSRs available" , 10, 10, bools },
6988 { "debug MSRs available" , 11, 11, bools },
6989 { "NPIEP available" , 12, 12, bools },
6990 { "disable hypervisor available" , 13, 13, bools },
6991 { "extended gva ranges for flush virt addrs", 14, 14, bools },
6992 { "hypercall XMM register return available" , 15, 15, bools },
6993 { "sint polling mode available" , 17, 17, bools },
6994 { "hypercall MSR lock available" , 18, 18, bools },
6995 { "use direct synthetic timers" , 19, 19, bools },
6996 };
6997
6998 printf(" hypervisor feature identification (0x%08x/edx):\n", reg);
6999 print_names(value, names, LENGTH(names),
7000 /* max_len => */ 0);
7001 }
7002
7003 static void
print_hypervisor_4_eax_xen(unsigned int reg,unsigned int value)7004 print_hypervisor_4_eax_xen(unsigned int reg,
7005 unsigned int value)
7006 {
7007 static named_item names[]
7008 = { { "virtualized APIC registers" , 0, 0, bools },
7009 { "virtualized x2APIC accesses" , 1, 1, bools },
7010 { "IOMMU mappings for other domain memory" , 2, 2, bools },
7011 { "vcpu id is valid" , 3, 3, bools },
7012 { "domain id is valid" , 4, 4, bools },
7013 };
7014
7015 printf(" HVM-specific parameters (0x%08x):\n", reg);
7016 print_names(value, names, LENGTH(names),
7017 /* max_len => */ 38);
7018 }
7019
7020 static void
print_hypervisor_4_eax_microsoft(unsigned int reg,unsigned int value)7021 print_hypervisor_4_eax_microsoft(unsigned int reg,
7022 unsigned int value)
7023 {
7024 static named_item names[]
7025 = { { "use hypercalls for AS switches" , 0, 0, bools },
7026 { "use hypercalls for local TLB flushes" , 1, 1, bools },
7027 { "use hypercalls for remote TLB flushes" , 2, 2, bools },
7028 { "use MSRs to access EOI, ICR, TPR" , 3, 3, bools },
7029 { "use MSRs to initiate system RESET" , 4, 4, bools },
7030 { "use relaxed timing" , 5, 5, bools },
7031 { "use DMA remapping" , 6, 6, bools },
7032 { "use interrupt remapping" , 7, 7, bools },
7033 { "use x2APIC MSRs" , 8, 8, bools },
7034 { "deprecate AutoEOI" , 9, 9, bools },
7035 { "use SyntheticClusterIpi hypercall" , 10, 10, bools },
7036 { "use ExProcessorMasks" , 11, 11, bools },
7037 { "hypervisor is nested with Hyper-V" , 12, 12, bools },
7038 { "use INT for MBEC system calls" , 13, 13, bools },
7039 { "use enlightened VMCS interface" , 14, 14, bools },
7040 };
7041
7042 printf(" hypervisor recommendations (0x%08x/eax):\n", reg);
7043 print_names(value, names, LENGTH(names),
7044 /* max_len => */ 0);
7045 }
7046
7047 static void
print_hypervisor_5_0_ebx_xen(unsigned int reg,unsigned int value)7048 print_hypervisor_5_0_ebx_xen(unsigned int reg,
7049 unsigned int value)
7050 {
7051 static named_item names[]
7052 = { { "maximum machine address width" , 0, 7, NIL_IMAGES },
7053 };
7054
7055 printf(" PV-specific parameters (0x%08x):\n", reg);
7056 print_names(value, names, LENGTH(names),
7057 /* max_len => */ 0);
7058 }
7059
7060 static void
print_hypervisor_6_eax_microsoft(unsigned int reg,unsigned int value)7061 print_hypervisor_6_eax_microsoft(unsigned int reg,
7062 unsigned int value)
7063 {
7064 static named_item names[]
7065 = { { "APIC overlay assist" , 0, 0, bools },
7066 { "MSR bitmaps" , 1, 1, bools },
7067 { "performance counters" , 2, 2, bools },
7068 { "second-level address translation" , 3, 3, bools },
7069 { "DMA remapping" , 4, 4, bools },
7070 { "interrupt remapping" , 5, 5, bools },
7071 { "memory patrol scrubber" , 6, 6, bools },
7072 { "DMA protection" , 7, 7, bools },
7073 { "HPET requested" , 8, 8, bools },
7074 { "synthetic timers are volatile" , 9, 9, bools },
7075 };
7076
7077 printf(" hypervisor hardware features used (0x%08x/eax):\n", reg);
7078 print_names(value, names, LENGTH(names),
7079 /* max_len => */ 0);
7080 }
7081
7082 static void
print_hypervisor_7_eax_microsoft(unsigned int value)7083 print_hypervisor_7_eax_microsoft(unsigned int value)
7084 {
7085 static named_item names[]
7086 = { { "StartLogicalProcessor" , 0, 0, bools },
7087 { "CreateRootvirtualProcessor" , 1, 1, bools },
7088 };
7089
7090 print_names(value, names, LENGTH(names),
7091 /* max_len => */ 0);
7092 }
7093
7094 static void
print_hypervisor_7_ebx_microsoft(unsigned int value)7095 print_hypervisor_7_ebx_microsoft(unsigned int value)
7096 {
7097 static named_item names[]
7098 = { { "ProcessorPowerManagement" , 0, 0, bools },
7099 { "MwaitIdleStates" , 1, 1, bools },
7100 { "LogicalProcessorIdling" , 2, 2, bools },
7101 };
7102
7103 print_names(value, names, LENGTH(names),
7104 /* max_len => */ 0);
7105 }
7106
7107 static void
print_hypervisor_8_eax_microsoft(unsigned int value)7108 print_hypervisor_8_eax_microsoft(unsigned int value)
7109 {
7110 static named_item names[]
7111 = { { "SvmSupported" , 0, 0, bools },
7112 { "MaxPasidSpacePasidCount" , 11, 31, NIL_IMAGES },
7113 };
7114
7115 print_names(value, names, LENGTH(names),
7116 /* max_len => */ 0);
7117 }
7118
7119 static void
print_hypervisor_9_eax_microsoft(unsigned int value)7120 print_hypervisor_9_eax_microsoft(unsigned int value)
7121 {
7122 static named_item names[]
7123 = { { "AccessSynicRegs" , 2, 2, bools },
7124 { "AccessIntrCtrlRegs" , 4, 4, bools },
7125 { "AccessHypercallMsrs" , 5, 5, bools },
7126 { "AccessVpIndex" , 6, 6, bools },
7127 { "AccessReenlightenmentControls" , 12, 12, bools },
7128 };
7129
7130 print_names(value, names, LENGTH(names),
7131 /* max_len => */ 0);
7132 }
7133
7134 static void
print_hypervisor_9_edx_microsoft(unsigned int value)7135 print_hypervisor_9_edx_microsoft(unsigned int value)
7136 {
7137 static named_item names[]
7138 = { { "XmmRegistersForFastHypercallAvailable" , 4, 4, bools },
7139 { "FastHypercallOutputAvailable" , 15, 15, bools },
7140 { "SintPoillingModeAvailable" , 17, 17, bools },
7141 };
7142
7143 print_names(value, names, LENGTH(names),
7144 /* max_len => */ 0);
7145 }
7146
7147 static void
print_hypervisor_a_eax_microsoft(unsigned int value)7148 print_hypervisor_a_eax_microsoft(unsigned int value)
7149 {
7150 static named_item names[]
7151 = { { "enlightened VMCS version (low)" , 0, 7, NIL_IMAGES },
7152 { "enlightened VMCS version (high)" , 8, 15, NIL_IMAGES },
7153 { "direct virtual flush hypercalls support" , 17, 17, bools },
7154 { "HvFlushGuestPhysicalAddress* hypercalls" , 18, 18, bools },
7155 { "enlightened MSR bitmap support" , 19, 19, bools },
7156 };
7157
7158 print_names(value, names, LENGTH(names),
7159 /* max_len => */ 0);
7160 }
7161
7162 static void
print_80000001_eax_amd(unsigned int value)7163 print_80000001_eax_amd(unsigned int value)
7164 {
7165 static named_item names[]
7166 = { { "family/generation" , 8, 11, NIL_IMAGES },
7167 { "model" , 4, 7, NIL_IMAGES },
7168 { "stepping id" , 0, 3, NIL_IMAGES },
7169 { "extended family" , 20, 27, NIL_IMAGES },
7170 { "extended model" , 16, 19, NIL_IMAGES },
7171 };
7172
7173 printf(" extended processor signature (0x80000001/eax):\n");
7174 print_names(value, names, LENGTH(names),
7175 /* max_len => */ 15);
7176
7177 unsigned int synth_family = Synth_Family(value);
7178 unsigned int synth_model = Synth_Model(value);
7179 printf(" (family synth) = 0x%x (%u)\n", synth_family, synth_family);
7180 printf(" (model synth) = 0x%x (%u)\n", synth_model, synth_model);
7181
7182 print_x_synth_amd(value);
7183 }
7184
7185 static void
print_80000001_eax_hygon(unsigned int value)7186 print_80000001_eax_hygon(unsigned int value)
7187 {
7188 static named_item names[]
7189 = { { "family/generation" , 8, 11, NIL_IMAGES },
7190 { "model" , 4, 7, NIL_IMAGES },
7191 { "stepping id" , 0, 3, NIL_IMAGES },
7192 { "extended family" , 20, 27, NIL_IMAGES },
7193 { "extended model" , 16, 19, NIL_IMAGES },
7194 };
7195
7196 printf(" extended processor signature (0x80000001/eax):\n");
7197 print_names(value, names, LENGTH(names),
7198 /* max_len => */ 15);
7199
7200 unsigned int synth_family = Synth_Family(value);
7201 unsigned int synth_model = Synth_Model(value);
7202 printf(" (family synth) = 0x%x (%u)\n", synth_family, synth_family);
7203 printf(" (model synth) = 0x%x (%u)\n", synth_model, synth_model);
7204
7205 print_x_synth_hygon(value);
7206 }
7207
7208 static void
print_80000001_eax_via(unsigned int value)7209 print_80000001_eax_via(unsigned int value)
7210 {
7211 static named_item names[]
7212 = { { "generation" , 8, 11, NIL_IMAGES },
7213 { "model" , 4, 7, NIL_IMAGES },
7214 { "stepping" , 0, 3, NIL_IMAGES },
7215 };
7216
7217 printf(" extended processor signature (0x80000001/eax):\n");
7218 print_names(value, names, LENGTH(names),
7219 /* max_len => */ 0);
7220
7221 print_x_synth_via(value);
7222 }
7223
7224 static void
print_80000001_eax_transmeta(unsigned int value)7225 print_80000001_eax_transmeta(unsigned int value)
7226 {
7227 static named_item names[]
7228 = { { "generation" , 8, 11, NIL_IMAGES },
7229 { "model" , 4, 7, NIL_IMAGES },
7230 { "stepping" , 0, 3, NIL_IMAGES },
7231 };
7232
7233 printf(" extended processor signature (0x80000001/eax):\n");
7234 print_names(value, names, LENGTH(names),
7235 /* max_len => */ 14);
7236
7237 ccstring synth = decode_synth_transmeta(value, NULL);
7238 printf(" (simple synth) = ");
7239 if (synth != NULL) {
7240 printf("%s", synth);
7241 }
7242 printf("\n");
7243 }
7244
7245 static void
print_80000001_eax(unsigned int value,vendor_t vendor)7246 print_80000001_eax(unsigned int value,
7247 vendor_t vendor)
7248 {
7249 switch (vendor) {
7250 case VENDOR_AMD:
7251 print_80000001_eax_amd(value);
7252 break;
7253 case VENDOR_VIA:
7254 print_80000001_eax_via(value);
7255 break;
7256 case VENDOR_TRANSMETA:
7257 print_80000001_eax_transmeta(value);
7258 break;
7259 case VENDOR_HYGON:
7260 print_80000001_eax_hygon(value);
7261 break;
7262 case VENDOR_INTEL:
7263 case VENDOR_CYRIX:
7264 case VENDOR_UMC:
7265 case VENDOR_NEXGEN:
7266 case VENDOR_RISE:
7267 case VENDOR_SIS:
7268 case VENDOR_NSC:
7269 case VENDOR_VORTEX:
7270 case VENDOR_RDC:
7271 case VENDOR_ZHAOXIN:
7272 case VENDOR_UNKNOWN:
7273 /* DO NOTHING */
7274 break;
7275 }
7276 }
7277
7278 static void
print_80000001_edx_intel(unsigned int value)7279 print_80000001_edx_intel(unsigned int value)
7280 {
7281 static named_item names[]
7282 = { { "SYSCALL and SYSRET instructions" , 11, 11, bools },
7283 { "execution disable" , 20, 20, bools },
7284 { "1-GB large page support" , 26, 26, bools },
7285 { "RDTSCP" , 27, 27, bools },
7286 { "64-bit extensions technology available" , 29, 29, bools },
7287 };
7288
7289 printf(" extended feature flags (0x80000001/edx):\n");
7290 print_names(value, names, LENGTH(names),
7291 /* max_len => */ 0);
7292 }
7293
7294 static void
print_80000001_edx_amd(unsigned int value)7295 print_80000001_edx_amd(unsigned int value)
7296 {
7297 static named_item names[]
7298 = { { "x87 FPU on chip" , 0, 0, bools },
7299 { "virtual-8086 mode enhancement" , 1, 1, bools },
7300 { "debugging extensions" , 2, 2, bools },
7301 { "page size extensions" , 3, 3, bools },
7302 { "time stamp counter" , 4, 4, bools },
7303 { "RDMSR and WRMSR support" , 5, 5, bools },
7304 { "physical address extensions" , 6, 6, bools },
7305 { "machine check exception" , 7, 7, bools },
7306 { "CMPXCHG8B inst." , 8, 8, bools },
7307 { "APIC on chip" , 9, 9, bools },
7308 { "SYSCALL and SYSRET instructions" , 11, 11, bools },
7309 { "memory type range registers" , 12, 12, bools },
7310 { "global paging extension" , 13, 13, bools },
7311 { "machine check architecture" , 14, 14, bools },
7312 { "conditional move/compare instruction" , 15, 15, bools },
7313 { "page attribute table" , 16, 16, bools },
7314 { "page size extension" , 17, 17, bools },
7315 { "multiprocessing capable" , 19, 19, bools },
7316 { "no-execute page protection" , 20, 20, bools },
7317 { "AMD multimedia instruction extensions" , 22, 22, bools },
7318 { "MMX Technology" , 23, 23, bools },
7319 { "FXSAVE/FXRSTOR" , 24, 24, bools },
7320 { "SSE extensions" , 25, 25, bools },
7321 { "1-GB large page support" , 26, 26, bools },
7322 { "RDTSCP" , 27, 27, bools },
7323 { "long mode (AA-64)" , 29, 29, bools },
7324 { "3DNow! instruction extensions" , 30, 30, bools },
7325 { "3DNow! instructions" , 31, 31, bools },
7326 };
7327
7328 printf(" extended feature flags (0x80000001/edx):\n");
7329 print_names(value, names, LENGTH(names),
7330 /* max_len => */ 0);
7331 }
7332
7333 static void
print_80000001_edx_cyrix_via(unsigned int value)7334 print_80000001_edx_cyrix_via(unsigned int value)
7335 {
7336 static named_item names[]
7337 = { { "x87 FPU on chip" , 0, 0, bools },
7338 { "virtual-8086 mode enhancement" , 1, 1, bools },
7339 { "debugging extensions" , 2, 2, bools },
7340 { "page size extensions" , 3, 3, bools },
7341 { "time stamp counter" , 4, 4, bools },
7342 { "RDMSR and WRMSR support" , 5, 5, bools },
7343 { "physical address extensions" , 6, 6, bools },
7344 { "machine check exception" , 7, 7, bools },
7345 { "CMPXCHG8B inst." , 8, 8, bools },
7346 { "APIC on chip" , 9, 9, bools },
7347 { "SYSCALL and SYSRET instructions" , 11, 11, bools },
7348 { "memory type range registers" , 12, 12, bools },
7349 { "global paging extension" , 13, 13, bools },
7350 { "machine check architecture" , 14, 14, bools },
7351 { "conditional move/compare instruction" , 15, 15, bools },
7352 { "page attribute table" , 16, 16, bools },
7353 { "page size extension" , 17, 17, bools },
7354 { "multiprocessing capable" , 19, 19, bools },
7355 { "AMD multimedia instruction extensions" , 22, 22, bools },
7356 { "MMX Technology" , 23, 23, bools },
7357 { "extended MMX" , 24, 24, bools },
7358 { "SSE extensions" , 25, 25, bools },
7359 { "AA-64" , 29, 29, bools },
7360 { "3DNow! instruction extensions" , 30, 30, bools },
7361 { "3DNow! instructions" , 31, 31, bools },
7362 };
7363
7364 printf(" extended feature flags (0x80000001/edx):\n");
7365 print_names(value, names, LENGTH(names),
7366 /* max_len => */ 0);
7367 }
7368
7369 static void
print_80000001_edx_transmeta(unsigned int value)7370 print_80000001_edx_transmeta(unsigned int value)
7371 {
7372 static named_item names[]
7373 = { { "x87 FPU on chip" , 0, 0, bools },
7374 { "virtual-8086 mode enhancement" , 1, 1, bools },
7375 { "debugging extensions" , 2, 2, bools },
7376 { "page size extensions" , 3, 3, bools },
7377 { "time stamp counter" , 4, 4, bools },
7378 { "RDMSR and WRMSR support" , 5, 5, bools },
7379 { "CMPXCHG8B inst." , 8, 8, bools },
7380 { "APIC on chip" , 9, 9, bools },
7381 { "memory type range registers" , 12, 12, bools },
7382 { "global paging extension" , 13, 13, bools },
7383 { "machine check architecture" , 14, 14, bools },
7384 { "conditional move/compare instruction" , 15, 15, bools },
7385 { "FP conditional move instructions" , 16, 16, bools },
7386 { "page size extension" , 17, 17, bools },
7387 { "AMD multimedia instruction extensions" , 22, 22, bools },
7388 { "MMX Technology" , 23, 23, bools },
7389 { "FXSAVE/FXRSTOR" , 24, 24, bools },
7390 };
7391
7392 printf(" extended feature flags (0x80000001/edx):\n");
7393 print_names(value, names, LENGTH(names),
7394 /* max_len => */ 0);
7395 }
7396
7397 static void
print_80000001_edx_nsc(unsigned int value)7398 print_80000001_edx_nsc(unsigned int value)
7399 {
7400 static named_item names[]
7401 = { { "x87 FPU on chip" , 0, 0, bools },
7402 { "virtual-8086 mode enhancement" , 1, 1, bools },
7403 { "debugging extensions" , 2, 2, bools },
7404 { "page size extensions" , 3, 3, bools },
7405 { "time stamp counter" , 4, 4, bools },
7406 { "RDMSR and WRMSR support" , 5, 5, bools },
7407 { "machine check exception" , 7, 7, bools },
7408 { "CMPXCHG8B inst." , 8, 8, bools },
7409 { "SYSCALL and SYSRET instructions" , 11, 11, bools },
7410 { "global paging extension" , 13, 13, bools },
7411 { "conditional move/compare instruction" , 15, 15, bools },
7412 { "FPU conditional move instruction" , 16, 16, bools },
7413 { "MMX Technology" , 23, 23, bools },
7414 { "6x86MX multimedia extensions" , 24, 24, bools },
7415 };
7416
7417 printf(" extended feature flags (0x80000001/edx):\n");
7418 print_names(value, names, LENGTH(names),
7419 /* max_len => */ 0);
7420 }
7421
7422 static void
print_80000001_edx(unsigned int value,vendor_t vendor)7423 print_80000001_edx(unsigned int value,
7424 vendor_t vendor)
7425 {
7426 switch (vendor) {
7427 case VENDOR_INTEL:
7428 print_80000001_edx_intel(value);
7429 break;
7430 case VENDOR_AMD:
7431 case VENDOR_HYGON:
7432 print_80000001_edx_amd(value);
7433 break;
7434 case VENDOR_CYRIX:
7435 case VENDOR_VIA:
7436 print_80000001_edx_cyrix_via(value);
7437 break;
7438 case VENDOR_TRANSMETA:
7439 print_80000001_edx_transmeta(value);
7440 break;
7441 case VENDOR_NSC:
7442 print_80000001_edx_nsc(value);
7443 break;
7444 case VENDOR_UMC:
7445 case VENDOR_NEXGEN:
7446 case VENDOR_RISE:
7447 case VENDOR_SIS:
7448 case VENDOR_VORTEX:
7449 case VENDOR_RDC:
7450 case VENDOR_ZHAOXIN:
7451 case VENDOR_UNKNOWN:
7452 /* DO NOTHING */
7453 break;
7454 }
7455 }
7456
7457 static void
print_80000001_ecx_amd(unsigned int value)7458 print_80000001_ecx_amd(unsigned int value)
7459 {
7460 static named_item names[]
7461 = { { "LAHF/SAHF supported in 64-bit mode" , 0, 0, bools },
7462 { "CMP Legacy" , 1, 1, bools },
7463 { "SVM: secure virtual machine" , 2, 2, bools },
7464 { "extended APIC space" , 3, 3, bools },
7465 { "AltMovCr8" , 4, 4, bools },
7466 { "LZCNT advanced bit manipulation" , 5, 5, bools },
7467 { "SSE4A support" , 6, 6, bools },
7468 { "misaligned SSE mode" , 7, 7, bools },
7469 { "3DNow! PREFETCH/PREFETCHW instructions" , 8, 8, bools },
7470 { "OS visible workaround" , 9, 9, bools },
7471 { "instruction based sampling" , 10, 10, bools },
7472 { "XOP support" , 11, 11, bools },
7473 { "SKINIT/STGI support" , 12, 12, bools },
7474 { "watchdog timer support" , 13, 13, bools },
7475 { "lightweight profiling support" , 15, 15, bools },
7476 { "4-operand FMA instruction" , 16, 16, bools },
7477 { "TCE: translation cache extension" , 17, 17, bools },
7478 { "NodeId MSR C001100C" , 19, 19, bools }, // LX*
7479 { "TBM support" , 21, 21, bools },
7480 { "topology extensions" , 22, 22, bools },
7481 { "core performance counter extensions" , 23, 23, bools },
7482 { "NB/DF performance counter extensions" , 24, 24, bools },
7483 { "data breakpoint extension" , 26, 26, bools },
7484 { "performance time-stamp counter support" , 27, 27, bools },
7485 { "LLC performance counter extensions" , 28, 28, bools },
7486 { "MWAITX/MONITORX supported" , 29, 29, bools },
7487 { "Address mask extension support" , 30, 30, bools },
7488 };
7489
7490 print_names(value, names, LENGTH(names),
7491 /* max_len => */ 0);
7492 }
7493
7494 static void
print_80000001_ecx_intel(unsigned int value)7495 print_80000001_ecx_intel(unsigned int value)
7496 {
7497 static named_item names[]
7498 = { { "LAHF/SAHF supported in 64-bit mode" , 0, 0, bools },
7499 { "LZCNT advanced bit manipulation" , 5, 5, bools },
7500 { "3DNow! PREFETCH/PREFETCHW instructions" , 8, 8, bools },
7501 };
7502
7503 print_names(value, names, LENGTH(names),
7504 /* max_len => */ 0);
7505 }
7506
7507 static void
print_80000001_ecx(unsigned int value,vendor_t vendor)7508 print_80000001_ecx(unsigned int value,
7509 vendor_t vendor)
7510 {
7511 switch (vendor) {
7512 case VENDOR_AMD:
7513 printf(" AMD feature flags (0x80000001/ecx):\n");
7514 print_80000001_ecx_amd(value);
7515 break;
7516 case VENDOR_INTEL:
7517 printf(" Intel feature flags (0x80000001/ecx):\n");
7518 print_80000001_ecx_intel(value);
7519 break;
7520 case VENDOR_HYGON:
7521 printf(" Hygon feature flags (0x80000001/ecx):\n");
7522 print_80000001_ecx_amd(value);
7523 break;
7524 case VENDOR_CYRIX:
7525 case VENDOR_VIA:
7526 case VENDOR_TRANSMETA:
7527 case VENDOR_UMC:
7528 case VENDOR_NEXGEN:
7529 case VENDOR_RISE:
7530 case VENDOR_SIS:
7531 case VENDOR_NSC:
7532 case VENDOR_VORTEX:
7533 case VENDOR_RDC:
7534 case VENDOR_ZHAOXIN:
7535 case VENDOR_UNKNOWN:
7536 /* DO NOTHING */
7537 break;
7538 }
7539 }
7540
7541 static void
print_80000001_ebx_amd(unsigned int value,unsigned int val_1_eax)7542 print_80000001_ebx_amd(unsigned int value,
7543 unsigned int val_1_eax)
7544 {
7545 unsigned int max_len = 0;
7546
7547 if (__F(val_1_eax) == _XF(0) + _F(15)
7548 && __M(val_1_eax) < _XM(4) + _M(0)) {
7549 static named_item names[]
7550 = { { "raw" , 0, 31, NIL_IMAGES },
7551 { "BrandId" , 0, 16, NIL_IMAGES },
7552 { "BrandTableIndex" , 6, 12, NIL_IMAGES },
7553 { "NN" , 0, 6, NIL_IMAGES },
7554 };
7555
7556 printf(" extended brand id (0x80000001/ebx):\n");
7557 print_names(value, names, LENGTH(names),
7558 /* max_len => */ 0);
7559 } else if (__F(val_1_eax) == _XF(0) + _F(15)
7560 && __M(val_1_eax) >= _XM(4) + _M(0)) {
7561 static named_item names[]
7562 = { { "raw" , 0, 31, NIL_IMAGES },
7563 { "BrandId" , 0, 16, NIL_IMAGES },
7564 { "PwrLmt:high" , 6, 8, NIL_IMAGES },
7565 { "PwrLmt:low" , 14, 14, NIL_IMAGES },
7566 { "BrandTableIndex" , 9, 13, NIL_IMAGES },
7567 { "NN:high" , 15, 15, NIL_IMAGES },
7568 { "NN:low" , 0, 5, NIL_IMAGES },
7569 };
7570
7571 printf(" extended brand id (0x80000001/ebx):\n");
7572 print_names(value, names, LENGTH(names),
7573 /* max_len => */ 0);
7574 } else if (__F(val_1_eax) == _XF(1) + _F(15)
7575 || __F(val_1_eax) == _XF(2) + _F(15)) {
7576 static named_item names[]
7577 = { { "raw" , 0, 31, NIL_IMAGES },
7578 { "BrandId" , 0, 15, NIL_IMAGES },
7579 { "str1" , 11, 14, NIL_IMAGES },
7580 { "str2" , 0, 3, NIL_IMAGES },
7581 { "PartialModel" , 4, 10, NIL_IMAGES },
7582 { "PG" , 15, 15, NIL_IMAGES },
7583 };
7584
7585 printf(" extended brand id (0x80000001/ebx):\n");
7586 max_len = 12;
7587 print_names(value, names, LENGTH(names),
7588 /* max_len => */ max_len);
7589 } else {
7590 static named_item names[]
7591 = { { "raw" , 0, 31, NIL_IMAGES },
7592 { "BrandId" , 0, 15, NIL_IMAGES },
7593 };
7594
7595 printf(" extended brand id (0x80000001/ebx):\n");
7596 max_len = 7;
7597 print_names(value, names, LENGTH(names),
7598 /* max_len => */ max_len);
7599 }
7600
7601 // PkgType values come from these two guides (depending on family):
7602 // AMD BIOS and Kernel Developer's Guide (BKDG) for ...
7603 // Processor Programming Reference (PPR) for ...
7604 //
7605 // NOTE: AMD Family = XF + F, e.g. 0x17 (17h) = 0xf + 0x8
7606 // AMD Model = (XM << 4) + M, e.g. 0x18 (18h) = (0x1 << 4) + 0x8
7607
7608 if (__F(val_1_eax) >= _XF(1) + _F(15)) {
7609 ccstring* use_pkg_type = NIL_IMAGES;
7610
7611 if (__F(val_1_eax) == _XF(1) + _F(15)) {
7612 // Family 10h
7613 static ccstring pkg_type[1<<4] = { "Fr2/Fr5/Fr6 (0)",
7614 "AM2r2/AM3 (1)",
7615 "S1g3/S1g4 (2)",
7616 "G34 (3)",
7617 "ASB2 (4)",
7618 "C32 (5)" };
7619 use_pkg_type = pkg_type;
7620 } else if (__F(val_1_eax) == _XF(6) + _F(15)) {
7621 // Family 15h
7622 if (__M(val_1_eax) <= _XM(0) + _M(15)) {
7623 static ccstring pkg_type[1<<4] = { NULL,
7624 "AM3r2 (1)",
7625 NULL,
7626 "G34r1 (3)",
7627 NULL,
7628 "C32r1 (5)" };
7629 use_pkg_type = pkg_type;
7630 } else if (__M(val_1_eax) >= _XM(1) + _M(0)
7631 && __M(val_1_eax) <= _XM(1) + _M(15)) {
7632 static ccstring pkg_type[1<<4] = { "FP2 (BGA) (0)",
7633 "FS1r2 (uPGA) (1)",
7634 "FM2 (PGA) (2)" };
7635
7636 use_pkg_type = pkg_type;
7637 } else if (__M(val_1_eax) >= _XM(3) + _M(0)
7638 && __M(val_1_eax) <= _XM(3) + _M(15)) {
7639 static ccstring pkg_type[1<<4] = { "FP3 (BGA) (0)",
7640 "FM2r2 (uPGA) (1)" };
7641 use_pkg_type = pkg_type;
7642 } else if (__M(val_1_eax) >= _XM(6) + _M(0)
7643 && __M(val_1_eax) <= _XM(6) + _M(15)) {
7644 static ccstring pkg_type[1<<4] = { "FP4 (BGA) (0)",
7645 NULL,
7646 "AM4 (uPGA) (2)",
7647 "FM2r2 (uPGA) (3)" };
7648 use_pkg_type = pkg_type;
7649 } else if (__M(val_1_eax) >= _XM(7) + _M(0)
7650 && __M(val_1_eax) <= _XM(7) + _M(15)) {
7651 static ccstring pkg_type[1<<4] = { "FP4 (BGA) (0)",
7652 NULL,
7653 "AM4 (uPGA) (2)",
7654 NULL,
7655 "FT4 (BGA) (4)" };
7656 use_pkg_type = pkg_type;
7657 }
7658 } else if (__F(val_1_eax) == _XF(7) + _F(15)) {
7659 // Family 16h
7660 if (__M(val_1_eax) <= _XM(0) + _M(15)) {
7661 static ccstring pkg_type[1<<4] = { "FT3 (BGA) (0)",
7662 "FS1b (1)" };
7663 use_pkg_type = pkg_type;
7664 } else if (__M(val_1_eax) >= _XM(3) + _M(0)
7665 && __M(val_1_eax) <= _XM(3) + _M(15)) {
7666 static ccstring pkg_type[1<<4] = { "FT3b (BGA) (0)",
7667 NULL,
7668 NULL,
7669 "FP4 (3)" };
7670 use_pkg_type = pkg_type;
7671 }
7672 } else if (__F(val_1_eax) == _XF(8) + _F(15)) {
7673 // Family 17h
7674 if (__M(val_1_eax) == _XM(0) + _M(1)
7675 || __M(val_1_eax) == _XM(0) + _M(8)) {
7676 static ccstring pkg_type[1<<4] = { NULL,
7677 NULL,
7678 "AM4 (2)" };
7679 use_pkg_type = pkg_type;
7680 } else if (__M(val_1_eax) == _XM(1) + _M(8)
7681 || __M(val_1_eax) == _XM(2) + _M(0)) {
7682 static ccstring pkg_type[1<<4] = { "FP5 (0)",
7683 NULL,
7684 "AM4 (2)" };
7685 use_pkg_type = pkg_type;
7686 } else if (__M(val_1_eax) == _XM(7) + _M(1)) {
7687 static ccstring pkg_type[1<<4] = { NULL,
7688 NULL,
7689 "AM4 (2)" };
7690 use_pkg_type = pkg_type;
7691 }
7692 }
7693
7694 named_item names[] = { { "PkgType", 28, 31, use_pkg_type } };
7695
7696 print_names(value, names, LENGTH(names),
7697 /* max_len => */ max_len);
7698 }
7699 }
7700
7701 static void
print_80000001_ebx(unsigned int value,vendor_t vendor,unsigned int val_1_eax)7702 print_80000001_ebx(unsigned int value,
7703 vendor_t vendor,
7704 unsigned int val_1_eax)
7705 {
7706 switch (vendor) {
7707 case VENDOR_AMD:
7708 case VENDOR_HYGON:
7709 print_80000001_ebx_amd(value, val_1_eax);
7710 break;
7711 case VENDOR_INTEL:
7712 case VENDOR_CYRIX:
7713 case VENDOR_VIA:
7714 case VENDOR_TRANSMETA:
7715 case VENDOR_UMC:
7716 case VENDOR_NEXGEN:
7717 case VENDOR_RISE:
7718 case VENDOR_SIS:
7719 case VENDOR_NSC:
7720 case VENDOR_VORTEX:
7721 case VENDOR_RDC:
7722 case VENDOR_ZHAOXIN:
7723 case VENDOR_UNKNOWN:
7724 /* DO NOTHING */
7725 break;
7726 }
7727 }
7728
7729 static void
print_80000005_eax(unsigned int value)7730 print_80000005_eax(unsigned int value)
7731 {
7732 static named_item names[]
7733 = { { "instruction # entries" , 0, 7, NIL_IMAGES },
7734 { "instruction associativity" , 8, 15, NIL_IMAGES },
7735 { "data # entries" , 16, 23, NIL_IMAGES },
7736 { "data associativity" , 24, 31, NIL_IMAGES },
7737 };
7738
7739 printf(" L1 TLB/cache information: 2M/4M pages & L1 TLB"
7740 " (0x80000005/eax):\n");
7741 print_names(value, names, LENGTH(names),
7742 /* max_len => */ 0);
7743 }
7744
7745 static void
print_80000005_ebx(unsigned int value)7746 print_80000005_ebx(unsigned int value)
7747 {
7748 static named_item names[]
7749 = { { "instruction # entries" , 0, 7, NIL_IMAGES },
7750 { "instruction associativity" , 8, 15, NIL_IMAGES },
7751 { "data # entries" , 16, 23, NIL_IMAGES },
7752 { "data associativity" , 24, 31, NIL_IMAGES },
7753 };
7754
7755 printf(" L1 TLB/cache information: 4K pages & L1 TLB"
7756 " (0x80000005/ebx):\n");
7757 print_names(value, names, LENGTH(names),
7758 /* max_len => */ 0);
7759 }
7760
7761 static void
print_80000005_ecx(unsigned int value)7762 print_80000005_ecx(unsigned int value)
7763 {
7764 static named_item names[]
7765 = { { "line size (bytes)" , 0, 7, NIL_IMAGES },
7766 { "lines per tag" , 8, 15, NIL_IMAGES },
7767 { "associativity" , 16, 23, NIL_IMAGES },
7768 { "size (KB)" , 24, 31, NIL_IMAGES },
7769 };
7770
7771 printf(" L1 data cache information (0x80000005/ecx):\n");
7772 print_names(value, names, LENGTH(names),
7773 /* max_len => */ 0);
7774 }
7775
7776 static void
print_80000005_edx(unsigned int value)7777 print_80000005_edx(unsigned int value)
7778 {
7779 static named_item names[]
7780 = { { "line size (bytes)" , 0, 7, NIL_IMAGES },
7781 { "lines per tag" , 8, 15, NIL_IMAGES },
7782 { "associativity" , 16, 23, NIL_IMAGES },
7783 { "size (KB)" , 24, 31, NIL_IMAGES },
7784 };
7785
7786 printf(" L1 instruction cache information (0x80000005/edx):\n");
7787 print_names(value, names, LENGTH(names),
7788 /* max_len => */ 0);
7789 }
7790
7791 static ccstring l2_assoc[1<<4] = { "L2 off (0)",
7792 "direct mapped (1)",
7793 "2-way (2)",
7794 "3-way (3)",
7795 "4-way (4)",
7796 "6-way (5)",
7797 "8-way (6)",
7798 NULL,
7799 "16-way (8)",
7800 NULL,
7801 "32-way (10)",
7802 "48-way (11)",
7803 "64-way (12)",
7804 "96-way (13)",
7805 "128-way (14)",
7806 "full (15)" };
7807
7808 static void
print_80000006_eax(unsigned int value)7809 print_80000006_eax(unsigned int value)
7810 {
7811 static named_item names[]
7812 = { { "instruction # entries" , 0, 11, NIL_IMAGES },
7813 { "instruction associativity" , 12, 15, l2_assoc },
7814 { "data # entries" , 16, 27, NIL_IMAGES },
7815 { "data associativity" , 28, 31, l2_assoc },
7816 };
7817
7818 printf(" L2 TLB/cache information: 2M/4M pages & L2 TLB"
7819 " (0x80000006/eax):\n");
7820 print_names(value, names, LENGTH(names),
7821 /* max_len => */ 0);
7822 }
7823
7824 static void
print_80000006_ebx(unsigned int value)7825 print_80000006_ebx(unsigned int value)
7826 {
7827 static named_item names[]
7828 = { { "instruction # entries" , 0, 11, NIL_IMAGES },
7829 { "instruction associativity" , 12, 15, l2_assoc },
7830 { "data # entries" , 16, 27, NIL_IMAGES },
7831 { "data associativity" , 28, 31, l2_assoc },
7832 };
7833
7834 printf(" L2 TLB/cache information: 4K pages & L2 TLB (0x80000006/ebx):\n");
7835 print_names(value, names, LENGTH(names),
7836 /* max_len => */ 0);
7837 }
7838
7839 static void
print_80000006_ecx(unsigned int value,code_stash_t * stash)7840 print_80000006_ecx(unsigned int value,
7841 code_stash_t* stash)
7842 {
7843 static named_item names[]
7844 = { { "line size (bytes)" , 0, 7, NIL_IMAGES },
7845 { "lines per tag" , 8, 11, NIL_IMAGES },
7846 { "associativity" , 12, 15, l2_assoc },
7847 { "size (KB)" , 16, 31, NIL_IMAGES },
7848 };
7849
7850 printf(" L2 unified cache information (0x80000006/ecx):\n");
7851 print_names(value, names, LENGTH(names),
7852 /* max_len => */ 0);
7853
7854 if (((value >> 12) & 0xf) == 4 && (value >> 16) == 256) {
7855 stash->L2_4w_256K = TRUE;
7856 } else if (((value >> 12) & 0xf) == 4 && (value >> 16) == 512) {
7857 stash->L2_4w_512K = TRUE;
7858 }
7859 }
7860
7861 static void
print_80000006_edx(unsigned int value)7862 print_80000006_edx(unsigned int value)
7863 {
7864 static named_item names[]
7865 = { { "line size (bytes)" , 0, 7, NIL_IMAGES },
7866 { "lines per tag" , 8, 11, NIL_IMAGES },
7867 { "associativity" , 12, 15, l2_assoc },
7868 { "size (in 512KB units)" , 18, 31, NIL_IMAGES },
7869 };
7870
7871 printf(" L3 cache information (0x80000006/edx):\n");
7872 print_names(value, names, LENGTH(names),
7873 /* max_len => */ 0);
7874 }
7875
7876 static void
print_80000007_ebx(unsigned int value)7877 print_80000007_ebx(unsigned int value)
7878 {
7879 static named_item names[]
7880 = { { "MCA overflow recovery support" , 0, 0, bools },
7881 { "SUCCOR support" , 1, 1, bools },
7882 { "HWA: hardware assert support" , 2, 2, bools },
7883 { "scalable MCA support" , 3, 3, bools },
7884 };
7885
7886 printf(" RAS Capability (0x80000007/ebx):\n");
7887 print_names(value, names, LENGTH(names),
7888 /* max_len => */ 0);
7889 }
7890
7891 static void
print_80000007_ecx(unsigned int value)7892 print_80000007_ecx(unsigned int value)
7893 {
7894 static named_item names[]
7895 = { { "CmpUnitPwrSampleTimeRatio" , 0, 31, NIL_IMAGES },
7896 };
7897
7898 printf(" Advanced Power Management Features (0x80000007/ecx):\n");
7899 print_names(value, names, LENGTH(names),
7900 /* max_len => */ 0);
7901 }
7902
7903 static void
print_80000007_edx(unsigned int value)7904 print_80000007_edx(unsigned int value)
7905 {
7906 static named_item names[]
7907 = { { "TS: temperature sensing diode" , 0, 0, bools },
7908 { "FID: frequency ID control" , 1, 1, bools },
7909 { "VID: voltage ID control" , 2, 2, bools },
7910 { "TTP: thermal trip" , 3, 3, bools },
7911 { "TM: thermal monitor" , 4, 4, bools },
7912 { "STC: software thermal control" , 5, 5, bools },
7913 { "100 MHz multiplier control" , 6, 6, bools },
7914 { "hardware P-State control" , 7, 7, bools },
7915 { "TscInvariant" , 8, 8, bools },
7916 { "CPB: core performance boost" , 9, 9, bools },
7917 { "read-only effective frequency interface" , 10, 10, bools },
7918 { "processor feedback interface" , 11, 11, bools },
7919 { "APM power reporting" , 12, 12, bools },
7920 { "connected standby" , 13, 13, bools },
7921 { "RAPL: running average power limit" , 14, 14, bools },
7922 };
7923
7924 printf(" Advanced Power Management Features (0x80000007/edx):\n");
7925 print_names(value, names, LENGTH(names),
7926 /* max_len => */ 0);
7927 }
7928
7929 static void
print_80000008_eax(unsigned int value)7930 print_80000008_eax(unsigned int value)
7931 {
7932 static named_item names[]
7933 = { { "maximum physical address bits" , 0, 7, NIL_IMAGES },
7934 { "maximum linear (virtual) address bits" , 8, 15, NIL_IMAGES },
7935 { "maximum guest physical address bits" , 16, 23, NIL_IMAGES },
7936 };
7937
7938 printf(" Physical Address and Linear Address Size (0x80000008/eax):\n");
7939 print_names(value, names, LENGTH(names),
7940 /* max_len => */ 0);
7941 }
7942
7943 static void
print_80000008_ebx(unsigned int value)7944 print_80000008_ebx(unsigned int value)
7945 {
7946 static named_item names[]
7947 = { { "CLZERO instruction" , 0, 0, bools },
7948 { "instructions retired count support" , 1, 1, bools },
7949 { "always save/restore error pointers" , 2, 2, bools },
7950 { "INVLPGB instruction" , 3, 3, bools },
7951 { "RDPRU instruction" , 4, 4, bools },
7952 { "memory bandwidth enforcement" , 6, 6, bools }, // SKC*
7953 { "MCOMMIT instruction" , 8, 8, bools },
7954 { "WBNOINVD instruction" , 9, 9, bools },
7955 { "IBPB: indirect branch prediction barrier", 12, 12, bools },
7956 { "interruptible WBINVD, WBNOINVD" , 13, 13, bools },
7957 { "IBRS: indirect branch restr speculation" , 14, 14, bools },
7958 { "STIBP: 1 thr indirect branch predictor" , 15, 15, bools }, // Qemu*
7959 { "STIBP always on preferred mode" , 17, 17, bools }, // LX*
7960 { "IBRS preferred over software solution" , 18, 18, bools },
7961 { "IBRS provides same mode protection" , 19, 19, bools },
7962 { "EFER[LMSLE] not supported" , 20, 20, bools },
7963 { "TLB flush nested" , 21, 21, bools },
7964 { "ppin processor id number supported" , 23, 23, bools }, // Xen*
7965 { "SSBD: speculative store bypass disable" , 24, 24, bools },
7966 { "virtualized SSBD" , 25, 25, bools },
7967 { "SSBD fixed in hardware" , 26, 26, bools },
7968 { "CPPC: collaborative processor perf ctrl" , 27, 27, bools },
7969 { "PSFD: predictive store forward disable" , 28, 28, bools },
7970 { "branch sampling feature support" , 31, 31, bools },
7971 };
7972
7973 printf(" Extended Feature Extensions ID (0x80000008/ebx):\n");
7974 print_names(value, names, LENGTH(names),
7975 /* max_len => */ 0);
7976 }
7977
7978 static void
print_80000008_ecx(unsigned int value)7979 print_80000008_ecx(unsigned int value)
7980 {
7981 static ccstring tscSize[1<<2] = { "40 bits (0)",
7982 "48 bits (1)",
7983 "56 bits (2)",
7984 "64 bits (3)" };
7985
7986 static named_item names[]
7987 = { // bit field 0, 7 is reported by caller
7988 { "ApicIdCoreIdSize" , 12, 15, NIL_IMAGES },
7989 { "performance time-stamp counter size" , 16, 17, tscSize },
7990 };
7991
7992 print_names(value, names, LENGTH(names),
7993 /* max_len => */ 0);
7994 }
7995
7996 static void
print_80000008_edx(unsigned int value)7997 print_80000008_edx(unsigned int value)
7998 {
7999 static named_item names[]
8000 = { { "max page count for INVLPGB instruction" , 0, 15, NIL_IMAGES },
8001 { "RDPRU instruction max input support" , 16, 23, NIL_IMAGES },
8002 };
8003
8004 printf(" Feature Extended Size (0x80000008/edx):\n");
8005 print_names(value, names, LENGTH(names),
8006 /* max_len => */ 0);
8007 }
8008
8009 static void
print_8000000a_eax(unsigned int value)8010 print_8000000a_eax(unsigned int value)
8011 {
8012 static named_item names[]
8013 = { { "SvmRev: SVM revision" , 0, 7, NIL_IMAGES },
8014 };
8015
8016 printf(" SVM Secure Virtual Machine (0x8000000a/eax):\n");
8017 print_names(value, names, LENGTH(names),
8018 /* max_len => */ 0);
8019 }
8020
8021 static void
print_8000000a_edx(unsigned int value)8022 print_8000000a_edx(unsigned int value)
8023 {
8024 static named_item names[]
8025 = { { "nested paging" , 0, 0, bools },
8026 { "LBR virtualization" , 1, 1, bools },
8027 { "SVM lock" , 2, 2, bools },
8028 { "NRIP save" , 3, 3, bools },
8029 { "MSR based TSC rate control" , 4, 4, bools },
8030 { "VMCB clean bits support" , 5, 5, bools },
8031 { "flush by ASID" , 6, 6, bools },
8032 { "decode assists" , 7, 7, bools },
8033 { "SSSE3/SSE5 opcode set disable" , 9, 9, bools },
8034 { "pause intercept filter" , 10, 10, bools },
8035 { "pause filter threshold" , 12, 12, bools },
8036 { "AVIC: AMD virtual interrupt controller" , 13, 13, bools },
8037 { "virtualized VMLOAD/VMSAVE" , 15, 15, bools },
8038 { "virtualized global interrupt flag (GIF)" , 16, 16, bools },
8039 { "GMET: guest mode execute trap" , 17, 17, bools },
8040 { "supervisor shadow stack" , 19, 19, bools },
8041 { "guest Spec_ctl support" , 20, 20, bools },
8042 { "host MCE override" , 23, 23, bools },
8043 { "INVLPGB/TLBSYNC hyperv interc enable" , 24, 24, bools },
8044 { "guest SVME addr check" , 28, 28, bools }, // LX*, Qemu*
8045 };
8046
8047 printf(" SVM Secure Virtual Machine (0x8000000a/edx):\n");
8048 print_names(value, names, LENGTH(names),
8049 /* max_len => */ 0);
8050 }
8051
8052 static void
print_8000000a_ebx(unsigned int value)8053 print_8000000a_ebx(unsigned int value)
8054 {
8055 printf(" NASID: number of address space identifiers = 0x%x (%u):\n",
8056 value, value);
8057 }
8058
8059 static void
print_80000019_eax(unsigned int value)8060 print_80000019_eax(unsigned int value)
8061 {
8062 static named_item names[]
8063 = { { "instruction # entries" , 0, 11, NIL_IMAGES },
8064 { "instruction associativity" , 12, 15, l2_assoc },
8065 { "data # entries" , 16, 27, NIL_IMAGES },
8066 { "data associativity" , 28, 31, l2_assoc },
8067 };
8068
8069 printf(" L1 TLB information: 1G pages (0x80000019/eax):\n");
8070 print_names(value, names, LENGTH(names),
8071 /* max_len => */ 0);
8072 }
8073
8074 static void
print_80000019_ebx(unsigned int value)8075 print_80000019_ebx(unsigned int value)
8076 {
8077 static named_item names[]
8078 = { { "instruction # entries" , 0, 11, NIL_IMAGES },
8079 { "instruction associativity" , 12, 15, l2_assoc },
8080 { "data # entries" , 16, 27, NIL_IMAGES },
8081 { "data associativity" , 28, 31, l2_assoc },
8082 };
8083
8084 printf(" L2 TLB information: 1G pages (0x80000019/ebx):\n");
8085 print_names(value, names, LENGTH(names),
8086 /* max_len => */ 0);
8087 }
8088
8089 static void
print_8000001a_eax(unsigned int value)8090 print_8000001a_eax(unsigned int value)
8091 {
8092 static named_item names[]
8093 = { { "128-bit SSE executed full-width" , 0, 0, bools },
8094 { "MOVU* better than MOVL*/MOVH*" , 1, 1, bools },
8095 { "256-bit SSE executed full-width" , 2, 2, bools },
8096 };
8097
8098 printf(" SVM Secure Virtual Machine (0x8000001a/eax):\n");
8099 print_names(value, names, LENGTH(names),
8100 /* max_len => */ 0);
8101 }
8102
8103 static void
print_8000001b_eax(unsigned int value)8104 print_8000001b_eax(unsigned int value)
8105 {
8106 static named_item names[]
8107 = { { "IBS feature flags valid" , 0, 0, bools },
8108 { "IBS fetch sampling" , 1, 1, bools },
8109 { "IBS execution sampling" , 2, 2, bools },
8110 { "read write of op counter" , 3, 3, bools },
8111 { "op counting mode" , 4, 4, bools },
8112 { "branch target address reporting" , 5, 5, bools },
8113 { "IbsOpCurCnt and IbsOpMaxCnt extend 7" , 6, 6, bools },
8114 { "invalid RIP indication support" , 7, 7, bools },
8115 { "fused branch micro-op indication support", 8, 8, bools },
8116 { "IBS fetch control extended MSR support" , 9, 9, bools },
8117 { "IBS op data 4 MSR support" , 10, 10, bools },
8118 };
8119
8120 printf(" Instruction Based Sampling Identifiers (0x8000001b/eax):\n");
8121 print_names(value, names, LENGTH(names),
8122 /* max_len => */ 0);
8123 }
8124
8125 static void
print_8000001c_eax(unsigned int value)8126 print_8000001c_eax(unsigned int value)
8127 {
8128 static named_item names[]
8129 = { { "lightweight profiling" , 0, 0, bools },
8130 { "LWPVAL instruction" , 1, 1, bools },
8131 { "instruction retired event" , 2, 2, bools },
8132 { "branch retired event" , 3, 3, bools },
8133 { "DC miss event" , 4, 4, bools },
8134 { "core clocks not halted event" , 5, 5, bools },
8135 { "core reference clocks not halted event" , 6, 6, bools },
8136 { "continuous mode sampling" , 29, 29, bools },
8137 { "tsc in event record" , 30, 30, bools },
8138 { "interrupt on threshold overflow" , 31, 31, bools },
8139 };
8140
8141 printf(" Lightweight Profiling Capabilities: Availability"
8142 " (0x8000001c/eax):\n");
8143 print_names(value, names, LENGTH(names),
8144 /* max_len => */ 0);
8145 }
8146
8147 static void
print_8000001c_ebx(unsigned int value)8148 print_8000001c_ebx(unsigned int value)
8149 {
8150 static named_item names[]
8151 = { { "LWPCB byte size" , 0, 7, NIL_IMAGES },
8152 { "event record byte size" , 8, 15, NIL_IMAGES },
8153 { "maximum EventId" , 16, 23, NIL_IMAGES },
8154 { "EventInterval1 field offset" , 24, 31, NIL_IMAGES },
8155 };
8156
8157 printf(" Lightweight Profiling Capabilities (0x8000001c/ebx):\n");
8158 print_names(value, names, LENGTH(names),
8159 /* max_len => */ 0);
8160 }
8161
8162 static void
print_8000001c_ecx(unsigned int value)8163 print_8000001c_ecx(unsigned int value)
8164 {
8165 static named_item names[]
8166 = { { "latency counter bit size" , 0, 4, NIL_IMAGES },
8167 { "data cache miss address valid" , 5, 5, bools },
8168 { "amount cache latency is rounded" , 6, 8, NIL_IMAGES },
8169 { "LWP implementation version" , 9, 15, NIL_IMAGES },
8170 { "event ring buffer size in records" , 16, 23, NIL_IMAGES },
8171 { "branch prediction filtering" , 28, 28, bools },
8172 { "IP filtering" , 29, 29, bools },
8173 { "cache level filtering" , 30, 30, bools },
8174 { "cache latency filteing" , 31, 31, bools },
8175 };
8176
8177 printf(" Lightweight Profiling Capabilities (0x8000001c/ecx):\n");
8178 print_names(value, names, LENGTH(names),
8179 /* max_len => */ 0);
8180 }
8181
8182 static void
print_8000001c_edx(unsigned int value)8183 print_8000001c_edx(unsigned int value)
8184 {
8185 static named_item names[]
8186 = { { "lightweight profiling" , 0, 0, bools },
8187 { "LWPVAL instruction" , 1, 1, bools },
8188 { "instruction retired event" , 2, 2, bools },
8189 { "branch retired event" , 3, 3, bools },
8190 { "DC miss event" , 4, 4, bools },
8191 { "core clocks not halted event" , 5, 5, bools },
8192 { "core reference clocks not halted event" , 6, 6, bools },
8193 { "continuous mode sampling" , 29, 29, bools },
8194 { "tsc in event record" , 30, 30, bools },
8195 { "interrupt on threshold overflow" , 31, 31, bools },
8196 };
8197
8198 printf(" Lightweight Profiling Capabilities: Supported"
8199 " (0x8000001c/edx):\n");
8200 print_names(value, names, LENGTH(names),
8201 /* max_len => */ 0);
8202 }
8203
8204 static void
print_8000001d_eax(unsigned int value)8205 print_8000001d_eax(unsigned int value)
8206 {
8207 static ccstring cache_type[1<<5] = { "no more caches (0)",
8208 "data (1)",
8209 "instruction (2)",
8210 "unified (3)" };
8211
8212 static named_item names[]
8213 = { { "type" , 0, 4, cache_type },
8214 { "level" , 5, 7, NIL_IMAGES },
8215 { "self-initializing" , 8, 8, bools },
8216 { "fully associative" , 9, 9, bools },
8217 { "extra cores sharing this cache" , 14, 25, NIL_IMAGES },
8218 };
8219
8220 print_names(value, names, LENGTH(names),
8221 /* max_len => */ 31);
8222 }
8223
8224 static void
print_8000001d_ebx(unsigned int value)8225 print_8000001d_ebx(unsigned int value)
8226 {
8227 static named_item names[]
8228 = { { "line size in bytes" , 0, 11, MINUS1_IMAGES },
8229 { "physical line partitions" , 12, 21, MINUS1_IMAGES },
8230 { "number of ways" , 22, 31, MINUS1_IMAGES },
8231 };
8232
8233 print_names(value, names, LENGTH(names),
8234 /* max_len => */ 31);
8235 }
8236
8237 static void
print_8000001d_edx(unsigned int value)8238 print_8000001d_edx(unsigned int value)
8239 {
8240 static named_item names[]
8241 = { { "write-back invalidate" , 0, 0, bools },
8242 { "cache inclusive of lower levels" , 1, 1, bools },
8243 };
8244
8245 print_names(value, names, LENGTH(names),
8246 /* max_len => */ 31);
8247 }
8248
8249 static void
print_8000001d_synth(const unsigned int words[])8250 print_8000001d_synth(const unsigned int words[])
8251 {
8252 unsigned int ways_assoc = BIT_EXTRACT_LE(words[WORD_EBX], 22, 32) + 1;
8253 unsigned int parts = BIT_EXTRACT_LE(words[WORD_EBX], 12, 22) + 1;
8254 unsigned int line_size = BIT_EXTRACT_LE(words[WORD_EBX], 0, 12) + 1;
8255 unsigned int sets = words[WORD_ECX] + 1;
8256 unsigned int size = (ways_assoc * parts * line_size * sets);
8257
8258 printf(" (synth size) = %u", size);
8259 if (size > 1048576) {
8260 if ((size % 1048576) == 0) {
8261 printf(" (%u MB)", size / 1048576);
8262 } else {
8263 printf(" (%.1f MB)", ((float)size) / 1048576.0);
8264 }
8265 } else if (size > 1024) {
8266 if ((size % 1024) == 0) {
8267 printf(" (%u KB)", size / 1024);
8268 } else {
8269 printf(" (%.1f KB)", ((float)size) / 1024.0);
8270 }
8271 }
8272 printf("\n");
8273 }
8274
8275 static void
print_8000001e_ebx_f16(unsigned int value)8276 print_8000001e_ebx_f16(unsigned int value)
8277 {
8278 static named_item names[]
8279 = { { "compute unit ID" , 0, 7, NIL_IMAGES },
8280 { "cores per compute unit" , 8, 9, MINUS1_IMAGES },
8281 };
8282
8283 printf(" Compute Unit Identifiers (0x8000001e/ebx):\n");
8284 print_names(value, names, LENGTH(names),
8285 /* max_len => */ 0);
8286 }
8287
8288 static void
print_8000001e_ebx_gt_f16(unsigned int value)8289 print_8000001e_ebx_gt_f16(unsigned int value)
8290 {
8291 static named_item names[]
8292 = { { "core ID" , 0, 7, NIL_IMAGES },
8293 { "threads per core" , 8, 15, MINUS1_IMAGES },
8294 };
8295
8296 printf(" Core Identifiers (0x8000001e/ebx):\n");
8297 print_names(value, names, LENGTH(names),
8298 /* max_len => */ 0);
8299 }
8300
8301 static void
print_8000001e_ecx(unsigned int value)8302 print_8000001e_ecx(unsigned int value)
8303 {
8304 static named_item names[]
8305 = { { "node ID" , 0, 7, NIL_IMAGES },
8306 { "nodes per processor" , 8, 10, MINUS1_IMAGES },
8307 };
8308
8309 printf(" Node Identifiers (0x8000001e/ecx):\n");
8310 print_names(value, names, LENGTH(names),
8311 /* max_len => */ 0);
8312 }
8313
8314 static void
print_8000001f_eax(unsigned int value)8315 print_8000001f_eax(unsigned int value)
8316 {
8317 static named_item names[]
8318 = { { "SME: secure memory encryption support" , 0, 0, bools },
8319 { "SEV: secure encrypted virtualize support", 1, 1, bools },
8320 { "VM page flush MSR support" , 2, 2, bools },
8321 { "SEV-ES: SEV encrypted state support" , 3, 3, bools },
8322 { "SEV-SNP: SEV secure nested paging" , 4, 4, bools },
8323 { "VMPL: VM permission levels" , 5, 5, bools },
8324 { "hardware cache coher across enc domains" , 10, 10, bools },
8325 { "SEV guest exec only from 64-bit host" , 11, 11, bools },
8326 { "restricted injection" , 12, 12, bools },
8327 { "alternate injection" , 13, 13, bools },
8328 { "full debug state swap for SEV-ES guests" , 14, 14, bools },
8329 { "disallowing IBS use by host" , 15, 15, bools },
8330 { "VTE: SEV virtual transparent encryption" , 16, 16, bools },
8331 };
8332
8333 print_names(value, names, LENGTH(names),
8334 /* max_len => */ 40);
8335 }
8336
8337 static void
print_8000001f_ebx(unsigned int value)8338 print_8000001f_ebx(unsigned int value)
8339 {
8340 static named_item names[]
8341 = { { "encryption bit position in PTE" , 0, 5, NIL_IMAGES },
8342 { "physical address space width reduction" , 6, 11, NIL_IMAGES },
8343 { "number of VM permission levels" , 12, 15, NIL_IMAGES },
8344 };
8345 print_names(value, names, LENGTH(names),
8346 /* max_len => */ 40);
8347 }
8348
8349 static void
print_80000020_0_ebx(unsigned int value)8350 print_80000020_0_ebx(unsigned int value)
8351 {
8352 static named_item names[]
8353 = { { "memory bandwidth enforcement support" , 1, 1, bools },
8354 };
8355
8356 print_names(value, names, LENGTH(names),
8357 /* max_len => */ 36);
8358 }
8359
8360 static void
print_80000021_eax(unsigned int value)8361 print_80000021_eax(unsigned int value)
8362 {
8363 static named_item names[]
8364 = { { "no nested data-breakpoints" , 0, 0, bools },
8365 { "LFENCE always serializing" , 2, 2, bools },
8366 { "SMM paging configuration lock support" , 3, 3, bools },
8367 { "null selector clears base" , 6, 6, bools },
8368 { "prefetch control MSR support" , 13, 13, bools },
8369 };
8370
8371 printf(" Extended Feature 2 EAX (0x80000021/eax):\n");
8372 print_names(value, names, LENGTH(names),
8373 /* max_len => */ 39);
8374 }
8375
8376 static void
print_80860001_eax(unsigned int value)8377 print_80860001_eax(unsigned int value)
8378 {
8379 static named_item names[]
8380 = { { "generation" , 8, 11, NIL_IMAGES },
8381 { "model" , 4, 7, NIL_IMAGES },
8382 { "stepping" , 0, 3, NIL_IMAGES },
8383 };
8384
8385 printf(" Transmeta processor signature (0x80860001/eax):\n");
8386 print_names(value, names, LENGTH(names),
8387 /* max_len => */ 0);
8388
8389 ccstring synth = decode_synth_transmeta(value, NULL);
8390 printf(" (simple synth) = ");
8391 if (synth != NULL) {
8392 printf("%s", synth);
8393 }
8394 printf("\n");
8395 }
8396
8397 static void
print_80860001_edx(unsigned int value)8398 print_80860001_edx(unsigned int value)
8399 {
8400 static named_item names[]
8401 = { { "recovery CMS active" , 0, 0, bools },
8402 { "LongRun" , 1, 1, bools },
8403 { "LongRun Table Interface LRTI (CMS 4.2)" , 3, 3, bools },
8404 { "persistent translation technology 1.x" , 7, 7, bools },
8405 { "persistent translation technology 2.0" , 8, 8, bools },
8406 { "processor break events" , 12, 12, bools },
8407 };
8408
8409 printf(" Transmeta feature flags (0x80860001/edx):\n");
8410 print_names(value, names, LENGTH(names),
8411 /* max_len => */ 0);
8412 }
8413
8414 static void
print_transmeta_proc_rev_meaning(unsigned int proc_rev)8415 print_transmeta_proc_rev_meaning(unsigned int proc_rev)
8416 {
8417 switch (proc_rev & 0xffff0000) {
8418 case 0x01010000:
8419 printf("(TM3200)");
8420 break;
8421 case 0x01020000:
8422 printf("(TM5400)");
8423 break;
8424 case 0x01030000:
8425 if ((proc_rev & 0xffffff00) == 0x00000000) {
8426 printf("(TM5400 / TM5600)");
8427 } else {
8428 printf("(unknown)");
8429 }
8430 break;
8431 case 0x01040000:
8432 case 0x01050000:
8433 printf("(TM5500 / TM5800)");
8434 break;
8435 default:
8436 printf("(unknown)");
8437 break;
8438 }
8439 }
8440
8441 static void
print_80860001_ebx_ecx(unsigned int val_ebx,unsigned int val_ecx)8442 print_80860001_ebx_ecx(unsigned int val_ebx,
8443 unsigned int val_ecx)
8444 {
8445 printf(" Transmeta processor revision (0x80000001/edx)"
8446 " = %u.%u-%u.%u-%u ",
8447 (val_ebx >> 24) & 0xff,
8448 (val_ebx >> 16) & 0xff,
8449 (val_ebx >> 8) & 0xff,
8450 (val_ebx >> 0) & 0xff,
8451 val_ecx);
8452
8453 if (val_ebx == 0x20000000) {
8454 printf("(see 80860002/eax)");
8455 } else {
8456 print_transmeta_proc_rev_meaning(val_ebx);
8457 }
8458 printf("\n");
8459 }
8460
8461 static void
print_80860002_eax(unsigned int value,code_stash_t * stash)8462 print_80860002_eax(unsigned int value,
8463 code_stash_t* stash)
8464 {
8465 if (stash->transmeta_proc_rev == 0x02000000) {
8466 printf(" Transmeta processor revision (0x80860002/eax)"
8467 " = %u.%u-%u.%u ",
8468 (value >> 24) & 0xff,
8469 (value >> 16) & 0xff,
8470 (value >> 8) & 0xff,
8471 (value >> 0) & 0xff);
8472
8473 print_transmeta_proc_rev_meaning(value);
8474
8475 printf("\n");
8476
8477 stash->transmeta_proc_rev = value;
8478 }
8479 }
8480
8481 static void
print_c0000001_edx(unsigned int value)8482 print_c0000001_edx(unsigned int value)
8483 {
8484 static named_item names[]
8485 = { { "alternate instruction set" , 0, 0, bools }, // sandpile.org
8486 { "alternate instruction set enabled" , 1, 1, bools }, // sandpile.org
8487 { "random number generator" , 2, 2, bools },
8488 { "random number generator enabled" , 3, 3, bools },
8489 { "LongHaul MSR 0000_110Ah" , 4, 4, bools }, // sandpile.org
8490 { "FEMMS" , 5, 5, bools }, // sandpile.org
8491 { "advanced cryptography engine (ACE)" , 6, 6, bools },
8492 { "advanced cryptography engine (ACE)enabled", 7, 7, bools },
8493 { "montgomery multiplier/hash (ACE2)" , 8, 8, bools },
8494 { "montgomery multiplier/hash (ACE2) enabled", 9, 9, bools },
8495 { "padlock hash engine (PHE)" , 10, 10, bools },
8496 { "padlock hash engine (PHE) enabled" , 11, 11, bools },
8497 { "padlock montgomery mult. (PMM)" , 12, 12, bools }, // LX*
8498 { "padlock montgomery mult. (PMM) enabled" , 13, 13, bools }, // LX*
8499 };
8500
8501 printf(" extended feature flags (0xc0000001/edx):\n");
8502 print_names(value, names, LENGTH(names),
8503 /* max_len => */ 0);
8504 }
8505
8506 static void
print_c0000002_ebx(unsigned int value)8507 print_c0000002_ebx(unsigned int value)
8508 {
8509 printf(" input voltage (mV) = %d (0x%0x)\n",
8510 (BIT_EXTRACT_LE(value, 0, 8) << 4) + 700,
8511 BIT_EXTRACT_LE(value, 0, 8));
8512
8513 static named_item names[]
8514 = { { "current clock multipler" , 8, 15, NIL_IMAGES },
8515 { "clock ratio transition in progress" , 16, 16, bools },
8516 { "voltage transition in progress" , 17, 17, bools },
8517 { "thermal monitor 2 transition" , 18, 18, bools },
8518 { "thermal monitor 2 transition" , 19, 19, bools },
8519 { "performance control MSR transition" , 20, 21, NIL_IMAGES },
8520 { "lowest clock ratio" , 24, 31, NIL_IMAGES },
8521 };
8522
8523 print_names(value, names, LENGTH(names),
8524 /* max_len => */ 34);
8525 }
8526
8527 static void
print_c0000002_ecx(unsigned int value)8528 print_c0000002_ecx(unsigned int value)
8529 {
8530 printf(" highest voltage (mV) = %d (0x%0x)\n",
8531 (BIT_EXTRACT_LE(value, 0, 8) << 4) + 700,
8532 BIT_EXTRACT_LE(value, 0, 8));
8533 printf(" lowest voltage (mV) = %d (0x%0x)\n",
8534 (BIT_EXTRACT_LE(value, 16, 24) << 4) + 700,
8535 BIT_EXTRACT_LE(value, 16, 24));
8536
8537 static named_item names[]
8538 = { { "highest clock multiplier" , 8, 15, NIL_IMAGES },
8539 { "lowest clock multiplier" , 24, 31, NIL_IMAGES },
8540 };
8541
8542 print_names(value, names, LENGTH(names),
8543 /* max_len => */ 34);
8544 }
8545
8546 static void
print_c0000002_edx(unsigned int value)8547 print_c0000002_edx(unsigned int value)
8548 {
8549 static ccstring mb_reset[1<<1] = { "0xffffffff (0)",
8550 "0x000ffff0 (1)" };
8551 static ccstring bus_clock[1<<2] = { "100 MHz (0)",
8552 "133 MHz (1)",
8553 "200 MHz (2)",
8554 "166 MHz (3)" };
8555
8556 static named_item names[]
8557 = { { "MB reset vector" , 14, 14, mb_reset },
8558 { "APIC cluster ID" , 16, 17, NIL_IMAGES },
8559 { "input front side bus clock" , 16, 17, bus_clock },
8560 { "APIC agent ID" , 20, 21, NIL_IMAGES },
8561 { "current clock multiplier" , 22, 26, NIL_IMAGES },
8562 };
8563
8564 print_names(value, names, LENGTH(names),
8565 /* max_len => */ 34);
8566 }
8567
8568 static void
print_c0000004_eax(unsigned int value)8569 print_c0000004_eax(unsigned int value)
8570 {
8571 static named_item names[]
8572 = { { "thermal monitor temperature" , 0, 7, NIL_IMAGES },
8573 };
8574
8575 print_names(value, names, LENGTH(names),
8576 /* max_len => */ 0);
8577 }
8578
8579 static void
print_c0000004_ebx(unsigned int value)8580 print_c0000004_ebx(unsigned int value)
8581 {
8582 printf(" current voltage (mV) = %d (0x%0x)\n",
8583 (BIT_EXTRACT_LE(value, 0, 8) << 4) + 700,
8584 BIT_EXTRACT_LE(value, 0, 8));
8585
8586 // This is a mirror of MSR 198h [31:0]
8587 // If it had been read via rdmsr, this would be eax.
8588
8589 static named_item names[]
8590 = { { "current clock ratio" , 8, 15, X2_IMAGES },
8591 { "clock ratio transition in progress" , 16, 16, bools },
8592 { "voltage transition in progress" , 17, 17, bools },
8593 { "thermal monitor 2 transition in progress", 18, 18, NIL_IMAGES },
8594 { "thermal monitor 2 transition in progress", 19, 19, NIL_IMAGES },
8595 { "IA32_PERF_CTL transition in progress" , 20, 20, NIL_IMAGES },
8596 { "IA32_PERF_CTL transition in progress" , 21, 21, NIL_IMAGES },
8597 { "lowest clock ratio" , 24, 30, X2_IMAGES },
8598 { "XE operation (R/O)" , 31, 31, bools },
8599
8600 };
8601
8602 print_names(value, names, LENGTH(names),
8603 /* max_len => */ 40);
8604 }
8605
8606 static void
print_c0000004_ecx(unsigned int value)8607 print_c0000004_ecx(unsigned int value)
8608 {
8609 // This is a mirror of MSR 198h [63:32]
8610 // If it had been read via rdmsr, this would be edx.
8611
8612 static named_item names[]
8613 = { { "highest supported voltage" , 0, 7, NIL_IMAGES },
8614 { "highest supported clock ratio" , 8, 15, X2_IMAGES },
8615 { "lowest supported voltage" , 16, 23, NIL_IMAGES },
8616 { "lowest supported clock ratio" , 24, 31, X2_IMAGES },
8617 };
8618
8619 print_names(value, names, LENGTH(names),
8620 /* max_len => */ 40);
8621 }
8622
8623 static void
usage(void)8624 usage(void)
8625 {
8626 printf("usage: %s [options...]\n", program);
8627 printf("\n");
8628 printf("Dump detailed information about the CPU(s) gathered from the CPUID"
8629 " instruction,\n");
8630 printf("and also determine the exact model of CPU(s).\n");
8631 printf("\n");
8632 printf("options:\n");
8633 printf("\n");
8634 printf(" -1, --one-cpu display information only for the current"
8635 " CPU\n");
8636 printf(" -f FILE, --file=FILE read raw hex information (-r output) from"
8637 " FILE instead\n");
8638 printf(" of from executions of the cpuid"
8639 " instruction.\n");
8640 printf(" If FILE is '-', read from stdin.\n");
8641 printf(" -l V, --leaf=V display information for the single specified"
8642 " leaf.\n");
8643 printf(" If -s/--subleaf is not specified, 0 is"
8644 " assumed.\n");
8645 printf(" -s V, --subleaf=V display information for the single specified"
8646 " subleaf.\n");
8647 printf(" It requires -l/--leaf.\n");
8648 printf(" -h, -H, --help display this help information\n");
8649 printf(" -i, --inst use the CPUID instruction: The information"
8650 " it provides\n");
8651 printf(" is reliable. It is not necessary to"
8652 " be root.\n");
8653 printf(" (This option is the default.)\n");
8654 #ifdef USE_CPUID_MODULE
8655 printf(" -k, --kernel use the CPUID kernel module: The"
8656 " information does not\n");
8657 printf(" seem to be reliable on all combinations of"
8658 " CPU type\n");
8659 printf(" and kernel version. Typically, it is"
8660 " necessary to be\n");
8661 printf(" root.\n");
8662 #endif
8663 printf(" -r, --raw display raw hex information with no"
8664 " decoding\n");
8665 printf(" -v, --version display cpuid version\n");
8666 printf("\n");
8667 exit(1);
8668 }
8669
8670 #ifdef USE_CPUID_MODULE
8671 static void
explain_dev_cpu_errno(void)8672 explain_dev_cpu_errno(void)
8673 {
8674 if (errno == ENODEV || errno == ENXIO) {
8675 fprintf(stderr,
8676 "%s: if running a modular kernel, execute"
8677 " \"modprobe cpuid\",\n",
8678 program);
8679 fprintf(stderr,
8680 "%s: wait a few seconds, and then try again\n",
8681 program);
8682 fprintf(stderr,
8683 "%s: or consider using the -i option\n", program);
8684 } else if (errno == ENOENT) {
8685 fprintf(stderr,
8686 "%s: if running a modular kernel, execute"
8687 " \"modprobe cpuid\",\n",
8688 program);
8689 fprintf(stderr,
8690 "%s: wait a few seconds, and then try again;\n",
8691 program);
8692 fprintf(stderr,
8693 "%s: if it still fails, try executing:\n",
8694 program);
8695 fprintf(stderr,
8696 "%s: mknod /dev/cpu/0/cpuid c %u 0\n",
8697 program, CPUID_MAJOR);
8698 fprintf(stderr,
8699 "%s: mknod /dev/cpu/1/cpuid c %u 1\n",
8700 program, CPUID_MAJOR);
8701 fprintf(stderr,
8702 "%s: etc.\n",
8703 program);
8704 fprintf(stderr,
8705 "%s: and then try again\n",
8706 program);
8707 fprintf(stderr,
8708 "%s: or consider using the -i option\n", program);
8709 } else if ((errno == EPERM || errno == EACCES) && getuid() != 0) {
8710 fprintf(stderr,
8711 "%s: on most systems,"
8712 " it is necessary to execute this as root\n",
8713 program);
8714 fprintf(stderr,
8715 "%s: or consider using the -i option\n", program);
8716 }
8717 exit(1);
8718 }
8719 #endif
8720
8721 #define IS_HYPERVISOR_LEAF(reg, want) \
8722 (0x4000000 <= (reg) && (reg) < 0x40010000 && ((reg) & 0xff) == (want))
8723
8724 #define FOUR_CHARS_VALUE(s) \
8725 ((unsigned int)((s)[0] + ((s)[1] << 8) + ((s)[2] << 16) + ((s)[3] << 24)))
8726 #define IS_VENDOR_ID(words, s) \
8727 ( (words)[WORD_EBX] == FOUR_CHARS_VALUE(&(s)[0]) \
8728 && (words)[WORD_EDX] == FOUR_CHARS_VALUE(&(s)[4]) \
8729 && (words)[WORD_ECX] == FOUR_CHARS_VALUE(&(s)[8]))
8730 #define IS_HYPERVISOR_ID(words, s) \
8731 ( (words)[WORD_EBX] == FOUR_CHARS_VALUE(&(s)[0]) \
8732 && (words)[WORD_ECX] == FOUR_CHARS_VALUE(&(s)[4]) \
8733 && (words)[WORD_EDX] == FOUR_CHARS_VALUE(&(s)[8]))
8734
8735 static hypervisor_t
get_hypervisor(const unsigned int words[WORD_NUM])8736 get_hypervisor (const unsigned int words[WORD_NUM])
8737 {
8738 if (IS_HYPERVISOR_ID(words, "VMwareVMware")) {
8739 return HYPERVISOR_VMWARE;
8740 } else if (IS_HYPERVISOR_ID(words, "XenVMMXenVMM")) {
8741 return HYPERVISOR_XEN;
8742 } else if (IS_HYPERVISOR_ID(words, "KVMKVMKVM\0\0\0")) {
8743 return HYPERVISOR_KVM;
8744 } else if (IS_HYPERVISOR_ID(words, "Microsoft Hv")) {
8745 return HYPERVISOR_MICROSOFT;
8746 } else if (IS_HYPERVISOR_ID(words, "ACRNACRNACRN")) {
8747 return HYPERVISOR_ACRN;
8748 } else {
8749 return HYPERVISOR_UNKNOWN;
8750 }
8751 }
8752
8753 static void
print_esc_substring(const char * str,unsigned int len)8754 print_esc_substring (const char* str,
8755 unsigned int len)
8756 {
8757 unsigned int i = 0;
8758 for (; i < len; i++) {
8759 unsigned char c = ((const unsigned char*)str)[i];
8760 if (isgraph(c) || (c) == ' ') {
8761 putchar(c);
8762 } else {
8763 printf("\\%o", c);
8764 }
8765 }
8766 }
8767
8768 static void
print_reg_raw(unsigned int reg,unsigned int try,const unsigned int words[WORD_NUM])8769 print_reg_raw (unsigned int reg,
8770 unsigned int try,
8771 const unsigned int words[WORD_NUM])
8772 {
8773 printf(" 0x%08x 0x%02x: eax=0x%08x ebx=0x%08x ecx=0x%08x edx=0x%08x\n",
8774 reg, try,
8775 words[WORD_EAX], words[WORD_EBX],
8776 words[WORD_ECX], words[WORD_EDX]);
8777 }
8778
8779 static void
print_reg(unsigned int reg,const unsigned int words[WORD_NUM],boolean raw,unsigned int try,code_stash_t * stash)8780 print_reg (unsigned int reg,
8781 const unsigned int words[WORD_NUM],
8782 boolean raw,
8783 unsigned int try,
8784 code_stash_t* stash)
8785 {
8786 if (reg == 0) {
8787 if (IS_VENDOR_ID(words, "GenuineIntel")) {
8788 stash->vendor = VENDOR_INTEL;
8789 } else if (IS_VENDOR_ID(words, "AuthenticAMD")) {
8790 stash->vendor = VENDOR_AMD;
8791 } else if (IS_VENDOR_ID(words, "CyrixInstead")) {
8792 stash->vendor = VENDOR_CYRIX;
8793 } else if (IS_VENDOR_ID(words, "CentaurHauls")) {
8794 stash->vendor = VENDOR_VIA;
8795 } else if (IS_VENDOR_ID(words, "UMC UMC UMC ")) {
8796 stash->vendor = VENDOR_UMC;
8797 } else if (IS_VENDOR_ID(words, "NexGenDriven")) {
8798 stash->vendor = VENDOR_NEXGEN;
8799 } else if (IS_VENDOR_ID(words, "RiseRiseRise")) {
8800 stash->vendor = VENDOR_RISE;
8801 } else if (IS_VENDOR_ID(words, "GenuineTMx86")) {
8802 stash->vendor = VENDOR_TRANSMETA;
8803 } else if (IS_VENDOR_ID(words, "SiS SiS SiS ")) {
8804 stash->vendor = VENDOR_SIS;
8805 } else if (IS_VENDOR_ID(words, "Geode by NSC")) {
8806 stash->vendor = VENDOR_NSC;
8807 } else if (IS_VENDOR_ID(words, "Vortex86 SoC")) {
8808 stash->vendor = VENDOR_VORTEX;
8809 } else if (IS_VENDOR_ID(words, "Genuine RDC")) {
8810 stash->vendor = VENDOR_RDC;
8811 } else if (IS_VENDOR_ID(words, "HygonGenuine")) {
8812 stash->vendor = VENDOR_HYGON;
8813 } else if (IS_VENDOR_ID(words, " Shanghai ")) {
8814 stash->vendor = VENDOR_ZHAOXIN;
8815 }
8816 } else if (reg == 1) {
8817 stash->val_1_eax = words[WORD_EAX];
8818 stash->val_1_ebx = words[WORD_EBX];
8819 stash->val_1_ecx = words[WORD_ECX];
8820 stash->val_1_edx = words[WORD_EDX];
8821 } else if (reg == 4) {
8822 stash->saw_4 = TRUE;
8823 if (try == 0) {
8824 stash->val_4_eax = words[WORD_EAX];
8825 }
8826 } else if (reg == 0xb) {
8827 stash->saw_b = TRUE;
8828 if (try < LENGTH(stash->val_b_eax)) {
8829 stash->val_b_eax[try] = words[WORD_EAX];
8830 }
8831 if (try < LENGTH(stash->val_b_ebx)) {
8832 stash->val_b_ebx[try] = words[WORD_EBX];
8833 }
8834 } else if (reg == 0x1f) {
8835 stash->saw_1f = TRUE;
8836 if (try < LENGTH(stash->val_1f_eax)) {
8837 stash->val_1f_eax[try] = words[WORD_EAX];
8838 }
8839 if (try < LENGTH(stash->val_1f_ebx)) {
8840 stash->val_1f_ebx[try] = words[WORD_EBX];
8841 }
8842 if (try < LENGTH(stash->val_1f_ecx)) {
8843 stash->val_1f_ecx[try] = words[WORD_ECX];
8844 }
8845 } else if (IS_HYPERVISOR_LEAF(reg, 0)) {
8846 stash->hypervisor = get_hypervisor(words);
8847 } else if (reg == 0x80000008) {
8848 stash->val_80000008_ecx = words[WORD_ECX];
8849 } else if (reg == 0x8000001e) {
8850 stash->val_8000001e_ebx = words[WORD_EBX];
8851 } else if (reg == 0x80860003) {
8852 memcpy(&stash->transmeta_info[0], words, sizeof(unsigned int)*WORD_NUM);
8853 } else if (reg == 0x80860004) {
8854 memcpy(&stash->transmeta_info[16], words, sizeof(unsigned int)*WORD_NUM);
8855 } else if (reg == 0x80860005) {
8856 memcpy(&stash->transmeta_info[32], words, sizeof(unsigned int)*WORD_NUM);
8857 } else if (reg == 0x80860006) {
8858 memcpy(&stash->transmeta_info[48], words, sizeof(unsigned int)*WORD_NUM);
8859 }
8860
8861 if (raw) {
8862 print_reg_raw(reg, try, words);
8863 } else if (reg == 0) {
8864 // max already set to words[WORD_EAX]
8865 stash->val_0_eax = words[WORD_EAX];
8866 printf(" vendor_id = \"%-4.4s%-4.4s%-4.4s\"\n",
8867 (const char*)&words[WORD_EBX],
8868 (const char*)&words[WORD_EDX],
8869 (const char*)&words[WORD_ECX]);
8870 } else if (reg == 1) {
8871 print_1_eax(words[WORD_EAX], stash->vendor);
8872 print_1_ebx(words[WORD_EBX]);
8873 print_brand(words[WORD_EAX], words[WORD_EBX]);
8874 print_1_edx(words[WORD_EDX]);
8875 print_1_ecx(words[WORD_ECX]);
8876 } else if (reg == 2) {
8877 unsigned int word = 0;
8878 for (; word < 4; word++) {
8879 if ((words[word] & 0x80000000) == 0) {
8880 const unsigned char* bytes = (const unsigned char*)&words[word];
8881 unsigned int byte = (try == 0 && word == WORD_EAX ? 1
8882 : 0);
8883 for (; byte < 4; byte++) {
8884 print_2_byte(bytes[byte], stash->vendor, stash->val_1_eax);
8885 stash_intel_cache(stash, bytes[byte]);
8886 }
8887 }
8888 }
8889 } else if (reg == 3) {
8890 printf(" processor serial number ="
8891 " %04X-%04X-%04X-%04X-%04X-%04X\n",
8892 stash->val_1_eax >> 16, stash->val_1_eax & 0xffff,
8893 words[WORD_EDX] >> 16, words[WORD_EDX] & 0xffff,
8894 words[WORD_ECX] >> 16, words[WORD_ECX] & 0xffff);
8895 } else if (reg == 4) {
8896 printf(" --- cache %d ---\n", try);
8897 print_4_eax(words[WORD_EAX]);
8898 print_4_ebx(words[WORD_EBX]);
8899 print_4_ecx(words[WORD_ECX]);
8900 print_4_edx(words[WORD_EDX]);
8901 printf(" number of sets (s) = %llu\n",
8902 (unsigned long long)words[WORD_ECX] + 1ULL);
8903 print_4_synth(words);
8904 } else if (reg == 5) {
8905 printf(" MONITOR/MWAIT (5):\n");
8906 print_5_eax(words[WORD_EAX]);
8907 print_5_ebx(words[WORD_EBX]);
8908 print_5_ecx(words[WORD_ECX]);
8909 print_5_edx(words[WORD_EDX]);
8910 } else if (reg == 6) {
8911 printf(" Thermal and Power Management Features (6):\n");
8912 print_6_eax(words[WORD_EAX]);
8913 print_6_ebx(words[WORD_EBX]);
8914 print_6_ecx(words[WORD_ECX]);
8915 print_6_edx(words[WORD_EDX]);
8916 } else if (reg == 7) {
8917 if (try == 0) {
8918 print_7_0_ebx(words[WORD_EBX]);
8919 print_7_0_ecx(words[WORD_ECX]);
8920 print_7_0_edx(words[WORD_EDX]);
8921 } else if (try == 1) {
8922 print_7_1_eax(words[WORD_EAX]);
8923 } else {
8924 /* Reserved: DO NOTHING */
8925 }
8926 } else if (reg == 8) {
8927 /* Reserved: DO NOTHING */
8928 } else if (reg == 9) {
8929 printf(" Direct Cache Access Parameters (9):\n");
8930 printf(" PLATFORM_DCA_CAP MSR bits = %u\n", words[WORD_EAX]);
8931 } else if (reg == 0xa) {
8932 printf(" Architecture Performance Monitoring Features (0xa):\n");
8933 print_a_eax(words[WORD_EAX]);
8934 print_a_ebx(words[WORD_EBX], words[WORD_EAX]);
8935 print_a_ecx(words[WORD_ECX]);
8936 print_a_edx(words[WORD_EDX]);
8937 } else if (reg == 0xb) {
8938 if (try == 0) {
8939 // This is invariant across subleaves, so print it only once
8940 printf(" extended APIC ID = %u\n",
8941 words[WORD_EDX]);
8942 }
8943 printf(" --- level %d ---\n", try);
8944 print_b_1f_ecx(words[WORD_ECX]);
8945 print_b_1f_eax(words[WORD_EAX]);
8946 print_b_1f_ebx(words[WORD_EBX]);
8947 } else if (reg == 0xc) {
8948 /* Reserved: DO NOTHING */
8949 } else if (reg == 0xd) {
8950 if (try == 0) {
8951 printf(" XSAVE features (0xd/0):\n");
8952 printf(" XCR0 valid bit field mask = 0x%08x%08x\n",
8953 words[WORD_EDX], words[WORD_EAX]);
8954 print_d_0_eax(words[WORD_EAX]);
8955 print_d_0_edx(words[WORD_EDX]);
8956 // No bits current are defined in d_0_edx
8957 printf(" bytes required by fields in XCR0 = 0x%08x (%u)\n",
8958 words[WORD_EBX], words[WORD_EBX]);
8959 printf(" bytes required by XSAVE/XRSTOR area = 0x%08x (%u)\n",
8960 words[WORD_ECX], words[WORD_ECX]);
8961 } else if (try == 1) {
8962 printf(" XSAVE features (0xd/1):\n");
8963 print_d_1_eax(words[WORD_EAX]);
8964 printf(" SAVE area size in bytes "
8965 " = 0x%08x (%u)\n",
8966 words[WORD_EBX], words[WORD_EBX]);
8967 printf(" IA32_XSS lower 32 bits valid bit field mask"
8968 " = 0x%08x\n",
8969 words[WORD_ECX]);
8970 printf(" IA32_XSS upper 32 bits valid bit field mask"
8971 " = 0x%08x\n",
8972 words[WORD_EDX]);
8973 } else if (try >= 2 && try < 63) {
8974 print_d_n(words, try);
8975 } else {
8976 print_reg_raw(reg, try, words);
8977 }
8978 } else if (reg == 0xe) {
8979 /* Reserved: DO NOTHING */
8980 } else if (reg == 0xf) {
8981 if (try == 0) {
8982 printf(" Quality of Service Monitoring Resource Type (0xf/0):\n");
8983 printf(" Maximum range of RMID = %u\n", words[WORD_EBX]);
8984 print_f_0_edx(words[WORD_EDX]);
8985 } else if (try == 1) {
8986 printf(" L3 Cache Quality of Service Monitoring (0xf/1):\n");
8987 printf(" Conversion factor from IA32_QM_CTR to bytes = %u\n",
8988 words[WORD_EBX]);
8989 printf(" Maximum range of RMID = %u\n",
8990 words[WORD_ECX]);
8991 printf(" Counter width = %u\n",
8992 24 + BIT_EXTRACT_LE(words[WORD_EAX], 0, 8));
8993 print_f_1_eax(words[WORD_EAX]);
8994 print_f_1_edx(words[WORD_EDX]);
8995 } else {
8996 print_reg_raw(reg, try, words);
8997 }
8998 } else if (reg == 0x10) {
8999 if (try == 0) {
9000 printf(" Resource Director Technology Allocation (0x10/0):\n");
9001 print_10_0_ebx(words[WORD_EBX]);
9002 } else if (try == 1 || try == 2) {
9003 if (try == 1) {
9004 printf(" L3 Cache Allocation Technology (0x10/1):\n");
9005 } else if (try == 2) {
9006 printf(" L2 Cache Allocation Technology (0x10/2):\n");
9007 }
9008 print_10_n_eax(words[WORD_EAX]);
9009 printf(" Bit-granular map of isolation/contention = 0x%08x\n",
9010 words[WORD_EBX]);
9011 print_10_n_ecx(words[WORD_ECX]);
9012 print_10_n_edx(words[WORD_EDX]);
9013 } else if (try == 3) {
9014 printf(" Memory Bandwidth Allocation (0x10/3):\n");
9015 print_10_3_eax(words[WORD_EAX]);
9016 print_10_3_ecx(words[WORD_ECX]);
9017 print_10_n_edx(words[WORD_EDX]);
9018 } else {
9019 print_reg_raw(reg, try, words);
9020 }
9021 } else if (reg == 0x12) {
9022 if (try == 0) {
9023 printf(" Software Guard Extensions (SGX) capability (0x12/0):\n");
9024 print_12_0_eax(words[WORD_EAX]);
9025 print_12_0_ebx(words[WORD_EBX]);
9026 print_12_0_edx(words[WORD_EDX]);
9027 } else if (try == 1) {
9028 printf(" SGX attributes: ECREATE SECS.ATTRIBUTES (0x12/1):\n");
9029 printf(" valid bit mask = 0x%08x%08x%08x%08x\n",
9030 words[WORD_EDX],
9031 words[WORD_ECX],
9032 words[WORD_EBX],
9033 words[WORD_EAX]);
9034 print_12_1_eax(words[WORD_EAX]);
9035 print_12_1_ebx(words[WORD_EBX]);
9036 printf(" XFRM: XSAVE feature request mask = 0x%08x%08x\n",
9037 words[WORD_EDX],
9038 words[WORD_ECX]);
9039 print_12_1_ecx(words[WORD_ECX]);
9040 print_12_1_edx(words[WORD_EDX]);
9041 } else {
9042 if ((words[WORD_EAX] & 0xf) == 1) {
9043 printf(" SGX EPC enumeration (0x12/n):\n");
9044 printf(" section physical address = 0x%08x%08x\n",
9045 words[WORD_EBX] & 0xfffff, words[WORD_EAX] & 0xfffff000);
9046 printf(" section size = 0x%08x%08x\n",
9047 words[WORD_EDX] & 0xfffff, words[WORD_ECX] & 0xfffff000);
9048 print_12_n_ecx(words[WORD_ECX]);
9049 } else {
9050 print_reg_raw(reg, try, words);
9051 }
9052 }
9053 } else if (reg == 0x14) {
9054 if (try == 0) {
9055 printf(" Intel Processor Trace (0x14):\n");
9056 print_14_0_ebx(words[WORD_EBX]);
9057 print_14_0_ecx(words[WORD_ECX]);
9058 } else if (try == 1) {
9059 print_14_1_eax(words[WORD_EAX]);
9060 print_14_1_ebx(words[WORD_EBX]);
9061 } else {
9062 print_reg_raw(reg, try, words);
9063 }
9064 } else if (reg == 0x15) {
9065 printf(" Time Stamp Counter/Core Crystal Clock Information (0x15):\n");
9066 printf(" TSC/clock ratio = %u/%u\n",
9067 words[WORD_EBX], words[WORD_EAX]);
9068 printf(" nominal core crystal clock = %u Hz\n", words[WORD_ECX]);
9069 } else if (reg == 0x16) {
9070 printf(" Processor Frequency Information (0x16):\n");
9071 print_16_eax(words[WORD_EAX]);
9072 print_16_ebx(words[WORD_EBX]);
9073 print_16_ecx(words[WORD_ECX]);
9074 } else if (reg == 0x17) {
9075 if (try == 0) {
9076 printf(" System-On-Chip Vendor Attribute (0x17/0):\n");
9077 print_17_0_ebx(words[WORD_EBX]);
9078 printf(" project id = 0x%08x (%u)\n",
9079 words[WORD_ECX], words[WORD_ECX]);
9080 printf(" stepping id = 0x%08x (%u)\n",
9081 words[WORD_EDX], words[WORD_EDX]);
9082 } else if (try == 1) {
9083 memcpy(&stash->soc_brand[0], words, sizeof(unsigned int)*WORD_NUM);
9084 } else if (try == 2) {
9085 memcpy(&stash->soc_brand[16], words, sizeof(unsigned int)*WORD_NUM);
9086 } else if (try == 3) {
9087 memcpy(&stash->soc_brand[32], words, sizeof(unsigned int)*WORD_NUM);
9088 printf(" SoC brand = \"%s\"\n", stash->soc_brand);
9089 } else {
9090 print_reg_raw(reg, try, words);
9091 }
9092 } else if (reg == 0x18) {
9093 printf(" Deterministic Address Translation Parameters (0x18/%d):\n",
9094 try);
9095 print_18_n_ebx(words[WORD_EBX]);
9096 printf(" number of sets = 0x%08x (%u)\n",
9097 words[WORD_ECX], words[WORD_ECX]);
9098 print_18_n_edx(words[WORD_EDX]);
9099 } else if (reg == 0x19) {
9100 printf(" Key Locker information (0x19):\n");
9101 print_19_eax(words[WORD_EAX]);
9102 print_19_ebx(words[WORD_EBX]);
9103 print_19_ecx(words[WORD_ECX]);
9104 } else if (reg == 0x1a) {
9105 printf(" Hybrid Information (0x1a/0):\n");
9106 print_1a_0_eax(words[WORD_EAX]);
9107 } else if (reg == 0x1b) {
9108 printf(" PCONFIG information (0x1b/n):\n");
9109 print_1b_n_eax(words[WORD_EAX]);
9110 printf(" identifier of target %d = 0x%08x (%u)\n",
9111 3 * try + 1, words[WORD_EBX], words[WORD_EBX]);
9112 printf(" identifier of target %d = 0x%08x (%u)\n",
9113 3 * try + 2, words[WORD_ECX], words[WORD_ECX]);
9114 printf(" identifier of target %d = 0x%08x (%u)\n",
9115 3 * try + 3, words[WORD_EDX], words[WORD_EDX]);
9116 } else if (reg == 0x1c) {
9117 printf(" Architectural LBR Capabilities (0x1c/0):\n");
9118 print_1c_eax(words[WORD_EAX]);
9119 print_1c_ebx(words[WORD_EBX]);
9120 print_1c_ecx(words[WORD_ECX]);
9121 } else if (reg == 0x1d) {
9122 if (try == 0) {
9123 printf(" max_palette = %u\n", words[WORD_EAX]);
9124 } else {
9125 printf(" --- palette %d ---\n", try);
9126 print_1d_n_eax(words[WORD_EAX]);
9127 print_1d_n_ebx(words[WORD_EBX]);
9128 print_1d_n_ecx(words[WORD_ECX]);
9129 }
9130 } else if (reg == 0x1e) {
9131 printf(" TMUL Information (0x1e/0):\n");
9132 print_1e_ebx(words[WORD_EBX]);
9133 } else if (reg == 0x1f) {
9134 if (try == 0) {
9135 // This is invariant across subleaves, so print it only once
9136 printf(" x2APIC ID of logical processor = 0x%x (%u)\n",
9137 words[WORD_EDX], words[WORD_EDX]);
9138 }
9139 printf(" --- level %d ---\n", try);
9140 print_b_1f_ecx(words[WORD_ECX]);
9141 print_b_1f_eax(words[WORD_EAX]);
9142 print_b_1f_ebx(words[WORD_EBX]);
9143 } else if (reg == 0x20) {
9144 if (try == 0) {
9145 print_20_ebx(words[WORD_EBX]);
9146 } else {
9147 print_reg_raw(reg, try, words);
9148 }
9149 } else if (reg == 0x20000000) {
9150 // max already set to words[WORD_EAX]
9151 } else if (reg == 0x20000001) {
9152 print_20000001_edx(words[WORD_EDX]);
9153 } else if (IS_HYPERVISOR_LEAF(reg, 0)) {
9154 printf(" hypervisor_id (0x%08x) = \"", reg);
9155 print_esc_substring((const char*)&words[WORD_EBX], sizeof(words[0]));
9156 print_esc_substring((const char*)&words[WORD_ECX], sizeof(words[0]));
9157 print_esc_substring((const char*)&words[WORD_EDX], sizeof(words[0]));
9158 printf("\"\n");
9159 } else if (IS_HYPERVISOR_LEAF(reg, 1)
9160 && stash->hypervisor == HYPERVISOR_XEN) {
9161 printf(" hypervisor version (0x%08x/eax):\n", reg);
9162 printf(" version = %d.%d\n",
9163 BIT_EXTRACT_LE(words[WORD_EAX], 16, 32),
9164 BIT_EXTRACT_LE(words[WORD_EAX], 0, 16));
9165 } else if (IS_HYPERVISOR_LEAF(reg, 1)
9166 && stash->hypervisor == HYPERVISOR_KVM) {
9167 print_hypervisor_1_eax_kvm(reg, words[WORD_EAX]);
9168 print_hypervisor_1_edx_kvm(reg, words[WORD_EDX]);
9169 } else if (IS_HYPERVISOR_LEAF(reg, 1)
9170 && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9171 printf(" hypervisor interface identification (0x%08x/eax):\n", reg);
9172 printf(" version = \"%-4.4s\"\n",
9173 (const char*)&words[WORD_EAX]);
9174 } else if (IS_HYPERVISOR_LEAF(reg, 1)
9175 && stash->hypervisor == HYPERVISOR_ACRN) {
9176 print_hypervisor_1_eax_acrn(reg, words[WORD_EAX]);
9177 } else if (IS_HYPERVISOR_LEAF(reg, 2)
9178 && stash->hypervisor == HYPERVISOR_XEN) {
9179 printf(" hypervisor features (0x%08x):\n", reg);
9180 printf(" number of hypercall-transfer pages = 0x%0x (%u)\n",
9181 words[WORD_EAX], words[WORD_EAX]);
9182 printf(" MSR base address = 0x%0x\n",
9183 words[WORD_EBX]);
9184 print_hypervisor_2_ecx_xen(words[WORD_ECX]);
9185 } else if (IS_HYPERVISOR_LEAF(reg, 2)
9186 && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9187 printf(" hypervisor system identity (0x%08x):\n", reg);
9188 printf(" build = %d\n", words[WORD_EAX]);
9189 printf(" version = %d.%d\n",
9190 BIT_EXTRACT_LE(words[WORD_EBX], 16, 32),
9191 BIT_EXTRACT_LE(words[WORD_EBX], 0, 16));
9192 printf(" service pack = %d\n", words[WORD_ECX]);
9193 printf(" service branch = %d\n",
9194 BIT_EXTRACT_LE(words[WORD_EDX], 24, 32));
9195 printf(" service number = %d\n",
9196 BIT_EXTRACT_LE(words[WORD_EDX], 0, 24));
9197 } else if (IS_HYPERVISOR_LEAF(reg, 3) && stash->hypervisor == HYPERVISOR_XEN
9198 && try == 0) {
9199 print_hypervisor_3_eax_xen(words[WORD_EAX]);
9200 printf(" tsc mode = 0x%0x (%u)\n",
9201 words[WORD_EBX], words[WORD_EBX]);
9202 printf(" tsc frequency (kHz) = %u\n",
9203 words[WORD_ECX]);
9204 printf(" incarnation = 0x%0x (%u)\n",
9205 words[WORD_EDX], words[WORD_EDX]);
9206 } else if (IS_HYPERVISOR_LEAF(reg, 3) && stash->hypervisor == HYPERVISOR_XEN
9207 && try == 1) {
9208 unsigned long long vtsc_offset
9209 = ((unsigned long long)words[WORD_EAX]
9210 + ((unsigned long long)words[WORD_EBX] << 32));
9211 printf(" vtsc offset = 0x%0llx (%llu)\n", vtsc_offset, vtsc_offset);
9212 printf(" vtsc mul_frac = 0x%0x (%u)\n",
9213 words[WORD_ECX], words[WORD_ECX]);
9214 printf(" vtsc shift = 0x%0x (%u)\n",
9215 words[WORD_EDX], words[WORD_EDX]);
9216 } else if (IS_HYPERVISOR_LEAF(reg, 3) && stash->hypervisor == HYPERVISOR_XEN
9217 && try == 2) {
9218 printf(" cpu frequency (kHZ) = %u\n", words[WORD_EAX]);
9219 } else if (IS_HYPERVISOR_LEAF(reg, 3) && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9220 print_hypervisor_3_eax_microsoft(reg, words[WORD_EAX]);
9221 print_hypervisor_3_ebx_microsoft(reg, words[WORD_EBX]);
9222 print_hypervisor_3_ecx_microsoft(reg, words[WORD_ECX]);
9223 print_hypervisor_3_edx_microsoft(reg, words[WORD_EDX]);
9224 } else if (IS_HYPERVISOR_LEAF(reg, 4) && stash->hypervisor == HYPERVISOR_XEN) {
9225 print_hypervisor_4_eax_xen(reg, words[WORD_EAX]);
9226 printf(" vcpu id = 0x%x (%u)\n",
9227 words[WORD_EBX], words[WORD_EBX]);
9228 printf(" domain id = 0x%x (%u)\n",
9229 words[WORD_ECX], words[WORD_ECX]);
9230 } else if (IS_HYPERVISOR_LEAF(reg, 4) && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9231 print_hypervisor_4_eax_microsoft(reg, words[WORD_EAX]);
9232 printf(" maximum number of spinlock retry attempts = 0x%0x (%u)\n",
9233 words[WORD_EBX], words[WORD_EBX]);
9234 } else if (IS_HYPERVISOR_LEAF(reg, 5) && stash->hypervisor == HYPERVISOR_XEN
9235 && try == 0) {
9236 print_hypervisor_5_0_ebx_xen(reg, words[WORD_EBX]);
9237 } else if (IS_HYPERVISOR_LEAF(reg, 5) && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9238 printf(" hypervisor implementation limits (0x%08x):\n", reg);
9239 printf(" maximum number of virtual processors "
9240 " = 0x%0x (%u)\n",
9241 words[WORD_EAX], words[WORD_EAX]);
9242 printf(" maximum number of logical processors "
9243 " = 0x%0x (%u)\n",
9244 words[WORD_EBX], words[WORD_EBX]);
9245 printf(" maximum number of physical interrupt vectors for remapping"
9246 " = 0x%0x (%u)\n",
9247 words[WORD_ECX], words[WORD_ECX]);
9248 } else if (IS_HYPERVISOR_LEAF(reg, 6)
9249 && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9250 print_hypervisor_6_eax_microsoft(reg, words[WORD_EAX]);
9251 } else if (IS_HYPERVISOR_LEAF(reg, 7)
9252 && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9253 printf(" hypervisor root partition enlightenments (0x%08x):\n", reg);
9254 print_hypervisor_7_eax_microsoft(words[WORD_EAX]);
9255 print_hypervisor_7_ebx_microsoft(words[WORD_EBX]);
9256 } else if (IS_HYPERVISOR_LEAF(reg, 8)
9257 && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9258 printf(" hypervisor shared virtual memory (0x%08x):\n", reg);
9259 print_hypervisor_8_eax_microsoft(words[WORD_EAX]);
9260 } else if (IS_HYPERVISOR_LEAF(reg, 9)
9261 && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9262 printf(" hypervisor nested hypervisor features (0x%08x):\n", reg);
9263 print_hypervisor_9_eax_microsoft(words[WORD_EAX]);
9264 print_hypervisor_9_edx_microsoft(words[WORD_EDX]);
9265 } else if (IS_HYPERVISOR_LEAF(reg, 0xa)
9266 && stash->hypervisor == HYPERVISOR_MICROSOFT) {
9267 printf(" hypervisor nested virtualization features (0x%08x):\n", reg);
9268 print_hypervisor_a_eax_microsoft(words[WORD_EAX]);
9269 } else if (IS_HYPERVISOR_LEAF(reg, 0x10)) {
9270 printf(" hypervisor generic timing information (0x%08x):\n", reg);
9271 printf(" TSC frequency (Hz) = %d\n", words[WORD_EAX]);
9272 printf(" bus frequency (Hz) = %d\n", words[WORD_EBX]);
9273 } else if (reg == 0x80000000) {
9274 // max already set to words[WORD_EAX]
9275 } else if (reg == 0x80000001) {
9276 print_80000001_eax(words[WORD_EAX], stash->vendor);
9277 print_80000001_edx(words[WORD_EDX], stash->vendor);
9278 print_80000001_ebx(words[WORD_EBX], stash->vendor, stash->val_1_eax);
9279 print_80000001_ecx(words[WORD_ECX], stash->vendor);
9280 stash->val_80000001_eax = words[WORD_EAX];
9281 stash->val_80000001_ebx = words[WORD_EBX];
9282 stash->val_80000001_ecx = words[WORD_ECX];
9283 stash->val_80000001_edx = words[WORD_EDX];
9284 } else if (reg == 0x80000002) {
9285 memcpy(&stash->brand[0], words, sizeof(unsigned int)*WORD_NUM);
9286 } else if (reg == 0x80000003) {
9287 memcpy(&stash->brand[16], words, sizeof(unsigned int)*WORD_NUM);
9288 } else if (reg == 0x80000004) {
9289 memcpy(&stash->brand[32], words, sizeof(unsigned int)*WORD_NUM);
9290 printf(" brand = \"%s\"\n", stash->brand);
9291 } else if (reg == 0x80000005) {
9292 print_80000005_eax(words[WORD_EAX]);
9293 print_80000005_ebx(words[WORD_EBX]);
9294 print_80000005_ecx(words[WORD_ECX]);
9295 print_80000005_edx(words[WORD_EDX]);
9296 } else if (reg == 0x80000006) {
9297 print_80000006_eax(words[WORD_EAX]);
9298 print_80000006_ebx(words[WORD_EBX]);
9299 print_80000006_ecx(words[WORD_ECX], stash);
9300 print_80000006_edx(words[WORD_EDX]);
9301 } else if (reg == 0x80000007) {
9302 print_80000007_ebx(words[WORD_EBX]);
9303 print_80000007_ecx(words[WORD_ECX]);
9304 print_80000007_edx(words[WORD_EDX]);
9305 } else if (reg == 0x80000008) {
9306 print_80000008_eax(words[WORD_EAX]);
9307 print_80000008_ebx(words[WORD_EBX]);
9308 printf(" Size Identifiers (0x80000008/ecx):\n");
9309 unsigned int num_thrs = BIT_EXTRACT_LE(stash->val_80000008_ecx, 0, 8);
9310 if (Synth_Family(stash->val_80000001_eax) > 0x16) {
9311 printf(" number of threads = 0x%llx (%llu)\n",
9312 (unsigned long long)num_thrs + 1ULL,
9313 (unsigned long long)num_thrs + 1ULL);
9314 } else {
9315 printf(" number of CPU cores = 0x%llx (%llu)\n",
9316 (unsigned long long)num_thrs + 1ULL,
9317 (unsigned long long)num_thrs + 1ULL);
9318 }
9319 print_80000008_ecx(words[WORD_ECX]);
9320 print_80000008_edx(words[WORD_EDX]);
9321 } else if (reg == 0x80000009) {
9322 /* reserved for Intel feature flag expansion */
9323 } else if (reg == 0x8000000a) {
9324 print_8000000a_eax(words[WORD_EAX]);
9325 print_8000000a_edx(words[WORD_EDX]);
9326 print_8000000a_ebx(words[WORD_EBX]);
9327 } else if (0x8000000b <= reg && reg <= 0x80000018) {
9328 /* reserved for vendors to be determined feature flag expansion */
9329 } else if (reg == 0x80000019) {
9330 print_80000019_eax(words[WORD_EAX]);
9331 print_80000019_ebx(words[WORD_EBX]);
9332 } else if (reg == 0x8000001a) {
9333 print_8000001a_eax(words[WORD_EAX]);
9334 } else if (reg == 0x8000001b) {
9335 print_8000001b_eax(words[WORD_EAX]);
9336 } else if (reg == 0x8000001c) {
9337 print_8000001c_eax(words[WORD_EAX]);
9338 print_8000001c_edx(words[WORD_EDX]);
9339 print_8000001c_ebx(words[WORD_EBX]);
9340 print_8000001c_ecx(words[WORD_ECX]);
9341 } else if (reg == 0x8000001d) {
9342 printf(" --- cache %d ---\n", try);
9343 print_8000001d_eax(words[WORD_EAX]);
9344 print_8000001d_ebx(words[WORD_EBX]);
9345 printf(" number of sets = %llu\n",
9346 (unsigned long long)words[WORD_ECX] + 1ULL);
9347 print_8000001d_edx(words[WORD_EDX]);
9348 print_8000001d_synth(words);
9349 } else if (reg == 0x8000001e) {
9350 printf(" extended APIC ID = %u\n", words[WORD_EAX]);
9351 if (Synth_Family(stash->val_80000001_eax) > 0x16) {
9352 print_8000001e_ebx_gt_f16(words[WORD_EBX]);
9353 } else {
9354 print_8000001e_ebx_f16(words[WORD_EBX]);
9355 }
9356 print_8000001e_ecx(words[WORD_ECX]);
9357 } else if (reg == 0x8000001f) {
9358 printf(" AMD Secure Encryption (0x8000001f):\n");
9359 print_8000001f_eax(words[WORD_EAX]);
9360 print_8000001f_ebx(words[WORD_EBX]);
9361 printf(" number of SEV-enabled guests supported = 0x%0x (%u)\n",
9362 words[WORD_ECX], words[WORD_ECX]);
9363 printf(" minimum SEV guest ASID = 0x%0x (%u)\n",
9364 words[WORD_EDX], words[WORD_EDX]);
9365 } else if (reg == 0x80000020) {
9366 if (try == 0) {
9367 printf(" PQoS Enforcement for Memory Bandwidth (0x80000020):\n");
9368 print_80000020_0_ebx(words[WORD_EBX]);
9369 } else if (try == 1) {
9370 printf(" capacity bitmask length = 0x%0llx (%llu)\n",
9371 (unsigned long long)words[WORD_EAX] + 1,
9372 (unsigned long long)words[WORD_EAX] + 1);
9373 printf(" number of classes of service = 0x%0x (%u)\n",
9374 words[WORD_EDX], words[WORD_EDX]);
9375 } else {
9376 print_reg_raw(reg, try, words);
9377 }
9378 } else if (reg == 0x80000021) {
9379 print_80000021_eax(words[WORD_EAX]);
9380 } else if (reg == 0x80860000) {
9381 // max already set to words[WORD_EAX]
9382 } else if (reg == 0x80860001) {
9383 print_80860001_eax(words[WORD_EAX]);
9384 print_80860001_edx(words[WORD_EDX]);
9385 print_80860001_ebx_ecx(words[WORD_EBX], words[WORD_ECX]);
9386 } else if (reg == 0x80860002) {
9387 print_80860002_eax(words[WORD_EAX], stash);
9388 printf(" Transmeta CMS revision (0x80000002/ecx)"
9389 " = %u.%u-%u.%u-%u\n",
9390 (words[WORD_EBX] >> 24) & 0xff,
9391 (words[WORD_EBX] >> 16) & 0xff,
9392 (words[WORD_EBX] >> 8) & 0xff,
9393 (words[WORD_EBX] >> 0) & 0xff,
9394 words[WORD_ECX]);
9395 } else if (reg == 0x80860003) {
9396 // DO NOTHING
9397 } else if (reg == 0x80860004) {
9398 // DO NOTHING
9399 } else if (reg == 0x80860005) {
9400 // DO NOTHING
9401 } else if (reg == 0x80860006) {
9402 printf(" Transmeta information = \"%s\"\n", stash->transmeta_info);
9403 } else if (reg == 0x80860007) {
9404 printf(" Transmeta core clock frequency = %u MHz\n",
9405 words[WORD_EAX]);
9406 printf(" Transmeta processor voltage = %u mV\n",
9407 words[WORD_EBX]);
9408 printf(" Transmeta performance = %u%%\n",
9409 words[WORD_ECX]);
9410 printf(" Transmeta gate delay = %u fs\n",
9411 words[WORD_EDX]);
9412 } else if (reg == 0xc0000000) {
9413 // max already set to words[WORD_EAX]
9414 } else if (reg == 0xc0000001) {
9415 if (stash->vendor == VENDOR_VIA) {
9416 /* TODO: figure out how to decode 0xc0000001:eax */
9417 printf(" 0x%08x 0x%02x: eax=0x%08x\n",
9418 (unsigned int)reg, try, words[WORD_EAX]);
9419 print_c0000001_edx(words[WORD_EDX]);
9420 } else {
9421 print_reg_raw(reg, try, words);
9422 }
9423 } else if (reg == 0xc0000002) {
9424 if (stash->vendor == VENDOR_VIA) {
9425 printf(" VIA C7 Current Performance Data (0xc0000002):\n");
9426 if (BIT_EXTRACT_LE(words[WORD_EAX], 0, 8) != 0) {
9427 printf(" core temperature (degrees C) = %f\n",
9428 (double)words[WORD_EAX] / 256.0);
9429 } else {
9430 printf(" core temperature (degrees C) = %d\n",
9431 BIT_EXTRACT_LE(words[WORD_EAX], 8, 32));
9432 }
9433 print_c0000002_ebx(words[WORD_EBX]);
9434 print_c0000002_ecx(words[WORD_ECX]);
9435 print_c0000002_edx(words[WORD_EDX]);
9436 } else {
9437 print_reg_raw(reg, try, words);
9438 }
9439 } else if (reg == 0xc0000004) {
9440 if (stash->vendor == VENDOR_VIA) {
9441 printf(" VIA Temperature (0xc0000004/eax):\n");
9442 print_c0000004_eax(words[WORD_EAX]);
9443 printf(" VIA MSR 198 Mirror (0xc0000004):\n");
9444 print_c0000004_ebx(words[WORD_EBX]);
9445 print_c0000004_ecx(words[WORD_ECX]);
9446 } else {
9447 print_reg_raw(reg, try, words);
9448 }
9449 } else {
9450 print_reg_raw(reg, try, words);
9451 }
9452 }
9453
9454 #define USE_INSTRUCTION (-2)
9455
9456 #define MAX_CPUS 1024
9457
9458 static int
real_setup(unsigned int cpu,boolean one_cpu,boolean inst)9459 real_setup(unsigned int cpu,
9460 boolean one_cpu,
9461 boolean inst)
9462 {
9463 if (inst) {
9464 if (!one_cpu) {
9465 /*
9466 ** This test is necessary because some versions of Linux will accept
9467 ** a sched_setaffinity mask that includes only nonexistent CPUs.
9468 */
9469 static unsigned int num_cpus = 0;
9470 if (num_cpus == 0) {
9471 num_cpus = sysconf(_SC_NPROCESSORS_CONF);
9472 }
9473 if (cpu >= num_cpus) return -1;
9474
9475 #if defined(USE_KERNEL_SCHED_SETAFFINITY)
9476 /*
9477 ** The interface for sched_setaffinity and cpusets has changed many
9478 ** times. Insulate this tool from all that by calling the system
9479 ** service directly.
9480 */
9481 unsigned int mask[MAX_CPUS / (sizeof(unsigned int)*8)];
9482 bzero(&mask, sizeof(mask));
9483 mask[cpu / (sizeof(unsigned int)*8)]
9484 = (1 << cpu % (sizeof(unsigned int)*8));
9485
9486 int status;
9487 status = syscall(__NR_sched_setaffinity, 0, sizeof(mask), &mask);
9488 #elif defined(USE_PROCESSOR_BIND)
9489 pthread_t thread = pthread_self();
9490 int status = processor_bind(P_LWPID, thread, cpu, NULL);
9491 #else
9492 cpuset_t cpuset;
9493 CPU_ZERO(&cpuset);
9494 CPU_SET(cpu, &cpuset);
9495 int status;
9496 #if defined(__FreeBSD__)
9497 status = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID,
9498 -1, sizeof(cpuset_t), &cpuset);
9499 #else
9500 status = sched_setaffinity(0, sizeof(cpuset_t), &cpuset);
9501 #endif
9502 #endif
9503 if (status == -1) {
9504 if (cpu > 0) {
9505 if (errno == EINVAL) return -1;
9506 }
9507
9508 fprintf(stderr,
9509 "%s: unable to setaffinity to cpu %d; errno = %d (%s)\n",
9510 program, cpu, errno, strerror(errno));
9511 fprintf(stderr,
9512 "%s: using -1 will avoid trying to setaffinity and run"
9513 " on an arbitrary CPU\n",
9514 program);
9515 exit(1);
9516 }
9517
9518 sleep(0); /* to have a chance to migrate */
9519 }
9520
9521 return USE_INSTRUCTION;
9522 } else {
9523 #ifdef USE_CPUID_MODULE
9524 int cpuid_fd = -1;
9525 char cpuid_name[20];
9526
9527 if (cpuid_fd == -1 && cpu == 0) {
9528 cpuid_fd = open("/dev/cpuid", O_RDONLY);
9529 if (cpuid_fd == -1 && errno != ENOENT) {
9530 fprintf(stderr,
9531 "%s: cannot open /dev/cpuid; errno = %d (%s)\n",
9532 program, errno, strerror(errno));
9533 explain_dev_cpu_errno();
9534 }
9535 }
9536
9537 if (cpuid_fd == -1) {
9538 sprintf(cpuid_name, "/dev/cpu/%u/cpuid", cpu);
9539 cpuid_fd = open(cpuid_name, O_RDONLY);
9540 if (cpuid_fd == -1) {
9541 if (cpu > 0) {
9542 if (errno == ENXIO) return -1;
9543 if (errno == ENODEV) return -1;
9544 }
9545 if (errno != ENOENT) {
9546 fprintf(stderr,
9547 "%s: cannot open /dev/cpuid or %s; errno = %d (%s)\n",
9548 program, cpuid_name, errno, strerror(errno));
9549 explain_dev_cpu_errno();
9550 }
9551 }
9552 }
9553
9554 if (cpuid_fd == -1) {
9555 /*
9556 ** Lots of Linux's omit the /dev/cpuid or /dev/cpu/%u/cpuid files.
9557 ** Try creating a temporary file with mknod.
9558 **
9559 ** mkstemp is of absolutely no security value here because I can't
9560 ** use the actual file it generates, and have to delete it and
9561 ** re-create it with mknod. But I have to use it anyway to
9562 ** eliminate errors from smartypants gcc/glibc during the link if I
9563 ** attempt to use tempnam.
9564 */
9565 char tmpname[20];
9566 int dummy_fd;
9567 strcpy(tmpname, "/tmp/cpuidXXXXXX");
9568 dummy_fd = mkstemp(tmpname);
9569 if (dummy_fd != -1) {
9570 close(dummy_fd);
9571 remove(tmpname);
9572 {
9573 int status = mknod(tmpname,
9574 (S_IFCHR | S_IRUSR),
9575 makedev(CPUID_MAJOR, cpu));
9576 if (status == 0) {
9577 cpuid_fd = open(tmpname, O_RDONLY);
9578 remove(tmpname);
9579 }
9580 }
9581 }
9582 if (cpuid_fd == -1) {
9583 if (cpu > 0) {
9584 if (errno == ENXIO) return -1;
9585 if (errno == ENODEV) return -1;
9586 }
9587 fprintf(stderr,
9588 "%s: cannot open /dev/cpuid or %s; errno = %d (%s)\n",
9589 program, cpuid_name, errno, strerror(errno));
9590 explain_dev_cpu_errno();
9591 }
9592 }
9593
9594 return cpuid_fd;
9595 #else
9596 return -1;
9597 #endif
9598 }
9599 }
9600
real_get(int cpuid_fd,unsigned int reg,unsigned int words[],unsigned int ecx,boolean quiet)9601 static int real_get (int cpuid_fd,
9602 unsigned int reg,
9603 unsigned int words[],
9604 unsigned int ecx,
9605 boolean quiet)
9606 {
9607 if (cpuid_fd == USE_INSTRUCTION) {
9608 bzero(words, sizeof(unsigned int)*WORD_NUM);
9609 #ifdef USE_CPUID_COUNT
9610 __cpuid_count(reg, ecx,
9611 words[WORD_EAX],
9612 words[WORD_EBX],
9613 words[WORD_ECX],
9614 words[WORD_EDX]);
9615 #else
9616 asm("cpuid"
9617 : "=a" (words[WORD_EAX]),
9618 "=b" (words[WORD_EBX]),
9619 "=c" (words[WORD_ECX]),
9620 "=d" (words[WORD_EDX])
9621 : "a" (reg),
9622 "c" (ecx));
9623 #endif
9624 } else {
9625 // off64_t result;
9626 // off64_t offset = ((off64_t)ecx << 32) + reg;
9627 int32_t result;
9628 int32_t offset = (int32_t)ecx + reg;
9629 int status;
9630
9631 // result = lseek64(cpuid_fd, offset, SEEK_SET);
9632 result = lseek(cpuid_fd, offset, SEEK_SET);
9633 if (result == -1) {
9634 if (quiet) {
9635 return FALSE;
9636 } else {
9637 fprintf(stderr,
9638 "%s: unable to seek cpuid file to offset 0x%llx;"
9639 " errno = %d (%s)\n",
9640 program, (long long unsigned)offset,
9641 errno, strerror(errno));
9642 exit(1);
9643 }
9644 }
9645
9646 unsigned int old_words[WORD_NUM];
9647 if (ecx != 0) memcpy(old_words, words, sizeof(old_words));
9648
9649 status = read(cpuid_fd, words, 16);
9650 if (status == -1) {
9651 if (quiet) {
9652 return FALSE;
9653 } else {
9654 fprintf(stderr,
9655 "%s: unable to read cpuid file at offset 0x%llx;"
9656 " errno = %d (%s)\n",
9657 program, (long long unsigned)offset,
9658 errno, strerror(errno));
9659 exit(1);
9660 }
9661 }
9662
9663 if (ecx != 0 && memcmp(old_words, words, sizeof(old_words)) == 0) {
9664 if (quiet) {
9665 return FALSE;
9666 } else {
9667 static boolean said = FALSE;
9668 if (!said) {
9669 fprintf(stderr,
9670 "%s: reading cpuid file at offset 0x%llx produced"
9671 " duplicate results\n",
9672 program, (long long unsigned)offset);
9673 fprintf(stderr,
9674 "%s: older kernels do not support cpuid ecx control\n",
9675 program);
9676 fprintf(stderr,
9677 "%s: consider not using -k\n",
9678 program);
9679 said = TRUE;
9680 }
9681 bzero(words, sizeof(old_words));
9682 return FALSE;
9683 }
9684 }
9685 }
9686
9687 return TRUE;
9688 }
9689
9690 static void
print_header(unsigned int reg,unsigned int try,boolean raw)9691 print_header (unsigned int reg,
9692 unsigned int try,
9693 boolean raw)
9694 {
9695 if (!raw) {
9696 if (reg == 2 && try == 0) {
9697 printf(" cache and TLB information (2):\n");
9698 } else if (reg == 4 && try == 0) {
9699 printf(" deterministic cache parameters (4):\n");
9700 } else if (reg == 7 && try == 0) {
9701 printf(" extended feature flags (7):\n");
9702 } else if (reg == 0xb && try == 0) {
9703 printf(" x2APIC features / processor topology (0xb):\n");
9704 } else if (reg == 0x1d && try == 0) {
9705 printf(" Tile Information (0x1d/0):\n");
9706 } else if (reg == 0x1f && try == 0) {
9707 printf(" V2 extended topology (0x1f):\n");
9708 } else if (reg == 0x20 && try == 0) {
9709 printf(" Processor History Reset information (0x20):\n");
9710 } else if (IS_HYPERVISOR_LEAF(reg, 3) && try == 0) {
9711 printf(" hypervisor time features (0x%08x/00):\n", reg);
9712 } else if (IS_HYPERVISOR_LEAF(reg, 3) && try == 1) {
9713 printf(" hypervisor time scale & offset (0x%08x/01):\n", reg);
9714 } else if (IS_HYPERVISOR_LEAF(reg, 3) && try == 2) {
9715 printf(" hypervisor time physical cpu frequency (0x%08x/02):\n", reg);
9716 } else if (reg == 0x8000001d && try == 0) {
9717 printf(" Cache Properties (0x8000001d):\n");
9718 }
9719 }
9720 }
9721
9722 static void
do_real_one(unsigned int reg,unsigned int try,boolean one_cpu,boolean inst,boolean raw,boolean debug UNUSED)9723 do_real_one(unsigned int reg,
9724 unsigned int try,
9725 boolean one_cpu,
9726 boolean inst,
9727 boolean raw,
9728 boolean debug UNUSED)
9729 {
9730 unsigned int cpu;
9731
9732 for (cpu = 0;; cpu++) {
9733 int cpuid_fd = -1;
9734 code_stash_t stash = NIL_STASH;
9735
9736 if (one_cpu && cpu > 0) break;
9737
9738 cpuid_fd = real_setup(cpu, one_cpu, inst);
9739 if (cpuid_fd == -1) break;
9740
9741 if (inst && one_cpu) {
9742 printf("CPU:\n");
9743 } else {
9744 printf("CPU %u:\n", cpu);
9745 }
9746
9747 unsigned int words[WORD_NUM];
9748 real_get(cpuid_fd, reg, words, try, FALSE);
9749 print_reg(reg, words, raw, try, &stash);
9750 }
9751 }
9752
9753 static void
do_real(boolean one_cpu,boolean inst,boolean raw,boolean debug)9754 do_real(boolean one_cpu,
9755 boolean inst,
9756 boolean raw,
9757 boolean debug)
9758 {
9759 unsigned int cpu;
9760
9761 for (cpu = 0;; cpu++) {
9762 int cpuid_fd = -1;
9763 code_stash_t stash = NIL_STASH;
9764 unsigned int max;
9765 unsigned int reg;
9766
9767 if (one_cpu && cpu > 0) break;
9768
9769 cpuid_fd = real_setup(cpu, one_cpu, inst);
9770 if (cpuid_fd == -1) break;
9771
9772 if (inst && one_cpu) {
9773 printf("CPU:\n");
9774 } else {
9775 printf("CPU %u:\n", cpu);
9776 }
9777
9778 max = 0;
9779 for (reg = 0; reg <= max; reg++) {
9780 unsigned int words[WORD_NUM];
9781
9782 real_get(cpuid_fd, reg, words, 0, FALSE);
9783
9784 if (reg == 0) {
9785 max = words[WORD_EAX];
9786 }
9787
9788 if (reg == 2) {
9789 unsigned int max_tries = words[WORD_EAX] & 0xff;
9790 unsigned int try = 0;
9791
9792 print_header(reg, try, raw);
9793
9794 for (;;) {
9795 print_reg(reg, words, raw, try, &stash);
9796
9797 try++;
9798 if (try >= max_tries) break;
9799
9800 real_get(cpuid_fd, reg, words, 0, FALSE);
9801 }
9802 } else if (reg == 4) {
9803 unsigned int try = 0;
9804 while ((words[WORD_EAX] & 0x1f) != 0) {
9805 print_header(reg, try, raw);
9806 print_reg(reg, words, raw, try, &stash);
9807 try++;
9808 real_get(cpuid_fd, reg, words, try, FALSE);
9809 }
9810 } else if (reg == 7) {
9811 unsigned int try = 0;
9812 unsigned int max_tries;
9813 for (;;) {
9814 print_header(reg, try, raw);
9815 print_reg(reg, words, raw, try, &stash);
9816 if (try == 0) {
9817 max_tries = words[WORD_EAX];
9818 }
9819 try++;
9820 if (try > max_tries) break;
9821 real_get(cpuid_fd, reg, words, try, FALSE);
9822 }
9823 } else if (reg == 0xb) {
9824 unsigned int try = 0;
9825 while (words[WORD_EAX] != 0 || words[WORD_EBX] != 0) {
9826 print_header(reg, try, raw);
9827 print_reg(reg, words, raw, try, &stash);
9828 try++;
9829 real_get(cpuid_fd, reg, words, try, FALSE);
9830 }
9831 } else if (reg == 0xd) {
9832 /*
9833 ** ecx values 0 & 1 are special.
9834 **
9835 ** Intel:
9836 ** For ecx values 2..63, the leaf is present if the corresponding
9837 ** bit is present in the bit catenation of 0xd/0/edx + 0xd/0/eax,
9838 ** or the bit catenation of 0xd/1/edx + 0xd/1/ecx.
9839 ** AMD:
9840 ** Only 4 ecx values are defined and it's gappy. It's unclear
9841 ** what the upper bound of any loop would be, so it seems
9842 ** inappropriate to use one.
9843 */
9844 print_header(reg, 0, raw);
9845 print_reg(reg, words, raw, 0, &stash);
9846 unsigned long long valid_xcr0
9847 = ((unsigned long long)words[WORD_EDX] << 32) | words[WORD_EAX];
9848 real_get(cpuid_fd, reg, words, 1, FALSE);
9849 print_reg(reg, words, raw, 1, &stash);
9850 unsigned long long valid_xss
9851 = ((unsigned long long)words[WORD_EDX] << 32) | words[WORD_ECX];
9852 unsigned long long valid_tries = valid_xcr0 | valid_xss;
9853 unsigned int try;
9854 for (try = 2; try < 63; try++) {
9855 if (valid_tries & (1ull << try)) {
9856 real_get(cpuid_fd, reg, words, try, FALSE);
9857 print_reg(reg, words, raw, try, &stash);
9858 }
9859 }
9860 } else if (reg == 0xf) {
9861 unsigned int mask = words[WORD_EDX];
9862 print_header(reg, 0, raw);
9863 print_reg(reg, words, raw, 0, &stash);
9864 if (BIT_EXTRACT_LE(mask, 1, 2)) {
9865 real_get(cpuid_fd, reg, words, 1, FALSE);
9866 print_reg(reg, words, raw, 1, &stash);
9867 }
9868 } else if (reg == 0x10) {
9869 unsigned int mask = words[WORD_EBX];
9870 print_header(reg, 0, raw);
9871 print_reg(reg, words, raw, 0, &stash);
9872 unsigned int try;
9873 for (try = 1; try < 32; try++) {
9874 if (mask & (1 << try)) {
9875 real_get(cpuid_fd, reg, words, try, FALSE);
9876 print_reg(reg, words, raw, try, &stash);
9877 }
9878 }
9879 } else if (reg == 0x12) {
9880 unsigned int mask = words[WORD_EAX];
9881 print_header(reg, 0, raw);
9882 print_reg(reg, words, raw, 0, &stash);
9883 unsigned int try;
9884 for (try = 1; try < 33; try++) {
9885 if (mask & (1 << (try-1))) {
9886 real_get(cpuid_fd, reg, words, try, FALSE);
9887 print_reg(reg, words, raw, try, &stash);
9888 }
9889 }
9890 } else if (reg == 0x14) {
9891 unsigned int try = 0;
9892 unsigned int max_tries;
9893 for (;;) {
9894 print_header(reg, try, raw);
9895 print_reg(reg, words, raw, try, &stash);
9896 if (try == 0) {
9897 max_tries = words[WORD_EAX];
9898 }
9899 try++;
9900 if (try > max_tries) break;
9901 real_get(cpuid_fd, reg, words, try, FALSE);
9902 }
9903 } else if (reg == 0x17) {
9904 unsigned int try = 0;
9905 unsigned int max_tries;
9906 for (;;) {
9907 print_header(reg, try, raw);
9908 print_reg(reg, words, raw, try, &stash);
9909 if (try == 0) {
9910 max_tries = words[WORD_EAX];
9911 }
9912 try++;
9913 if (try > max_tries) break;
9914 real_get(cpuid_fd, reg, words, try, FALSE);
9915 }
9916 } else if (reg == 0x18) {
9917 unsigned int try = 0;
9918 unsigned int max_tries;
9919 for (;;) {
9920 print_header(reg, try, raw);
9921 print_reg(reg, words, raw, try, &stash);
9922 if (try == 0) {
9923 max_tries = words[WORD_EAX];
9924 }
9925 try++;
9926 if (try > max_tries) break;
9927 real_get(cpuid_fd, reg, words, try, FALSE);
9928 }
9929 } else if (reg == 0x1d) {
9930 unsigned int try = 0;
9931 unsigned int max_tries;
9932 for (;;) {
9933 print_header(reg, try, raw);
9934 print_reg(reg, words, raw, try, &stash);
9935 if (try == 0) {
9936 max_tries = words[WORD_EAX];
9937 }
9938 try++;
9939 if (try > max_tries) break;
9940 real_get(cpuid_fd, reg, words, try, FALSE);
9941 }
9942 } else if (reg == 0x1f) {
9943 print_header(reg, 0, raw);
9944 print_reg(reg, words, raw, 0, &stash);
9945 unsigned int try;
9946 for (try = 1; try < 256; try++) {
9947 real_get(cpuid_fd, reg, words, try, FALSE);
9948 print_reg(reg, words, raw, try, &stash);
9949 if (BIT_EXTRACT_LE(words[WORD_ECX], 8, 16) == 0) break;
9950 }
9951 } else if (reg == 0x20) {
9952 unsigned int try = 0;
9953 unsigned int max_tries;
9954 for (;;) {
9955 print_header(reg, try, raw);
9956 print_reg(reg, words, raw, try, &stash);
9957 if (try == 0) {
9958 max_tries = words[WORD_EAX];
9959 }
9960 try++;
9961 if (try > max_tries) break;
9962 real_get(cpuid_fd, reg, words, try, FALSE);
9963 }
9964 } else {
9965 print_reg(reg, words, raw, 0, &stash);
9966 }
9967 }
9968
9969 max = 0x20000000;
9970 for (reg = 0x20000000; reg <= max; reg++) {
9971 boolean success;
9972 unsigned int words[WORD_NUM];
9973
9974 success = real_get(cpuid_fd, reg, words, 0, TRUE);
9975 if (!success) break;
9976
9977 if (reg == 0x20000000) {
9978 max = words[WORD_EAX];
9979 if (max > 0x20000100) {
9980 // Pentium 4 (and probably many early CPUs) don't support this
9981 // leaf correctly and return garbage (which appears to be a
9982 // replica of the values for the last valid leaf in the
9983 // 0x0xxxxxxx range). As a sanity check to avoid an absurdly
9984 // long dump, if the value obviously is out-of-range, just
9985 // disable all further 0x2xxxxxxx leaves.
9986 max = 0x20000000;
9987 }
9988 }
9989
9990 print_reg(reg, words, raw, 0, &stash);
9991 }
9992
9993 if (BIT_EXTRACT_LE(stash.val_1_ecx, 31, 32)) {
9994 // Xen (and probably other hypervisors in the future) support
9995 // configurable ranges, so that hypervisors can exist under other
9996 // hypervisors. Walk the possible base addresses looking for valid
9997 // hypervisors. See Xen's tools/misc/xen-detect.c for the reg range &
9998 // stride.
9999 unsigned int base = 0x40000000;
10000 for (; base < 0x40010000; base += 0x100) {
10001 // Use the base leaf to determine if this is a valid hypervisor, its
10002 // identity, and its max register. Always print the base leaf, even
10003 // if it's invalid (to clearly indicate that it is).
10004 {
10005 boolean success;
10006 unsigned int words[WORD_NUM];
10007
10008 success = real_get(cpuid_fd, base, words, 0, TRUE);
10009 if (!success) break;
10010
10011 print_reg(base, words, raw, 0, &stash);
10012
10013 max = words[WORD_EAX];
10014 if (stash.hypervisor == HYPERVISOR_KVM && max == 0) {
10015 max = base + 1;
10016 }
10017
10018 // Check for broken hypervisor information. If it looks broken,
10019 // skip the reg loop, and break out of the base loop. Note that
10020 // HYPERVISOR_UNKNOWN does not imply broken by itself!
10021 if (stash.hypervisor == HYPERVISOR_UNKNOWN
10022 && max > base + 0x100) {
10023 break;
10024 }
10025 if (max < base) {
10026 break;
10027 }
10028 }
10029
10030 // For a valid hypervisor, walk all additional leaves.
10031 for (reg = base+1; reg <= max; reg++) {
10032 boolean success;
10033 unsigned int words[WORD_NUM];
10034
10035 success = real_get(cpuid_fd, reg, words, 0, TRUE);
10036 if (!success) break;
10037
10038 if (IS_HYPERVISOR_LEAF(reg, 3)
10039 && stash.hypervisor == HYPERVISOR_XEN) {
10040 unsigned int try = 0;
10041 while (try <= 2) {
10042 print_header(reg, try, raw);
10043 print_reg(reg, words, raw, try, &stash);
10044 try++;
10045 real_get(cpuid_fd, reg, words, try, FALSE);
10046 }
10047 } else {
10048 print_reg(reg, words, raw, 0, &stash);
10049 }
10050 }
10051 }
10052 }
10053
10054 max = 0x80000000;
10055 for (reg = 0x80000000; reg <= max; reg++) {
10056 boolean success;
10057 unsigned int words[WORD_NUM];
10058
10059 success = real_get(cpuid_fd, reg, words, 0, TRUE);
10060 if (!success) break;
10061
10062 if (reg == 0x80000000) {
10063 max = words[WORD_EAX];
10064 }
10065
10066 if (reg == 0x8000001d) {
10067 unsigned int try = 0;
10068 while ((words[WORD_EAX] & 0x1f) != 0) {
10069 print_header(reg, try, raw);
10070 print_reg(reg, words, raw, try, &stash);
10071 try++;
10072 real_get(cpuid_fd, reg, words, try, FALSE);
10073 }
10074 } else if (reg == 0x80000020) {
10075 // Rules for loop termination from SKC*.
10076 unsigned int try = 0;
10077 while (words[WORD_EAX] != 0 || words[WORD_EBX] != 0 ||
10078 words[WORD_ECX] != 0 || words[WORD_EDX] != 0) {
10079 print_header(reg, try, raw);
10080 print_reg(reg, words, raw, try, &stash);
10081 try++;
10082 real_get(cpuid_fd, reg, words, try, FALSE);
10083 }
10084 } else {
10085 print_reg(reg, words, raw, 0, &stash);
10086 }
10087 }
10088
10089 max = 0x80860000;
10090 for (reg = 0x80860000; reg <= max; reg++) {
10091 boolean success;
10092 unsigned int words[WORD_NUM];
10093
10094 success = real_get(cpuid_fd, reg, words, 0, TRUE);
10095 if (!success) break;
10096
10097 if (reg == 0x80860000) {
10098 max = words[WORD_EAX];
10099 }
10100
10101 print_reg(reg, words, raw, 0, &stash);
10102 }
10103
10104 max = 0xc0000000;
10105 for (reg = 0xc0000000; reg <= max; reg++) {
10106 boolean success;
10107 unsigned int words[WORD_NUM];
10108
10109 success = real_get(cpuid_fd, reg, words, 0, TRUE);
10110 if (!success) break;
10111
10112 if (reg == 0xc0000000) {
10113 max = words[WORD_EAX];
10114 }
10115
10116 if (max > 0xc0001000) {
10117 // Assume some busted cpuid information and stop walking
10118 // further 0x4xxxxxxx registers.
10119 max = 0xc0000000;
10120 }
10121
10122 print_reg(reg, words, raw, 0, &stash);
10123 }
10124
10125 do_final(raw, debug, &stash);
10126
10127 close(cpuid_fd);
10128 }
10129 }
10130
10131 static void
do_file(ccstring filename,boolean raw,boolean debug)10132 do_file(ccstring filename,
10133 boolean raw,
10134 boolean debug)
10135 {
10136 boolean seen_cpu = FALSE;
10137 unsigned int cpu = -1;
10138 /*
10139 ** The try* variables are a kludge to deal with those leaves that depended on
10140 ** the try (a.k.a. ecx) values that existed with cpuid's old-style method of
10141 ** dumping raw leaves, which lacked an explicit indication of the try number.
10142 ** It is not necessary to add more kludges for more modern ecx-dependent
10143 ** leaves.
10144 */
10145 unsigned int try2 = -1;
10146 unsigned int try4 = -1;
10147 unsigned int try7 = -1;
10148 unsigned int tryb = -1;
10149 unsigned int try8000001d = -1;
10150 code_stash_t stash = NIL_STASH;
10151
10152 FILE* file;
10153 if (strcmp(filename, "-") == 0) {
10154 file = stdin;
10155 } else {
10156 file = fopen(filename, "r");
10157 if (file == NULL) {
10158 fprintf(stderr,
10159 "%s: unable to open %s; errno = %d (%s)\n",
10160 program, filename, errno, strerror(errno));
10161 exit(1);
10162 }
10163 }
10164
10165 while (!feof(file)) {
10166 char buffer[88];
10167 char* ptr;
10168 int status;
10169 unsigned int reg;
10170 unsigned int try;
10171 unsigned int words[WORD_NUM];
10172
10173 ptr = fgets(buffer, LENGTH(buffer), file);
10174 if (ptr == NULL && errno == 0) break;
10175 if (ptr == NULL) {
10176 if (errno != EPIPE) {
10177 fprintf(stderr,
10178 "%s: unable to read a line of text from %s;"
10179 " errno = %d (%s)\n",
10180 program, filename, errno, strerror(errno));
10181 }
10182 exit(1);
10183 }
10184
10185 status = sscanf(ptr, "CPU %u:\r", &cpu);
10186 if (status == 1 || strcmp(ptr, "CPU:\n") == SAME) {
10187 if (seen_cpu) {
10188 do_final(raw, debug, &stash);
10189 }
10190
10191 seen_cpu = TRUE;
10192
10193 if (status == 1) {
10194 printf("CPU %u:\n", cpu);
10195 } else {
10196 printf("CPU:\n");
10197 }
10198 try2 = 0;
10199 try4 = 0;
10200 try7 = 0;
10201 tryb = 0;
10202 try8000001d = 0;
10203 {
10204 static code_stash_t empty_stash = NIL_STASH;
10205 stash = empty_stash;
10206 }
10207 continue;
10208 }
10209
10210 status = sscanf(ptr,
10211 " 0x%x 0x%x: eax=0x%x ebx=0x%x ecx=0x%x edx=0x%x\r",
10212 ®, &try,
10213 &words[WORD_EAX], &words[WORD_EBX],
10214 &words[WORD_ECX], &words[WORD_EDX]);
10215 if (status == 6) {
10216 print_header(reg, try, raw);
10217 print_reg(reg, words, raw, try, &stash);
10218 continue;
10219 }
10220 status = sscanf(ptr,
10221 " 0x%x: eax=0x%x ebx=0x%x ecx=0x%x edx=0x%x\r",
10222 ®,
10223 &words[WORD_EAX], &words[WORD_EBX],
10224 &words[WORD_ECX], &words[WORD_EDX]);
10225 if (status == 5) {
10226 if (reg == 2) {
10227 print_header(reg, try2, raw);
10228 print_reg(reg, words, raw, try2++, &stash);
10229 } else if (reg == 4) {
10230 print_header(reg, try4, raw);
10231 print_reg(reg, words, raw, try4++, &stash);
10232 } else if (reg == 7) {
10233 print_header(reg, try7, raw);
10234 print_reg(reg, words, raw, try7++, &stash);
10235 } else if (reg == 0xb) {
10236 print_header(reg, tryb, raw);
10237 print_reg(reg, words, raw, tryb++, &stash);
10238 } else if (reg == 0x8000001d) {
10239 print_header(reg, try8000001d, raw);
10240 print_reg(reg, words, raw, try8000001d++, &stash);
10241 } else {
10242 print_reg(reg, words, raw, 0, &stash);
10243 }
10244 continue;
10245 }
10246
10247 fprintf(stderr,
10248 "%s: unexpected input with -f option: %s\n",
10249 program, ptr);
10250 exit(1);
10251 }
10252
10253 if (seen_cpu) {
10254 do_final(raw, debug, &stash);
10255 }
10256
10257 if (file != stdin) {
10258 fclose(file);
10259 }
10260 }
10261
10262 int
main(int argc,string argv[])10263 main(int argc,
10264 string argv[])
10265 {
10266 static ccstring shortopts = "+hH1ikrdf:vl:s:";
10267 static const struct option longopts[] = {
10268 { "help", no_argument, NULL, 'h' },
10269 { "one-cpu", no_argument, NULL, '1' },
10270 { "inst", no_argument, NULL, 'i' },
10271 { "kernel", no_argument, NULL, 'k' },
10272 { "raw", no_argument, NULL, 'r' },
10273 { "debug", no_argument, NULL, 'd' },
10274 { "file", required_argument, NULL, 'f' },
10275 { "version", no_argument, NULL, 'v' },
10276 { "leaf", required_argument, NULL, 'l' },
10277 { "subleaf", required_argument, NULL, 's' },
10278 { NULL, no_argument, NULL, '\0' }
10279 };
10280
10281 boolean opt_one_cpu = FALSE;
10282 boolean opt_inst = FALSE;
10283 boolean opt_kernel = FALSE;
10284 boolean opt_raw = FALSE;
10285 boolean opt_debug = FALSE;
10286 cstring opt_filename = NULL;
10287 boolean opt_version = FALSE;
10288 boolean opt_leaf = FALSE;
10289 unsigned long opt_leaf_val = 0;
10290 boolean opt_subleaf = FALSE;
10291 unsigned long opt_subleaf_val = 0;
10292
10293 program = strrchr(argv[0], '/');
10294 if (program == NULL) {
10295 program = argv[0];
10296 } else {
10297 program++;
10298 }
10299
10300 opterr = 0;
10301
10302 for (;;) {
10303 int longindex;
10304 int opt = getopt_long(argc, argv, shortopts, longopts, &longindex);
10305
10306 if (opt == EOF) break;
10307
10308 switch (opt) {
10309 case 'h':
10310 case 'H':
10311 usage();
10312 /*NOTREACHED*/
10313 break;
10314 case '1':
10315 opt_one_cpu = TRUE;
10316 break;
10317 case 'i':
10318 opt_inst = TRUE;
10319 break;
10320 case 'k':
10321 opt_kernel = TRUE;
10322 break;
10323 case 'r':
10324 opt_raw = TRUE;
10325 break;
10326 case 'd':
10327 opt_debug = TRUE;
10328 break;
10329 case 'f':
10330 opt_filename = optarg;
10331 break;
10332 case 'v':
10333 opt_version = TRUE;
10334 break;
10335 case 'l':
10336 opt_leaf = TRUE;
10337 {
10338 errno = 0;
10339 char* endptr = NULL;
10340 opt_leaf_val = strtoul(optarg, &endptr, 0);
10341 if (errno != 0) {
10342 fprintf(stderr,
10343 "%s: argument to -l/--leaf not understood: %s\n",
10344 program, argv[optind-1]);
10345 exit(1);
10346 }
10347 }
10348 break;
10349 case 's':
10350 opt_subleaf = TRUE;
10351 {
10352 errno = 0;
10353 char* endptr = NULL;
10354 opt_subleaf_val = strtoul(optarg, &endptr, 0);
10355 if (errno != 0) {
10356 fprintf(stderr,
10357 "%s: argument to -s/--subleaf not understood: %s\n",
10358 program, argv[optind-1]);
10359 exit(1);
10360 }
10361 }
10362 break;
10363 case '?':
10364 default:
10365 if (optopt == '\0') {
10366 fprintf(stderr,
10367 "%s: unrecognized option: %s\n", program, argv[optind-1]);
10368 } else {
10369 fprintf(stderr,
10370 "%s: unrecognized option letter: %c\n", program, optopt);
10371 }
10372 usage();
10373 /*NOTREACHED*/
10374 }
10375 }
10376
10377 if (optind < argc) {
10378 fprintf(stderr, "%s: unrecognized argument: %s\n", program, argv[optind]);
10379 usage();
10380 /*NOTREACHED*/
10381 }
10382
10383 #ifndef USE_CPUID_MODULE
10384 if (opt_kernel) {
10385 fprintf(stderr, "%s: unrecognized argument: -k\n", program);
10386 usage();
10387 /*NOTREACHED*/
10388 }
10389 #endif
10390
10391 if (opt_inst && opt_kernel) {
10392 fprintf(stderr,
10393 "%s: -i/--inst and -k/--kernel are incompatible options\n",
10394 program);
10395 exit(1);
10396 }
10397
10398 if (opt_filename != NULL && opt_leaf) {
10399 fprintf(stderr,
10400 "%s: -f/--file and -l/--leaf are incompatible options\n",
10401 program);
10402 exit(1);
10403 }
10404
10405 if (opt_subleaf && !opt_leaf) {
10406 fprintf(stderr,
10407 "%s: -s/--subleaf requires that -l/--leaf also be specified\n",
10408 program);
10409 exit(1);
10410 }
10411
10412 // Default to -i. So use inst unless -k is specified.
10413 boolean inst = !opt_kernel;
10414
10415 if (opt_version) {
10416 printf("cpuid version %s\n", XSTR(VERSION));
10417 } else {
10418 if (opt_filename != NULL) {
10419 do_file(opt_filename, opt_raw, opt_debug);
10420 } else if (opt_leaf) {
10421 do_real_one(opt_leaf_val, opt_subleaf_val,
10422 opt_one_cpu, inst, opt_raw, opt_debug);
10423 } else {
10424 do_real(opt_one_cpu, inst, opt_raw, opt_debug);
10425 }
10426 }
10427
10428 exit(0);
10429 /*NOTREACHED*/
10430 }
10431