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 -------------------------------------------------*/