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                       &reg, &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                       &reg,
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