sync with rev. 1.192
[mplayer/greg.git] / TOOLS / cpuinfo.c
blobf1e8022f9d02b644fa7c56d98e3f6fdfc9979028
1 /* small utility to extract CPU information
2 Used by configure to set CPU optimization levels on some operating
3 systems where /proc/cpuinfo is non-existent or unreliable. */
5 #include <stdio.h>
6 #include <sys/time.h>
8 #ifdef __MINGW32__
9 #include <sys/timeb.h>
10 void gettimeofday(struct timeval* t,void* timezone)
11 { struct timeb timebuffer;
12 ftime( &timebuffer );
13 t->tv_sec=timebuffer.time;
14 t->tv_usec=1000*timebuffer.millitm;
16 #define MISSING_USLEEP
17 #define sleep(t) _sleep(1000*t);
18 #endif
20 #ifdef __BEOS__
21 #define usleep(t) snooze(t)
22 #endif
24 #ifdef M_UNIX
25 typedef long long int64_t;
26 #define MISSING_USLEEP
27 #else
28 #include <inttypes.h>
29 #endif
32 typedef struct cpuid_regs {
33 unsigned int eax;
34 unsigned int ebx;
35 unsigned int ecx;
36 unsigned int edx;
37 } cpuid_regs_t;
39 static cpuid_regs_t
40 cpuid(int func) {
41 cpuid_regs_t regs;
42 #define CPUID ".byte 0x0f, 0xa2; "
43 asm("push %%ebx; "
44 "movl %4,%%eax; " CPUID
45 "movl %%eax,%0; movl %%ebx,%1; movl %%ecx,%2; movl %%edx,%3; "
46 "pop %%ebx"
47 : "=m" (regs.eax), "=m" (regs.ebx), "=m" (regs.ecx), "=m" (regs.edx)
48 : "g" (func)
49 : "%eax", "%ecx", "%edx");
50 return regs;
54 static int64_t
55 rdtsc(void)
57 unsigned int i, j;
58 #define RDTSC ".byte 0x0f, 0x31; "
59 asm(RDTSC : "=a"(i), "=d"(j) : );
60 return ((int64_t)j<<32) + (int64_t)i;
64 static void
65 store32(char *d, unsigned int v)
67 d[0] = v & 0xff;
68 d[1] = (v >> 8) & 0xff;
69 d[2] = (v >> 16) & 0xff;
70 d[3] = (v >> 24) & 0xff;
74 int
75 main(int argc, char **argv)
77 cpuid_regs_t regs, regs_ext;
78 char idstr[13];
79 unsigned max_cpuid;
80 unsigned max_ext_cpuid;
81 unsigned int amd_flags;
82 char *model_name = "Unknown CPU";
83 int i;
84 char processor_name[49];
86 regs = cpuid(0);
87 max_cpuid = regs.eax;
88 /* printf("%d CPUID function codes\n", max_cpuid+1); */
90 store32(idstr+0, regs.ebx);
91 store32(idstr+4, regs.edx);
92 store32(idstr+8, regs.ecx);
93 idstr[12] = 0;
94 printf("vendor_id\t: %s\n", idstr);
96 if (strcmp(idstr, "GenuineIntel") == 0)
97 model_name = "Unknown Intel CPU";
98 else if (strcmp(idstr, "AuthenticAMD") == 0)
99 model_name = "Unknown AMD CPU";
101 regs_ext = cpuid((1<<31) + 0);
102 max_ext_cpuid = regs_ext.eax;
103 if (max_ext_cpuid >= (1<<31) + 1) {
104 regs_ext = cpuid((1<<31) + 1);
105 amd_flags = regs_ext.edx;
107 if (max_ext_cpuid >= (1<<31) + 4) {
108 for (i = 2; i <= 4; i++) {
109 regs_ext = cpuid((1<<31) + i);
110 store32(processor_name + (i-2)*16, regs_ext.eax);
111 store32(processor_name + (i-2)*16 + 4, regs_ext.ebx);
112 store32(processor_name + (i-2)*16 + 8, regs_ext.ecx);
113 store32(processor_name + (i-2)*16 + 12, regs_ext.edx);
115 processor_name[48] = 0;
116 model_name = processor_name;
118 } else {
119 amd_flags = 0;
122 if (max_cpuid >= 1) {
123 static struct {
124 int bit;
125 char *desc;;
126 char *description;
127 } cap[] = {
128 { 0, "fpu", "Floating-point unit on-chip" },
129 { 1, "vme", "Virtual Mode Enhancements" },
130 { 2, "de", "Debugging Extension" },
131 { 3, "pse", "Page Size Extension" },
132 { 4, "tsc", "Time Stamp Counter" },
133 { 5, "msr", "Pentium Processor MSR" },
134 { 6, "pae", "Physical Address Extension" },
135 { 7, "mce", "Machine Check Exception" },
136 { 8, "cx8", "CMPXCHG8B Instruction Supported" },
137 { 9, "apic", "On-chip CPIC Hardware Enabled" },
138 { 11, "sep", "SYSENTER and SYSEXIT" },
139 { 12, "mtrr", "Memory Type Range Registers" },
140 { 13, "pge", "PTE Global Bit" },
141 { 14, "mca", "Machine Check Architecture" },
142 { 15, "cmov", "Conditional Move/Compare Instruction" },
143 { 16, "pat", "Page Attribute Table" },
144 { 17, "pse36", "Page Size Extension 36-bit" },
145 { 18, "psn", "Processor Serial Number" },
146 { 19, "cflsh", "CFLUSH instruction" },
147 { 21, "ds", "Debug Store" },
148 { 22, "acpi", "Thermal Monitor and Clock Ctrl" },
149 { 23, "mmx", "MMX Technology" },
150 { 24, "fxsr", "FXSAVE/FXRSTOR" },
151 { 25, "sse", "SSE Extensions" },
152 { 26, "sse2", "SSE2 Extensions" },
153 { 27, "ss", "Self Snoop" },
154 { 29, "tm", "Therm. Monitor" },
155 { -1 }
157 static struct {
158 int bit;
159 char *desc;;
160 char *description;
161 } cap_amd[] = {
162 { 22, "mmxext","MMX Technology (AMD Extensions)" },
163 { 30, "3dnowext","3Dnow! Extensions" },
164 { 31, "3dnow", "3Dnow!" },
165 { 32, "k6_mtrr", "Memory Type Range Registers" },
166 { -1 }
168 int i;
170 regs = cpuid(1);
171 printf("cpu family\t: %d\n"
172 "model\t\t: %d\n"
173 "stepping\t: %d\n" ,
174 (regs.eax >> 8) & 0xf,
175 (regs.eax >> 4) & 0xf,
176 regs.eax & 0xf);
178 printf("flags\t\t:");
179 for (i = 0; cap[i].bit >= 0; i++) {
180 if (regs.edx & (1 << cap[i].bit)) {
181 printf(" %s", cap[i].desc);
184 for (i = 0; cap_amd[i].bit >= 0; i++) {
185 if (amd_flags & (1 << cap_amd[i].bit)) {
186 printf(" %s", cap_amd[i].desc);
189 printf("\n");
191 if (regs.edx & (1 << 4)) {
192 int64_t tsc_start, tsc_end;
193 struct timeval tv_start, tv_end;
194 int usec_delay;
196 tsc_start = rdtsc();
197 gettimeofday(&tv_start, NULL);
198 #ifdef MISSING_USLEEP
199 sleep(1);
200 #else
201 usleep(100000);
202 #endif
203 tsc_end = rdtsc();
204 gettimeofday(&tv_end, NULL);
206 usec_delay = 1000000 * (tv_end.tv_sec - tv_start.tv_sec)
207 + (tv_end.tv_usec - tv_start.tv_usec);
209 printf("cpu MHz\t\t: %.3f\n",
210 (double)(tsc_end-tsc_start) / usec_delay);
214 printf("model name\t: %s\n", model_name);
216 exit(0);