1 /*********************************************************************/
2 /* Copyright 2009, 2010 The University of Texas at Austin. */
3 /* All rights reserved. */
4 /* */
5 /* Redistribution and use in source and binary forms, with or */
6 /* without modification, are permitted provided that the following */
7 /* conditions are met: */
8 /* */
9 /* 1. Redistributions of source code must retain the above */
10 /* copyright notice, this list of conditions and the following */
11 /* disclaimer. */
12 /* */
13 /* 2. Redistributions in binary form must reproduce the above */
14 /* copyright notice, this list of conditions and the following */
15 /* disclaimer in the documentation and/or other materials */
16 /* provided with the distribution. */
17 /* */
18 /* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF TEXAS AT */
19 /* AUSTIN ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, */
20 /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
21 /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT */
23 /* AUSTIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */
24 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
25 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */
26 /* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */
27 /* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
28 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
29 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */
30 /* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
31 /* POSSIBILITY OF SUCH DAMAGE. */
32 /* */
33 /* The views and conclusions contained in the software and */
34 /* documentation are those of the authors and should not be */
35 /* interpreted as representing official policies, either expressed */
36 /* or implied, of The University of Texas at Austin. */
37 /*********************************************************************/
38
39 #include <stdio.h>
40 #include <string.h>
41 #include "cpuid.h"
42
43 #ifndef CPUIDEMU
44
45 #if defined(__APPLE__) && defined(__i386__)
46 void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx);
47 #else
cpuid(int op,int * eax,int * ebx,int * ecx,int * edx)48 static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx){
49 __asm__ __volatile__
50 ("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op) : "cc");
51
52 }
53 #endif
54
55 #else
56
57 typedef struct {
58 unsigned int id, a, b, c, d;
59 } idlist_t;
60
61 typedef struct {
62 char *vendor;
63 char *name;
64 int start, stop;
65 } vendor_t;
66
67 extern idlist_t idlist[];
68 extern vendor_t vendor[];
69
70 static int cv = VENDOR;
71
cpuid(unsigned int op,unsigned int * eax,unsigned int * ebx,unsigned int * ecx,unsigned int * edx)72 void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx){
73
74 static int current = 0;
75
76 int start = vendor[cv].start;
77 int stop = vendor[cv].stop;
78 int count = stop - start;
79
80 if ((current < start) || (current > stop)) current = start;
81
82 while ((count > 0) && (idlist[current].id != op)) {
83
84 current ++;
85 if (current > stop) current = start;
86 count --;
87
88 }
89
90 *eax = idlist[current].a;
91 *ebx = idlist[current].b;
92 *ecx = idlist[current].c;
93 *edx = idlist[current].d;
94 }
95
96 #endif
97
have_cpuid(void)98 static inline int have_cpuid(void){
99 int eax, ebx, ecx, edx;
100
101 cpuid(0, &eax, &ebx, &ecx, &edx);
102 return eax;
103 }
104
have_excpuid(void)105 static inline int have_excpuid(void){
106 int eax, ebx, ecx, edx;
107
108 cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
109 return eax & 0xffff;
110 }
111
get_vendor(void)112 int get_vendor(void){
113 int eax, ebx, ecx, edx;
114 char vendor[13];
115
116 cpuid(0, &eax, &ebx, &ecx, &edx);
117
118 *(int *)(&vendor[0]) = ebx;
119 *(int *)(&vendor[4]) = edx;
120 *(int *)(&vendor[8]) = ecx;
121 vendor[12] = (char)0;
122
123 if (!strcmp(vendor, "GenuineIntel")) return VENDOR_INTEL;
124 if (!strcmp(vendor, " UMC UMC UMC")) return VENDOR_UMC;
125 if (!strcmp(vendor, "AuthenticAMD")) return VENDOR_AMD;
126 if (!strcmp(vendor, "CyrixInstead")) return VENDOR_CYRIX;
127 if (!strcmp(vendor, "NexGenDriven")) return VENDOR_NEXGEN;
128 if (!strcmp(vendor, "CentaurHauls")) return VENDOR_CENTAUR;
129 if (!strcmp(vendor, "RiseRiseRise")) return VENDOR_RISE;
130 if (!strcmp(vendor, " SiS SiS SiS")) return VENDOR_SIS;
131 if (!strcmp(vendor, "GenuineTMx86")) return VENDOR_TRANSMETA;
132 if (!strcmp(vendor, "Geode by NSC")) return VENDOR_NSC;
133
134 if ((eax == 0) || ((eax & 0x500) != 0)) return VENDOR_INTEL;
135
136 return VENDOR_UNKNOWN;
137 }
138
get_cputype(int gettype)139 int get_cputype(int gettype){
140 int eax, ebx, ecx, edx;
141 int extend_family, family;
142 int extend_model, model;
143 int type, stepping;
144 int feature = 0;
145
146 cpuid(1, &eax, &ebx, &ecx, &edx);
147
148 switch (gettype) {
149 case GET_EXFAMILY :
150 return BITMASK(eax, 20, 0xff);
151 case GET_EXMODEL :
152 return BITMASK(eax, 16, 0x0f);
153 case GET_TYPE :
154 return BITMASK(eax, 12, 0x03);
155 case GET_FAMILY :
156 return BITMASK(eax, 8, 0x0f);
157 case GET_MODEL :
158 return BITMASK(eax, 4, 0x0f);
159 case GET_APICID :
160 return BITMASK(ebx, 24, 0x0f);
161 case GET_LCOUNT :
162 return BITMASK(ebx, 16, 0x0f);
163 case GET_CHUNKS :
164 return BITMASK(ebx, 8, 0x0f);
165 case GET_STEPPING :
166 return BITMASK(eax, 0, 0x0f);
167 case GET_BLANDID :
168 return BITMASK(ebx, 0, 0xff);
169 case GET_NUMSHARE :
170 if (have_cpuid() < 4) return 0;
171 cpuid(4, &eax, &ebx, &ecx, &edx);
172 return BITMASK(eax, 14, 0xfff);
173 case GET_NUMCORES :
174 if (have_cpuid() < 4) return 0;
175 cpuid(4, &eax, &ebx, &ecx, &edx);
176 return BITMASK(eax, 26, 0x3f);
177
178 case GET_FEATURE :
179 if ((edx & (1 << 3)) != 0) feature |= HAVE_PSE;
180 if ((edx & (1 << 15)) != 0) feature |= HAVE_CMOV;
181 if ((edx & (1 << 19)) != 0) feature |= HAVE_CFLUSH;
182 if ((edx & (1 << 23)) != 0) feature |= HAVE_MMX;
183 if ((edx & (1 << 25)) != 0) feature |= HAVE_SSE;
184 if ((edx & (1 << 26)) != 0) feature |= HAVE_SSE2;
185 if ((edx & (1 << 27)) != 0) {
186 if (BITMASK(ebx, 16, 0x0f) > 0) feature |= HAVE_HIT;
187 }
188 if ((ecx & (1 << 0)) != 0) feature |= HAVE_SSE3;
189 if ((ecx & (1 << 9)) != 0) feature |= HAVE_SSSE3;
190 if ((ecx & (1 << 19)) != 0) feature |= HAVE_SSE4_1;
191 if ((ecx & (1 << 20)) != 0) feature |= HAVE_SSE4_2;
192
193 if (have_excpuid() >= 0x01) {
194 cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
195 if ((ecx & (1 << 6)) != 0) feature |= HAVE_SSE4A;
196 if ((ecx & (1 << 7)) != 0) feature |= HAVE_MISALIGNSSE;
197 if ((edx & (1 << 30)) != 0) feature |= HAVE_3DNOWEX;
198 if ((edx & (1 << 31)) != 0) feature |= HAVE_3DNOW;
199 }
200
201 if (have_excpuid() >= 0x1a) {
202 cpuid(0x8000001a, &eax, &ebx, &ecx, &edx);
203 if ((eax & (1 << 0)) != 0) feature |= HAVE_128BITFPU;
204 if ((eax & (1 << 1)) != 0) feature |= HAVE_FASTMOVU;
205 }
206
207 }
208 return feature;
209 }
210
get_cacheinfo(int type,cache_info_t * cacheinfo)211 int get_cacheinfo(int type, cache_info_t *cacheinfo){
212 int eax, ebx, ecx, edx, cpuid_level;
213 int info[15];
214 int i;
215 cache_info_t LC1, LD1, L2, L3,
216 ITB, DTB, LITB, LDTB,
217 L2ITB, L2DTB, L2LITB, L2LDTB;
218
219 LC1.size = 0; LC1.associative = 0; LC1.linesize = 0; LC1.shared = 0;
220 LD1.size = 0; LD1.associative = 0; LD1.linesize = 0; LD1.shared = 0;
221 L2.size = 0; L2.associative = 0; L2.linesize = 0; L2.shared = 0;
222 L3.size = 0; L3.associative = 0; L3.linesize = 0; L3.shared = 0;
223 ITB.size = 0; ITB.associative = 0; ITB.linesize = 0; ITB.shared = 0;
224 DTB.size = 0; DTB.associative = 0; DTB.linesize = 0; DTB.shared = 0;
225 LITB.size = 0; LITB.associative = 0; LITB.linesize = 0; LITB.shared = 0;
226 LDTB.size = 0; LDTB.associative = 0; LDTB.linesize = 0; LDTB.shared = 0;
227 L2ITB.size = 0; L2ITB.associative = 0; L2ITB.linesize = 0; L2ITB.shared = 0;
228 L2DTB.size = 0; L2DTB.associative = 0; L2DTB.linesize = 0; L2DTB.shared = 0;
229 L2LITB.size = 0; L2LITB.associative = 0; L2LITB.linesize = 0; L2LITB.shared = 0;
230 L2LDTB.size = 0; L2LDTB.associative = 0; L2LDTB.linesize = 0; L2LDTB.shared = 0;
231
232 cpuid(0, &cpuid_level, &ebx, &ecx, &edx);
233
234 if (cpuid_level > 1) {
235
236 cpuid(2, &eax, &ebx, &ecx, &edx);
237
238 info[ 0] = BITMASK(eax, 8, 0xff);
239 info[ 1] = BITMASK(eax, 16, 0xff);
240 info[ 2] = BITMASK(eax, 24, 0xff);
241
242 info[ 3] = BITMASK(ebx, 0, 0xff);
243 info[ 4] = BITMASK(ebx, 8, 0xff);
244 info[ 5] = BITMASK(ebx, 16, 0xff);
245 info[ 6] = BITMASK(ebx, 24, 0xff);
246
247 info[ 7] = BITMASK(ecx, 0, 0xff);
248 info[ 8] = BITMASK(ecx, 8, 0xff);
249 info[ 9] = BITMASK(ecx, 16, 0xff);
250 info[10] = BITMASK(ecx, 24, 0xff);
251
252 info[11] = BITMASK(edx, 0, 0xff);
253 info[12] = BITMASK(edx, 8, 0xff);
254 info[13] = BITMASK(edx, 16, 0xff);
255 info[14] = BITMASK(edx, 24, 0xff);
256
257 for (i = 0; i < 15; i++){
258
259 switch (info[i]){
260
261 /* This table is from http://www.sandpile.org/ia32/cpuid.htm */
262
263 case 0x01 :
264 ITB.size = 4;
265 ITB.associative = 4;
266 ITB.linesize = 32;
267 break;
268 case 0x02 :
269 LITB.size = 4096;
270 LITB.associative = 0;
271 LITB.linesize = 2;
272 break;
273 case 0x03 :
274 DTB.size = 4;
275 DTB.associative = 4;
276 DTB.linesize = 64;
277 break;
278 case 0x04 :
279 LDTB.size = 4096;
280 LDTB.associative = 4;
281 LDTB.linesize = 8;
282 break;
283 case 0x05 :
284 LDTB.size = 4096;
285 LDTB.associative = 4;
286 LDTB.linesize = 32;
287 break;
288 case 0x06 :
289 LC1.size = 8;
290 LC1.associative = 4;
291 LC1.linesize = 32;
292 break;
293 case 0x08 :
294 LC1.size = 16;
295 LC1.associative = 4;
296 LC1.linesize = 32;
297 break;
298 case 0x09 :
299 LC1.size = 32;
300 LC1.associative = 4;
301 LC1.linesize = 64;
302 break;
303 case 0x0a :
304 LD1.size = 8;
305 LD1.associative = 2;
306 LD1.linesize = 32;
307 break;
308 case 0x0c :
309 LD1.size = 16;
310 LD1.associative = 4;
311 LD1.linesize = 32;
312 break;
313 case 0x0d :
314 LD1.size = 16;
315 LD1.associative = 4;
316 LD1.linesize = 64;
317 break;
318 case 0x0e :
319 LD1.size = 24;
320 LD1.associative = 6;
321 LD1.linesize = 64;
322 break;
323 case 0x10 :
324 LD1.size = 16;
325 LD1.associative = 4;
326 LD1.linesize = 32;
327 break;
328 case 0x15 :
329 LC1.size = 16;
330 LC1.associative = 4;
331 LC1.linesize = 32;
332 break;
333 case 0x1a :
334 L2.size = 96;
335 L2.associative = 6;
336 L2.linesize = 64;
337 break;
338 case 0x21 :
339 L2.size = 256;
340 L2.associative = 8;
341 L2.linesize = 64;
342 break;
343 case 0x22 :
344 L3.size = 512;
345 L3.associative = 4;
346 L3.linesize = 64;
347 break;
348 case 0x23 :
349 L3.size = 1024;
350 L3.associative = 8;
351 L3.linesize = 64;
352 break;
353 case 0x25 :
354 L3.size = 2048;
355 L3.associative = 8;
356 L3.linesize = 64;
357 break;
358 case 0x29 :
359 L3.size = 4096;
360 L3.associative = 8;
361 L3.linesize = 64;
362 break;
363 case 0x2c :
364 LD1.size = 32;
365 LD1.associative = 8;
366 LD1.linesize = 64;
367 break;
368 case 0x30 :
369 LC1.size = 32;
370 LC1.associative = 8;
371 LC1.linesize = 64;
372 break;
373 case 0x39 :
374 L2.size = 128;
375 L2.associative = 4;
376 L2.linesize = 64;
377 break;
378 case 0x3a :
379 L2.size = 192;
380 L2.associative = 6;
381 L2.linesize = 64;
382 break;
383 case 0x3b :
384 L2.size = 128;
385 L2.associative = 2;
386 L2.linesize = 64;
387 break;
388 case 0x3c :
389 L2.size = 256;
390 L2.associative = 4;
391 L2.linesize = 64;
392 break;
393 case 0x3d :
394 L2.size = 384;
395 L2.associative = 6;
396 L2.linesize = 64;
397 break;
398 case 0x3e :
399 L2.size = 512;
400 L2.associative = 4;
401 L2.linesize = 64;
402 break;
403 case 0x41 :
404 L2.size = 128;
405 L2.associative = 4;
406 L2.linesize = 32;
407 break;
408 case 0x42 :
409 L2.size = 256;
410 L2.associative = 4;
411 L2.linesize = 32;
412 break;
413 case 0x43 :
414 L2.size = 512;
415 L2.associative = 4;
416 L2.linesize = 32;
417 break;
418 case 0x44 :
419 L2.size = 1024;
420 L2.associative = 4;
421 L2.linesize = 32;
422 break;
423 case 0x45 :
424 L2.size = 2048;
425 L2.associative = 4;
426 L2.linesize = 32;
427 break;
428 case 0x46 :
429 L3.size = 4096;
430 L3.associative = 4;
431 L3.linesize = 64;
432 break;
433 case 0x47 :
434 L3.size = 8192;
435 L3.associative = 8;
436 L3.linesize = 64;
437 break;
438 case 0x48 :
439 L2.size = 3184;
440 L2.associative = 12;
441 L2.linesize = 64;
442 break;
443 case 0x49 :
444 if ((get_cputype(GET_FAMILY) == 0x0f) && (get_cputype(GET_MODEL) == 0x06)) {
445 L3.size = 4096;
446 L3.associative = 16;
447 L3.linesize = 64;
448 } else {
449 L2.size = 4096;
450 L2.associative = 16;
451 L2.linesize = 64;
452 }
453 break;
454 case 0x4a :
455 L3.size = 6144;
456 L3.associative = 12;
457 L3.linesize = 64;
458 break;
459 case 0x4b :
460 L3.size = 8192;
461 L3.associative = 16;
462 L3.linesize = 64;
463 break;
464 case 0x4c :
465 L3.size = 12280;
466 L3.associative = 12;
467 L3.linesize = 64;
468 break;
469 case 0x4d :
470 L3.size = 16384;
471 L3.associative = 16;
472 L3.linesize = 64;
473 break;
474 case 0x4e :
475 L2.size = 6144;
476 L2.associative = 24;
477 L2.linesize = 64;
478 break;
479 case 0x4f :
480 ITB.size = 4;
481 ITB.associative = 0;
482 ITB.linesize = 32;
483 break;
484 case 0x50 :
485 ITB.size = 4;
486 ITB.associative = 0;
487 ITB.linesize = 64;
488 LITB.size = 4096;
489 LITB.associative = 0;
490 LITB.linesize = 64;
491 LITB.shared = 1;
492 break;
493 case 0x51 :
494 ITB.size = 4;
495 ITB.associative = 0;
496 ITB.linesize = 128;
497 LITB.size = 4096;
498 LITB.associative = 0;
499 LITB.linesize = 128;
500 LITB.shared = 1;
501 break;
502 case 0x52 :
503 ITB.size = 4;
504 ITB.associative = 0;
505 ITB.linesize = 256;
506 LITB.size = 4096;
507 LITB.associative = 0;
508 LITB.linesize = 256;
509 LITB.shared = 1;
510 break;
511 case 0x55 :
512 LITB.size = 4096;
513 LITB.associative = 0;
514 LITB.linesize = 7;
515 LITB.shared = 1;
516 break;
517 case 0x56 :
518 LDTB.size = 4096;
519 LDTB.associative = 4;
520 LDTB.linesize = 16;
521 break;
522 case 0x57 :
523 LDTB.size = 4096;
524 LDTB.associative = 4;
525 LDTB.linesize = 16;
526 break;
527 case 0x5b :
528 DTB.size = 4;
529 DTB.associative = 0;
530 DTB.linesize = 64;
531 LDTB.size = 4096;
532 LDTB.associative = 0;
533 LDTB.linesize = 64;
534 LDTB.shared = 1;
535 break;
536 case 0x5c :
537 DTB.size = 4;
538 DTB.associative = 0;
539 DTB.linesize = 128;
540 LDTB.size = 4096;
541 LDTB.associative = 0;
542 LDTB.linesize = 128;
543 LDTB.shared = 1;
544 break;
545 case 0x5d :
546 DTB.size = 4;
547 DTB.associative = 0;
548 DTB.linesize = 256;
549 LDTB.size = 4096;
550 LDTB.associative = 0;
551 LDTB.linesize = 256;
552 LDTB.shared = 1;
553 break;
554 case 0x60 :
555 LD1.size = 16;
556 LD1.associative = 8;
557 LD1.linesize = 64;
558 break;
559 case 0x66 :
560 LD1.size = 8;
561 LD1.associative = 4;
562 LD1.linesize = 64;
563 break;
564 case 0x67 :
565 LD1.size = 16;
566 LD1.associative = 4;
567 LD1.linesize = 64;
568 break;
569 case 0x68 :
570 LD1.size = 32;
571 LD1.associative = 4;
572 LD1.linesize = 64;
573 break;
574 case 0x70 :
575 LC1.size = 12;
576 LC1.associative = 8;
577 break;
578 case 0x71 :
579 LC1.size = 16;
580 LC1.associative = 8;
581 break;
582 case 0x72 :
583 LC1.size = 32;
584 LC1.associative = 8;
585 break;
586 case 0x73 :
587 LC1.size = 64;
588 LC1.associative = 8;
589 break;
590 case 0x77 :
591 LC1.size = 16;
592 LC1.associative = 4;
593 LC1.linesize = 64;
594 break;
595 case 0x78 :
596 L2.size = 1024;
597 L2.associative = 4;
598 L2.linesize = 64;
599 break;
600 case 0x79 :
601 L2.size = 128;
602 L2.associative = 8;
603 L2.linesize = 64;
604 break;
605 case 0x7a :
606 L2.size = 256;
607 L2.associative = 8;
608 L2.linesize = 64;
609 break;
610 case 0x7b :
611 L2.size = 512;
612 L2.associative = 8;
613 L2.linesize = 64;
614 break;
615 case 0x7c :
616 L2.size = 1024;
617 L2.associative = 8;
618 L2.linesize = 64;
619 break;
620 case 0x7d :
621 L2.size = 2048;
622 L2.associative = 8;
623 L2.linesize = 64;
624 break;
625 case 0x7e :
626 L2.size = 256;
627 L2.associative = 8;
628 L2.linesize = 128;
629 break;
630 case 0x7f :
631 L2.size = 512;
632 L2.associative = 2;
633 L2.linesize = 64;
634 break;
635 case 0x81 :
636 L2.size = 128;
637 L2.associative = 8;
638 L2.linesize = 32;
639 break;
640 case 0x82 :
641 L2.size = 256;
642 L2.associative = 8;
643 L2.linesize = 32;
644 break;
645 case 0x83 :
646 L2.size = 512;
647 L2.associative = 8;
648 L2.linesize = 32;
649 break;
650 case 0x84 :
651 L2.size = 1024;
652 L2.associative = 8;
653 L2.linesize = 32;
654 break;
655 case 0x85 :
656 L2.size = 2048;
657 L2.associative = 8;
658 L2.linesize = 32;
659 break;
660 case 0x86 :
661 L2.size = 512;
662 L2.associative = 4;
663 L2.linesize = 64;
664 break;
665 case 0x87 :
666 L2.size = 1024;
667 L2.associative = 8;
668 L2.linesize = 64;
669 break;
670 case 0x88 :
671 L3.size = 2048;
672 L3.associative = 4;
673 L3.linesize = 64;
674 break;
675 case 0x89 :
676 L3.size = 4096;
677 L3.associative = 4;
678 L3.linesize = 64;
679 break;
680 case 0x8a :
681 L3.size = 8192;
682 L3.associative = 4;
683 L3.linesize = 64;
684 break;
685 case 0x8d :
686 L3.size = 3096;
687 L3.associative = 12;
688 L3.linesize = 128;
689 break;
690 case 0x90 :
691 ITB.size = 4;
692 ITB.associative = 0;
693 ITB.linesize = 64;
694 break;
695 case 0x96 :
696 DTB.size = 4;
697 DTB.associative = 0;
698 DTB.linesize = 32;
699 break;
700 case 0x9b :
701 L2DTB.size = 4;
702 L2DTB.associative = 0;
703 L2DTB.linesize = 96;
704 break;
705 case 0xb0 :
706 ITB.size = 4;
707 ITB.associative = 4;
708 ITB.linesize = 128;
709 break;
710 case 0xb1 :
711 LITB.size = 4096;
712 LITB.associative = 4;
713 LITB.linesize = 4;
714 break;
715 case 0xb2 :
716 ITB.size = 4;
717 ITB.associative = 4;
718 ITB.linesize = 64;
719 break;
720 case 0xb3 :
721 DTB.size = 4;
722 DTB.associative = 4;
723 DTB.linesize = 128;
724 break;
725 case 0xb4 :
726 DTB.size = 4;
727 DTB.associative = 4;
728 DTB.linesize = 256;
729 break;
730 case 0xba :
731 DTB.size = 4;
732 DTB.associative = 4;
733 DTB.linesize = 64;
734 break;
735 case 0xd0 :
736 L3.size = 512;
737 L3.associative = 4;
738 L3.linesize = 64;
739 break;
740 case 0xd1 :
741 L3.size = 1024;
742 L3.associative = 4;
743 L3.linesize = 64;
744 break;
745 case 0xd2 :
746 L3.size = 2048;
747 L3.associative = 4;
748 L3.linesize = 64;
749 break;
750 case 0xd6 :
751 L3.size = 1024;
752 L3.associative = 8;
753 L3.linesize = 64;
754 break;
755 case 0xd7 :
756 L3.size = 2048;
757 L3.associative = 8;
758 L3.linesize = 64;
759 break;
760 case 0xd8 :
761 L3.size = 4096;
762 L3.associative = 8;
763 L3.linesize = 64;
764 break;
765 case 0xdc :
766 L3.size = 2048;
767 L3.associative = 12;
768 L3.linesize = 64;
769 break;
770 case 0xdd :
771 L3.size = 4096;
772 L3.associative = 12;
773 L3.linesize = 64;
774 break;
775 case 0xde :
776 L3.size = 8192;
777 L3.associative = 12;
778 L3.linesize = 64;
779 break;
780 case 0xe2 :
781 L3.size = 2048;
782 L3.associative = 16;
783 L3.linesize = 64;
784 break;
785 case 0xe3 :
786 L3.size = 4096;
787 L3.associative = 16;
788 L3.linesize = 64;
789 break;
790 case 0xe4 :
791 L3.size = 8192;
792 L3.associative = 16;
793 L3.linesize = 64;
794 break;
795 }
796 }
797 }
798
799 if (get_vendor() == VENDOR_INTEL) {
800 cpuid(0x80000000, &cpuid_level, &ebx, &ecx, &edx);
801 if (cpuid_level >= 0x80000006) {
802 cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
803
804 L2.size = BITMASK(ecx, 16, 0xffff);
805 L2.associative = BITMASK(ecx, 12, 0x0f);
806 L2.linesize = BITMASK(ecx, 0, 0xff);
807 }
808 }
809
810 if ((get_vendor() == VENDOR_AMD) || (get_vendor() == VENDOR_CENTAUR)) {
811 cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
812
813 LDTB.size = 4096;
814 LDTB.associative = BITMASK(eax, 24, 0xff);
815 if (LDTB.associative == 0xff) LDTB.associative = 0;
816 LDTB.linesize = BITMASK(eax, 16, 0xff);
817
818 LITB.size = 4096;
819 LITB.associative = BITMASK(eax, 8, 0xff);
820 if (LITB.associative == 0xff) LITB.associative = 0;
821 LITB.linesize = BITMASK(eax, 0, 0xff);
822
823 DTB.size = 4;
824 DTB.associative = BITMASK(ebx, 24, 0xff);
825 if (DTB.associative == 0xff) DTB.associative = 0;
826 DTB.linesize = BITMASK(ebx, 16, 0xff);
827
828 ITB.size = 4;
829 ITB.associative = BITMASK(ebx, 8, 0xff);
830 if (ITB.associative == 0xff) ITB.associative = 0;
831 ITB.linesize = BITMASK(ebx, 0, 0xff);
832
833 LD1.size = BITMASK(ecx, 24, 0xff);
834 LD1.associative = BITMASK(ecx, 16, 0xff);
835 if (LD1.associative == 0xff) LD1.associative = 0;
836 LD1.linesize = BITMASK(ecx, 0, 0xff);
837
838 LC1.size = BITMASK(ecx, 24, 0xff);
839 LC1.associative = BITMASK(ecx, 16, 0xff);
840 if (LC1.associative == 0xff) LC1.associative = 0;
841 LC1.linesize = BITMASK(ecx, 0, 0xff);
842
843 cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
844
845 L2LDTB.size = 4096;
846 L2LDTB.associative = BITMASK(eax, 24, 0xff);
847 if (L2LDTB.associative == 0xff) L2LDTB.associative = 0;
848 L2LDTB.linesize = BITMASK(eax, 16, 0xff);
849
850 L2LITB.size = 4096;
851 L2LITB.associative = BITMASK(eax, 8, 0xff);
852 if (L2LITB.associative == 0xff) L2LITB.associative = 0;
853 L2LITB.linesize = BITMASK(eax, 0, 0xff);
854
855 L2DTB.size = 4;
856 L2DTB.associative = BITMASK(ebx, 24, 0xff);
857 if (L2DTB.associative == 0xff) L2DTB.associative = 0;
858 L2DTB.linesize = BITMASK(ebx, 16, 0xff);
859
860 L2ITB.size = 4;
861 L2ITB.associative = BITMASK(ebx, 8, 0xff);
862 if (L2ITB.associative == 0xff) L2ITB.associative = 0;
863 L2ITB.linesize = BITMASK(ebx, 0, 0xff);
864
865 L2.size = BITMASK(ecx, 16, 0xffff);
866 L2.associative = BITMASK(ecx, 12, 0xf);
867 if (L2.associative == 0xff) L2.associative = 0;
868 L2.linesize = BITMASK(ecx, 0, 0xff);
869
870 L3.size = BITMASK(edx, 18, 0x3fff) * 512;
871 L3.associative = BITMASK(edx, 12, 0xf);
872 if (L3.associative == 0xff) L2.associative = 0;
873 L3.linesize = BITMASK(edx, 0, 0xff);
874
875 }
876
877 switch (type) {
878
879 case CACHE_INFO_L1_I :
880 *cacheinfo = LC1;
881 break;
882 case CACHE_INFO_L1_D :
883 *cacheinfo = LD1;
884 break;
885 case CACHE_INFO_L2 :
886 *cacheinfo = L2;
887 break;
888 case CACHE_INFO_L3 :
889 *cacheinfo = L3;
890 break;
891 case CACHE_INFO_L1_DTB :
892 *cacheinfo = DTB;
893 break;
894 case CACHE_INFO_L1_ITB :
895 *cacheinfo = ITB;
896 break;
897 case CACHE_INFO_L1_LDTB :
898 *cacheinfo = LDTB;
899 break;
900 case CACHE_INFO_L1_LITB :
901 *cacheinfo = LITB;
902 break;
903 case CACHE_INFO_L2_DTB :
904 *cacheinfo = L2DTB;
905 break;
906 case CACHE_INFO_L2_ITB :
907 *cacheinfo = L2ITB;
908 break;
909 case CACHE_INFO_L2_LDTB :
910 *cacheinfo = L2LDTB;
911 break;
912 case CACHE_INFO_L2_LITB :
913 *cacheinfo = L2LITB;
914 break;
915 }
916 return 0;
917 }
918
get_cpuname(void)919 int get_cpuname(void){
920
921 int family, exfamily, model, vendor, exmodel;
922
923 if (!have_cpuid()) return CPUTYPE_80386;
924
925 family = get_cputype(GET_FAMILY);
926 exfamily = get_cputype(GET_EXFAMILY);
927 model = get_cputype(GET_MODEL);
928 exmodel = get_cputype(GET_EXMODEL);
929
930 vendor = get_vendor();
931
932 if (vendor == VENDOR_INTEL){
933 switch (family) {
934 case 0x4:
935 return CPUTYPE_80486;
936 case 0x5:
937 return CPUTYPE_PENTIUM;
938 case 0x6:
939 switch (exmodel) {
940 case 0:
941 switch (model) {
942 case 1:
943 case 3:
944 case 5:
945 case 6:
946 return CPUTYPE_PENTIUM2;
947 case 7:
948 case 8:
949 case 10:
950 case 11:
951 return CPUTYPE_PENTIUM3;
952 case 9:
953 case 13:
954 case 14:
955 return CPUTYPE_PENTIUMM;
956 case 15:
957 return CPUTYPE_CORE2;
958 }
959 break;
960 case 1:
961 switch (model) {
962 case 6:
963 return CPUTYPE_CORE2;
964 case 7:
965 return CPUTYPE_PENRYN;
966 case 10:
967 case 11:
968 case 14:
969 case 15:
970 return CPUTYPE_NEHALEM;
971 case 12:
972 return CPUTYPE_ATOM;
973 case 13:
974 return CPUTYPE_DUNNINGTON;
975 break;
976 }
977 }
978 break;
979 case 0x7:
980 return CPUTYPE_ITANIUM;
981 case 0xf:
982 switch (exfamily) {
983 case 0 :
984 return CPUTYPE_PENTIUM4;
985 case 1 :
986 return CPUTYPE_ITANIUM;
987 }
988 break;
989 }
990 return CPUTYPE_INTEL_UNKNOWN;
991 }
992
993 if (vendor == VENDOR_AMD){
994 switch (family) {
995 case 0x4:
996 return CPUTYPE_AMD5X86;
997 case 0x5:
998 return CPUTYPE_AMDK6;
999 case 0x6:
1000 return CPUTYPE_ATHLON;
1001 case 0xf:
1002 switch (exfamily) {
1003 case 0:
1004 case 2:
1005 return CPUTYPE_OPTERON;
1006 case 1:
1007 case 10:
1008 return CPUTYPE_BARCELONA;
1009 }
1010 break;
1011 }
1012 return CPUTYPE_AMD_UNKNOWN;
1013 }
1014
1015 if (vendor == VENDOR_CYRIX){
1016 switch (family) {
1017 case 0x4:
1018 return CPUTYPE_CYRIX5X86;
1019 case 0x5:
1020 return CPUTYPE_CYRIXM1;
1021 case 0x6:
1022 return CPUTYPE_CYRIXM2;
1023 }
1024 return CPUTYPE_CYRIX_UNKNOWN;
1025 }
1026
1027 if (vendor == VENDOR_NEXGEN){
1028 switch (family) {
1029 case 0x5:
1030 return CPUTYPE_NEXGENNX586;
1031 }
1032 return CPUTYPE_NEXGEN_UNKNOWN;
1033 }
1034
1035 if (vendor == VENDOR_CENTAUR){
1036 switch (family) {
1037 case 0x5:
1038 return CPUTYPE_CENTAURC6;
1039 break;
1040 case 0x6:
1041 return CPUTYPE_NANO;
1042 break;
1043
1044 }
1045 return CPUTYPE_VIAC3;
1046 }
1047
1048 if (vendor == VENDOR_RISE){
1049 switch (family) {
1050 case 0x5:
1051 return CPUTYPE_RISEMP6;
1052 }
1053 return CPUTYPE_RISE_UNKNOWN;
1054 }
1055
1056 if (vendor == VENDOR_SIS){
1057 switch (family) {
1058 case 0x5:
1059 return CPUTYPE_SYS55X;
1060 }
1061 return CPUTYPE_SIS_UNKNOWN;
1062 }
1063
1064 if (vendor == VENDOR_TRANSMETA){
1065 switch (family) {
1066 case 0x5:
1067 return CPUTYPE_CRUSOETM3X;
1068 }
1069 return CPUTYPE_TRANSMETA_UNKNOWN;
1070 }
1071
1072 if (vendor == VENDOR_NSC){
1073 switch (family) {
1074 case 0x5:
1075 return CPUTYPE_NSGEODE;
1076 }
1077 return CPUTYPE_NSC_UNKNOWN;
1078 }
1079
1080 return CPUTYPE_UNKNOWN;
1081 }
1082
1083 static char *cpuname[] = {
1084 "UNKNOWN",
1085 "INTEL_UNKNOWN",
1086 "UMC_UNKNOWN",
1087 "AMD_UNKNOWN",
1088 "CYRIX_UNKNOWN",
1089 "NEXGEN_UNKNOWN",
1090 "CENTAUR_UNKNOWN",
1091 "RISE_UNKNOWN",
1092 "SIS_UNKNOWN",
1093 "TRANSMETA_UNKNOWN",
1094 "NSC_UNKNOWN",
1095 "80386",
1096 "80486",
1097 "PENTIUM",
1098 "PENTIUM2",
1099 "PENTIUM3",
1100 "PENTIUMM",
1101 "PENTIUM4",
1102 "CORE2",
1103 "PENRYN",
1104 "DUNNINGTON",
1105 "NEHALEM",
1106 "ATOM",
1107 "ITANIUM",
1108 "ITANIUM2",
1109 "5X86",
1110 "K6",
1111 "ATHLON",
1112 "DURON",
1113 "OPTERON",
1114 "BARCELONA",
1115 "SHANGHAI",
1116 "ISTANBUL",
1117 "CYRIX5X86",
1118 "CYRIXM1",
1119 "CYRIXM2",
1120 "NEXGENNX586",
1121 "CENTAURC6",
1122 "RISEMP6",
1123 "SYS55X",
1124 "TM3X00",
1125 "NSGEODE",
1126 "VIAC3",
1127 "NANO",
1128 };
1129
1130 static char *lowercpuname[] = {
1131 "unknown",
1132 "intel_unknown",
1133 "umc_unknown",
1134 "amd_unknown",
1135 "cyrix_unknown",
1136 "nexgen_unknown",
1137 "centaur_unknown",
1138 "rise_unknown",
1139 "sis_unknown",
1140 "transmeta_unknown",
1141 "nsc_unknown",
1142 "80386",
1143 "80486",
1144 "pentium",
1145 "pentium2",
1146 "pentium3",
1147 "pentiumm",
1148 "pentium4",
1149 "core2",
1150 "penryn",
1151 "dunnington",
1152 "nehalem",
1153 "atom",
1154 "itanium",
1155 "itanium2",
1156 "5x86",
1157 "k6",
1158 "athlon",
1159 "duron",
1160 "opteron",
1161 "barcelona",
1162 "shanghai",
1163 "istanbul",
1164 "cyrix5x86",
1165 "cyrixm1",
1166 "cyrixm2",
1167 "nexgennx586",
1168 "centaurc6",
1169 "risemp6",
1170 "sys55x",
1171 "tms3x00",
1172 "nsgeode",
1173 "nano",
1174 };
1175
1176 static char *corename[] = {
1177 "UNKOWN",
1178 "80486",
1179 "P5",
1180 "P6",
1181 "KATMAI",
1182 "COPPERMINE",
1183 "NORTHWOOD",
1184 "PRESCOTT",
1185 "BANIAS",
1186 "ATHLON",
1187 "OPTERON",
1188 "BARCELONA",
1189 "VIAC3",
1190 "YONAH",
1191 "CORE2",
1192 "PENRYN",
1193 "DUNNINGTON",
1194 "NEHALEM",
1195 "ATOM",
1196 "NANO",
1197 };
1198
1199 static char *corename_lower[] = {
1200 "unknown",
1201 "80486",
1202 "p5",
1203 "p6",
1204 "katmai",
1205 "coppermine",
1206 "northwood",
1207 "prescott",
1208 "banias",
1209 "athlon",
1210 "opteron",
1211 "barcelona",
1212 "viac3",
1213 "yonah",
1214 "core2",
1215 "penryn",
1216 "dunnington",
1217 "nehalem",
1218 "atom",
1219 "nano",
1220 };
1221
1222
get_cpunamechar(void)1223 char *get_cpunamechar(void){
1224 return cpuname[get_cpuname()];
1225 }
1226
get_lower_cpunamechar(void)1227 char *get_lower_cpunamechar(void){
1228 return lowercpuname[get_cpuname()];
1229 }
1230
1231
get_coretype(void)1232 int get_coretype(void){
1233
1234 int family, exfamily, model, exmodel, vendor;
1235
1236 if (!have_cpuid()) return CORE_80486;
1237
1238 family = get_cputype(GET_FAMILY);
1239 exfamily = get_cputype(GET_EXFAMILY);
1240 model = get_cputype(GET_MODEL);
1241 exmodel = get_cputype(GET_EXMODEL);
1242
1243 vendor = get_vendor();
1244
1245 if (vendor == VENDOR_INTEL){
1246 switch (family) {
1247 case 4:
1248 return CORE_80486;
1249 case 5:
1250 return CORE_P5;
1251 case 6:
1252 switch (exmodel) {
1253 case 0:
1254 switch (model) {
1255 case 0:
1256 case 1:
1257 case 2:
1258 case 3:
1259 case 4:
1260 case 5:
1261 case 6:
1262 return CORE_P6;
1263 case 7:
1264 return CORE_KATMAI;
1265 case 8:
1266 case 10:
1267 case 11:
1268 return CORE_COPPERMINE;
1269 case 9:
1270 case 13:
1271 case 14:
1272 return CORE_BANIAS;
1273 case 15:
1274 return CORE_CORE2;
1275 }
1276 break;
1277 case 1:
1278 switch (model) {
1279 case 6:
1280 return CORE_CORE2;
1281 case 7:
1282 return CORE_PENRYN;
1283 case 10:
1284 case 11:
1285 case 14:
1286 case 15:
1287 return CORE_NEHALEM;
1288 case 12:
1289 return CORE_ATOM;
1290 case 13:
1291 return CORE_DUNNINGTON;
1292 break;
1293 }
1294 }
1295 case 15:
1296 if (model <= 0x2) return CORE_NORTHWOOD;
1297 return CORE_PRESCOTT;
1298 }
1299 }
1300
1301 if (vendor == VENDOR_AMD){
1302 if (family <= 0x5) return CORE_80486;
1303 if (family <= 0xe) return CORE_ATHLON;
1304 if (family == 0xf){
1305 if ((exfamily == 0) || (exfamily == 2)) return CORE_OPTERON; else return CORE_BARCELONA;
1306 }
1307 }
1308
1309 if (vendor == VENDOR_CENTAUR) {
1310 switch (family) {
1311 case 0x6:
1312 return CORE_NANO;
1313 break;
1314 }
1315 return CORE_VIAC3;
1316 }
1317
1318 return CORE_UNKNOWN;
1319 }
1320
get_cpuconfig(void)1321 void get_cpuconfig(void){
1322
1323 cache_info_t info;
1324 int features;
1325
1326 printf("#define %s\n", cpuname[get_cpuname()]);
1327
1328
1329 if (get_coretype() != CORE_P5) {
1330
1331 get_cacheinfo(CACHE_INFO_L1_I, &info);
1332 if (info.size > 0) {
1333 printf("#define L1_CODE_SIZE %d\n", info.size * 1024);
1334 printf("#define L1_CODE_ASSOCIATIVE %d\n", info.associative);
1335 printf("#define L1_CODE_LINESIZE %d\n", info.linesize);
1336 }
1337
1338 get_cacheinfo(CACHE_INFO_L1_D, &info);
1339 if (info.size > 0) {
1340 printf("#define L1_DATA_SIZE %d\n", info.size * 1024);
1341 printf("#define L1_DATA_ASSOCIATIVE %d\n", info.associative);
1342 printf("#define L1_DATA_LINESIZE %d\n", info.linesize);
1343 }
1344
1345 get_cacheinfo(CACHE_INFO_L2, &info);
1346 if (info.size > 0) {
1347 printf("#define L2_SIZE %d\n", info.size * 1024);
1348 printf("#define L2_ASSOCIATIVE %d\n", info.associative);
1349 printf("#define L2_LINESIZE %d\n", info.linesize);
1350 }
1351
1352 get_cacheinfo(CACHE_INFO_L3, &info);
1353 if (info.size > 0) {
1354 printf("#define L3_SIZE %d\n", info.size * 1024);
1355 printf("#define L3_ASSOCIATIVE %d\n", info.associative);
1356 printf("#define L3_LINESIZE %d\n", info.linesize);
1357 }
1358
1359 get_cacheinfo(CACHE_INFO_L1_ITB, &info);
1360 if (info.size > 0) {
1361 printf("#define ITB_SIZE %d\n", info.size * 1024);
1362 printf("#define ITB_ASSOCIATIVE %d\n", info.associative);
1363 printf("#define ITB_ENTRIES %d\n", info.linesize);
1364 }
1365
1366 get_cacheinfo(CACHE_INFO_L1_DTB, &info);
1367 if (info.size > 0) {
1368 printf("#define DTB_SIZE %d\n", info.size * 1024);
1369 printf("#define DTB_ASSOCIATIVE %d\n", info.associative);
1370 printf("#define DTB_ENTRIES %d\n", info.linesize);
1371 }
1372
1373 features = get_cputype(GET_FEATURE);
1374
1375 if (features & HAVE_CMOV ) printf("#define HAVE_CMOV\n");
1376 if (features & HAVE_MMX ) printf("#define HAVE_MMX\n");
1377 if (features & HAVE_SSE ) printf("#define HAVE_SSE\n");
1378 if (features & HAVE_SSE2 ) printf("#define HAVE_SSE2\n");
1379 if (features & HAVE_SSE3 ) printf("#define HAVE_SSE3\n");
1380 if (features & HAVE_SSSE3) printf("#define HAVE_SSSE3\n");
1381 if (features & HAVE_SSE4_1) printf("#define HAVE_SSE4_1\n");
1382 if (features & HAVE_SSE4_2) printf("#define HAVE_SSE4_2\n");
1383 if (features & HAVE_SSE4A) printf("#define HAVE_SSE4A\n");
1384 if (features & HAVE_SSE5 ) printf("#define HAVE_SSSE5\n");
1385 if (features & HAVE_3DNOWEX) printf("#define HAVE_3DNOWEX\n");
1386 if (features & HAVE_3DNOW) printf("#define HAVE_3DNOW\n");
1387 if (features & HAVE_CFLUSH) printf("#define HAVE_CFLUSH\n");
1388 if (features & HAVE_HIT) printf("#define HAVE_HIT 1\n");
1389 if (features & HAVE_MISALIGNSSE) printf("#define HAVE_MISALIGNSSE\n");
1390 if (features & HAVE_128BITFPU) printf("#define HAVE_128BITFPU\n");
1391 if (features & HAVE_FASTMOVU) printf("#define HAVE_FASTMOVU\n");
1392
1393 printf("#define NUM_SHAREDCACHE %d\n", get_cputype(GET_NUMSHARE) + 1);
1394 printf("#define NUM_CORES %d\n", get_cputype(GET_NUMCORES) + 1);
1395
1396 features = get_coretype();
1397 if (features > 0) printf("#define CORE_%s\n", corename[features]);
1398 } else {
1399 printf("#define DTB_ENTRIES 16\n");
1400 printf("#define L1_CODE_SIZE 8192\n");
1401 printf("#define L1_DATA_SIZE 8192\n");
1402 printf("#define L2_SIZE 0\n");
1403 }
1404 }
1405
get_architecture(void)1406 void get_architecture(void){
1407 #ifndef __64BIT__
1408 printf("X86");
1409 #else
1410 printf("X86_64");
1411 #endif
1412 }
1413
get_subarchitecture(void)1414 void get_subarchitecture(void){
1415 printf("%s", get_cpunamechar());
1416 }
1417
get_subdirname(void)1418 void get_subdirname(void){
1419 #ifndef __64BIT__
1420 printf("x86");
1421 #else
1422 printf("x86_64");
1423 #endif
1424 }
1425
get_corename(void)1426 char *get_corename(void){
1427 return corename[get_coretype()];
1428 }
1429
get_libname(void)1430 void get_libname(void){
1431 printf("%s", corename_lower[get_coretype()]);
1432 }
1433
1434 /* This if for Makefile */
get_sse(void)1435 void get_sse(void){
1436
1437 int features;
1438
1439 features = get_cputype(GET_FEATURE);
1440
1441 if (features & HAVE_MMX ) printf("HAVE_MMX=1\n");
1442 if (features & HAVE_SSE ) printf("HAVE_SSE=1\n");
1443 if (features & HAVE_SSE2 ) printf("HAVE_SSE2=1\n");
1444 if (features & HAVE_SSE3 ) printf("HAVE_SSE3=1\n");
1445 if (features & HAVE_SSSE3) printf("HAVE_SSSE3=1\n");
1446 if (features & HAVE_SSE4_1) printf("HAVE_SSE4_1=1\n");
1447 if (features & HAVE_SSE4_2) printf("HAVE_SSE4_2=1\n");
1448 if (features & HAVE_SSE4A) printf("HAVE_SSE4A=1\n");
1449 if (features & HAVE_SSE5 ) printf("HAVE_SSSE5=1\n");
1450 if (features & HAVE_3DNOWEX) printf("HAVE_3DNOWEX=1\n");
1451 if (features & HAVE_3DNOW) printf("HAVE_3DNOW=1\n");
1452
1453 }
1454