3 * Determine x86 CPU model number
5 * (c) 2009 Mark Wooding
8 /*----- Licensing notice --------------------------------------------------*
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 /*----- Header files ------------------------------------------------------*/
31 #include <mLib/mdwopt.h>
32 #include <mLib/quis.h>
33 #include <mLib/report.h>
35 #if !defined(__GNUC__) || (!defined(__i386__) && !defined(__amd64__))
36 # error "This isn't going to work."
39 /*----- Data structures ---------------------------------------------------*/
41 struct cpuid { unsigned eax, ebx, ecx, edx; };
43 /*----- Main code ---------------------------------------------------------*/
45 static inline void cpuid(unsigned leaf, struct cpuid *c)
59 static void identify(unsigned f)
62 unsigned stepping, model, family, type, extmodel, extfamily;
63 unsigned dispfamily, dispmodel;
66 stepping = (c.eax >> 0) & 0x0f;
67 model = (c.eax >> 4) & 0x0f;
68 family = (c.eax >> 8) & 0x0f;
69 type = (c.eax >> 12) & 0x03;
70 extmodel = (c.eax >> 16) & 0x0f;
71 extfamily = (c.eax >> 20) & 0xff;
73 dispfamily = family + (family == 0x0f ? extfamily : 0);
74 dispmodel = model | (family == 0x06 || family == 0x0f ? extmodel << 4 : 0);
77 printf("%02X_%02XH\n", dispfamily, dispmodel);
79 printf("type = %d\n", type);
80 printf("family = %d", dispfamily);
82 printf(" (base = %d, extended = %d)", family, extfamily);
84 printf("model = %d", dispmodel);
85 if (family == 0x06 || family == 0x0f)
86 printf(" (base = %d, extended = %d)", model, extmodel);
88 printf("stepping = %d\n", stepping);
92 static void dump(unsigned leaf)
100 printf("%08x: %08x %08x %08x %08x\n", leaf, c.eax, c.ebx, c.ecx, c.edx);
108 static void usage(FILE *fp)
109 { pquis(fp, "Usage: $ [-v] [-i | -d | [-s] LEAF | -x LEAF]\n"); }
111 static void version(void)
112 { pquis(stdout, "$, version " VERSION ); }
114 static void help(void)
116 version(); putchar('\n'); usage(stdout);
118 Shows information about the host's processor. You may find cpuid(1) more\n\
123 -h, --help This useless help text.\n\
124 -V, --version Program's version number.\n\
125 -u, --usage Short usage summary.\n\
127 -v, --verbose Show more detailed information.\n\
129 -i, --identify Show CPU display-model designation. [default]\n\
130 -s, --show=LEAF Show named leaf of CPUID data.\n\
131 -x, --extended=LEAF Show named extended leaf of CPUID data.\n\
132 -d, --dump Dump all CPUID information.\n");
135 int main(int argc, char *argv[])
141 const char *leafstr = 0;
142 unsigned long leaf = -1;
156 static const struct option opts[] = {
157 { "help", 0, 0, 'h' },
158 { "version", 0, 0, 'V' },
159 { "usage", 0, 0, 'u' },
160 { "verbose", 0, 0, 'v' },
161 { "identify", 0, 0, 'i' },
162 { "dump", 0, 0, 'd' },
163 { "show", OPTF_ARGREQ, 0, 's' },
164 { "extended", OPTF_ARGREQ, 0, 'x' },
168 if ((i = mdwopt(argc, argv, "hVu" "v" "ids:x:", opts, 0, 0, 0)) < 0)
184 if (mode) f |= f_bogus;
188 if (mode) f |= f_bogus;
192 if (mode) f |= f_bogus;
197 if (mode) f |= f_bogus;
207 argv += optind; argc -= optind;
208 if ((f & f_bogus) || argc > 1 || (mode && argc)) {
219 leaf = strtoul(leafstr, &q, 0);
220 if (q == leafstr || *q || errno || leaf > 0xffffffff)
221 die(EXIT_FAILURE, "bad leaf value: %s", leafstr);
234 if (!(f & f_verbose))
235 printf("%08x %08x %08x %08x\n", c.eax, c.ebx, c.ecx, c.edx);
237 printf("EAX = %08x\n", c.eax);
238 printf("EBX = %08x\n", c.ebx);
239 printf("ECX = %08x\n", c.ecx);
240 printf("EDX = %08x\n", c.edx);
254 /*----- That's all, folks -------------------------------------------------*/