Mercurial > mplayer.hg
comparison TOOLS/cpuinfo.c @ 1038:b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
author | arpi_esp |
---|---|
date | Tue, 05 Jun 2001 18:40:44 +0000 |
parents | |
children | d7a83bb5fec9 |
comparison
equal
deleted
inserted
replaced
1037:2767682b85de | 1038:b36fb1ae4b53 |
---|---|
1 | |
2 #include <stdio.h> | |
3 #include <sys/time.h> | |
4 | |
5 #ifdef M_UNIX | |
6 typedef long long int64_t; | |
7 #define MISSING_USLEEP | |
8 #else | |
9 #include <inttypes.h> | |
10 #endif | |
11 | |
12 | |
13 typedef struct cpuid_regs { | |
14 unsigned int eax; | |
15 unsigned int ebx; | |
16 unsigned int ecx; | |
17 unsigned int edx; | |
18 } cpuid_regs_t; | |
19 | |
20 static cpuid_regs_t | |
21 cpuid(int func) { | |
22 cpuid_regs_t regs; | |
23 #define CPUID ".byte 0x0f, 0xa2; " | |
24 asm("movl %4,%%eax; " CPUID | |
25 "movl %%eax,%0; movl %%ebx,%1; movl %%ecx,%2; movl %%edx,%3" | |
26 : "=m" (regs.eax), "=m" (regs.ebx), "=m" (regs.ecx), "=m" (regs.edx) | |
27 : "g" (func) | |
28 : "%eax", "%ebx", "%ecx", "%edx"); | |
29 return regs; | |
30 } | |
31 | |
32 | |
33 static int64_t | |
34 rdtsc(void) | |
35 { | |
36 unsigned int i, j; | |
37 #define RDTSC ".byte 0x0f, 0x31; " | |
38 asm(RDTSC : "=a"(i), "=d"(j) : ); | |
39 return ((int64_t)j<<32) + (int64_t)i; | |
40 } | |
41 | |
42 | |
43 static void | |
44 store32(char *d, unsigned int v) | |
45 { | |
46 d[0] = v & 0xff; | |
47 d[1] = (v >> 8) & 0xff; | |
48 d[2] = (v >> 16) & 0xff; | |
49 d[3] = (v >> 24) & 0xff; | |
50 } | |
51 | |
52 | |
53 int | |
54 main(int argc, char **argv) | |
55 { | |
56 cpuid_regs_t regs, regs_ext; | |
57 char idstr[13]; | |
58 unsigned max_cpuid; | |
59 unsigned max_ext_cpuid; | |
60 unsigned int amd_flags; | |
61 char *model_name = "Unknown CPU"; | |
62 int i; | |
63 char processor_name[49]; | |
64 | |
65 regs = cpuid(0); | |
66 max_cpuid = regs.eax; | |
67 /* printf("%d CPUID function codes\n", max_cpuid+1); */ | |
68 | |
69 store32(idstr+0, regs.ebx); | |
70 store32(idstr+4, regs.edx); | |
71 store32(idstr+8, regs.ecx); | |
72 idstr[12] = 0; | |
73 printf("vendor_id\t: %s\n", idstr); | |
74 | |
75 if (strcmp(idstr, "GenuineIntel") == 0) | |
76 model_name = "Unknown Intel CPU"; | |
77 else if (strcmp(idstr, "AuthenticAMD") == 0) | |
78 model_name = "Unknown AMD CPU"; | |
79 | |
80 regs_ext = cpuid((1<<31) + 0); | |
81 max_ext_cpuid = regs_ext.eax; | |
82 if (max_ext_cpuid >= (1<<31) + 1) { | |
83 regs_ext = cpuid((1<<31) + 1); | |
84 amd_flags = regs_ext.edx; | |
85 | |
86 if (max_ext_cpuid >= (1<<31) + 4) { | |
87 for (i = 2; i <= 4; i++) { | |
88 regs_ext = cpuid((1<<31) + i); | |
89 store32(processor_name + (i-2)*16, regs_ext.eax); | |
90 store32(processor_name + (i-2)*16 + 4, regs_ext.ebx); | |
91 store32(processor_name + (i-2)*16 + 8, regs_ext.ecx); | |
92 store32(processor_name + (i-2)*16 + 12, regs_ext.edx); | |
93 } | |
94 processor_name[48] = 0; | |
95 model_name = processor_name; | |
96 } | |
97 } else { | |
98 amd_flags = 0; | |
99 } | |
100 | |
101 if (max_cpuid >= 1) { | |
102 static struct { | |
103 int bit; | |
104 char *desc;; | |
105 char *description; | |
106 } cap[] = { | |
107 { 0, "fpu", "Floating-point unit on-chip" }, | |
108 { 1, "vme", "Virtual Mode Enhancements" }, | |
109 { 2, "de", "Debugging Extension" }, | |
110 { 3, "pse", "Page Size Extension" }, | |
111 { 4, "tsc", "Time Stamp Counter" }, | |
112 { 5, "msr", "Pentium Processor MSR" }, | |
113 { 6, "pae", "Physical Address Extension" }, | |
114 { 7, "mce", "Machine Check Exception" }, | |
115 { 8, "cx8", "CMPXCHG8B Instruction Supported" }, | |
116 { 9, "apic", "On-chip CPIC Hardware Enabled" }, | |
117 { 11, "sep", "SYSENTER and SYSEXIT" }, | |
118 { 12, "mtrr", "Memory Type Range Registers" }, | |
119 { 13, "pge", "PTE Global Bit" }, | |
120 { 14, "mca", "Machine Check Architecture" }, | |
121 { 15, "cmov", "Conditional Move/Compare Instruction" }, | |
122 { 16, "pat", "Page Attribute Table" }, | |
123 { 17, "pse", "Page Size Extension" }, | |
124 { 18, "psn", "Processor Serial Number" }, | |
125 { 19, "cflsh", "CFLUSH instruction" }, | |
126 { 21, "ds", "Debug Store" }, | |
127 { 22, "acpi", "Thermal Monitor and Clock Ctrl" }, | |
128 { 23, "mmx", "MMX Technology" }, | |
129 { 24, "fxsr", "FXSAVE/FXRSTOR" }, | |
130 { 25, "sse", "SSE Extensions" }, | |
131 { 26, "sse2", "SSE2 Extensions" }, | |
132 { 27, "ss", "Self Snoop" }, | |
133 { 29, "tm", "Therm. Monitor" }, | |
134 { -1 } | |
135 }; | |
136 static struct { | |
137 int bit; | |
138 char *desc;; | |
139 char *description; | |
140 } cap_amd[] = { | |
141 { 22, "mmxext","MMX Technology (AMD Extensions)" }, | |
142 { 30, "3dnowext","3Dnow! Extensions" }, | |
143 { 31, "3dnow", "3Dnow!" }, | |
144 { -1 } | |
145 }; | |
146 int i; | |
147 | |
148 regs = cpuid(1); | |
149 printf("cpu family\t: %d\n" | |
150 "model\t\t: %d\n" | |
151 "stepping\t: %d\n" , | |
152 (regs.eax >> 8) & 0xf, | |
153 (regs.eax >> 4) & 0xf, | |
154 regs.eax & 0xf); | |
155 | |
156 printf("flags\t\t:"); | |
157 for (i = 0; cap[i].bit >= 0; i++) { | |
158 if (regs.edx & (1 << cap[i].bit)) { | |
159 printf(" %s", cap[i].desc); | |
160 } | |
161 } | |
162 for (i = 0; cap_amd[i].bit >= 0; i++) { | |
163 if (amd_flags & (1 << cap_amd[i].bit)) { | |
164 printf(" %s", cap_amd[i].desc); | |
165 } | |
166 } | |
167 printf("\n"); | |
168 | |
169 if (regs.edx & (1 << 4)) { | |
170 int64_t tsc_start, tsc_end; | |
171 struct timeval tv_start, tv_end; | |
172 int usec_delay; | |
173 | |
174 tsc_start = rdtsc(); | |
175 gettimeofday(&tv_start, NULL); | |
176 #ifdef MISSING_USLEEP | |
177 sleep(1); | |
178 #else | |
179 usleep(100000); | |
180 #endif | |
181 tsc_end = rdtsc(); | |
182 gettimeofday(&tv_end, NULL); | |
183 | |
184 usec_delay = 1000000 * (tv_end.tv_sec - tv_start.tv_sec) | |
185 + (tv_end.tv_usec - tv_start.tv_usec); | |
186 | |
187 printf("cpu MHz\t\t: %.3f\n", | |
188 (double)(tsc_end-tsc_start) / usec_delay); | |
189 } | |
190 } | |
191 | |
192 printf("model name\t: %s\n", model_name); | |
193 | |
194 exit(0); | |
195 } |