No strncasecmp with MSVC
[platform/upstream/openblas.git] / cpuid_x86.c
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 #if defined(_MSC_VER) && !defined(__clang__)
44 #define C_INLINE __inline
45 #else
46 #define C_INLINE inline
47 #endif
48
49 /*
50 #ifdef NO_AVX
51 #define CPUTYPE_HASWELL CPUTYPE_NEHALEM
52 #define CORE_HASWELL CORE_NEHALEM
53 #define CPUTYPE_SANDYBRIDGE CPUTYPE_NEHALEM
54 #define CORE_SANDYBRIDGE CORE_NEHALEM
55 #define CPUTYPE_BULLDOZER CPUTYPE_BARCELONA
56 #define CORE_BULLDOZER CORE_BARCELONA
57 #define CPUTYPE_PILEDRIVER CPUTYPE_BARCELONA
58 #define CORE_PILEDRIVER CORE_BARCELONA
59 #endif
60 */
61
62 #if defined(_MSC_VER) && !defined(__clang__)
63
64 void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
65 {
66   int cpuInfo[4] = {-1};
67   __cpuid(cpuInfo, op);
68   *eax = cpuInfo[0];
69   *ebx = cpuInfo[1];
70   *ecx = cpuInfo[2];
71   *edx = cpuInfo[3];
72 }
73
74 void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, int *edx)
75 {
76   int cpuInfo[4] = {-1};
77   __cpuidex(cpuInfo, op, count);
78   *eax = cpuInfo[0];
79   *ebx = cpuInfo[1];
80   *ecx = cpuInfo[2];
81   *edx = cpuInfo[3];
82 }
83
84 #else
85
86 #ifndef CPUIDEMU
87
88 #if defined(__APPLE__) && defined(__i386__)
89 void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx);
90 void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, int *edx);
91 #else
92 static C_INLINE void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx){
93 #if defined(__i386__) && defined(__PIC__)
94   __asm__ __volatile__
95     ("mov %%ebx, %%edi;"
96      "cpuid;"
97      "xchgl %%ebx, %%edi;"
98      : "=a" (*eax), "=D" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op) : "cc");
99 #else
100   __asm__ __volatile__
101     ("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "a" (op) : "cc");
102 #endif
103 }
104
105 static C_INLINE void cpuid_count(int op, int count ,int *eax, int *ebx, int *ecx, int *edx){
106 #if defined(__i386__) && defined(__PIC__)
107   __asm__ __volatile__
108     ("mov %%ebx, %%edi;"
109      "cpuid;"
110      "xchgl %%ebx, %%edi;"
111      : "=a" (*eax), "=D" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (op), "2" (count) : "cc");
112 #else
113   __asm__ __volatile__
114     ("cpuid": "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (op), "2" (count) : "cc");
115 #endif
116 }
117 #endif
118
119 #else
120
121 typedef struct {
122   unsigned int id, a, b, c, d;
123 } idlist_t;
124
125 typedef struct {
126   char *vendor;
127   char *name;
128   int start, stop;
129 } vendor_t;
130
131 extern idlist_t idlist[];
132 extern vendor_t vendor[];
133
134 static int cv = VENDOR;
135
136 void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx){
137
138   static int current = 0;
139
140   int start = vendor[cv].start;
141   int stop  = vendor[cv].stop;
142   int count = stop - start;
143
144   if ((current < start) || (current > stop)) current = start;
145
146   while ((count > 0) && (idlist[current].id != op)) {
147
148     current ++;
149     if (current > stop) current = start;
150     count --;
151
152   }
153
154   *eax = idlist[current].a;
155   *ebx = idlist[current].b;
156   *ecx = idlist[current].c;
157   *edx = idlist[current].d;
158 }
159
160 void cpuid_count (unsigned int op, unsigned int count, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) {
161   return cpuid (op, eax, ebx, ecx, edx);
162 }
163
164 #endif
165
166 #endif // _MSC_VER
167
168 static C_INLINE int have_cpuid(void){
169   int eax, ebx, ecx, edx;
170
171   cpuid(0, &eax, &ebx, &ecx, &edx);
172   return eax;
173 }
174
175 static C_INLINE int have_excpuid(void){
176   int eax, ebx, ecx, edx;
177
178   cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
179   return eax & 0xffff;
180 }
181
182 #ifndef NO_AVX
183 static C_INLINE void xgetbv(int op, int * eax, int * edx){
184   //Use binary code for xgetbv
185 #if defined(_MSC_VER) && !defined(__clang__)
186   *eax = __xgetbv(op);
187 #else
188   __asm__ __volatile__
189     (".byte 0x0f, 0x01, 0xd0": "=a" (*eax), "=d" (*edx) : "c" (op) : "cc");
190 #endif
191 }
192 #endif
193
194 int support_avx(){
195 #ifndef NO_AVX
196   int eax, ebx, ecx, edx;
197   int ret=0;
198
199   cpuid(1, &eax, &ebx, &ecx, &edx);
200   if ((ecx & (1 << 28)) != 0 && (ecx & (1 << 27)) != 0 && (ecx & (1 << 26)) != 0){
201     xgetbv(0, &eax, &edx);
202     if((eax & 6) == 6){
203       ret=1;  //OS support AVX
204     }
205   }
206   return ret;
207 #else
208   return 0;
209 #endif
210 }
211
212
213 int get_vendor(void){
214   int eax, ebx, ecx, edx;
215   char vendor[13];
216
217   cpuid(0, &eax, &ebx, &ecx, &edx);
218
219   *(int *)(&vendor[0]) = ebx;
220   *(int *)(&vendor[4]) = edx;
221   *(int *)(&vendor[8]) = ecx;
222   vendor[12] = (char)0;
223
224   if (!strcmp(vendor, "GenuineIntel")) return VENDOR_INTEL;
225   if (!strcmp(vendor, " UMC UMC UMC")) return VENDOR_UMC;
226   if (!strcmp(vendor, "AuthenticAMD")) return VENDOR_AMD;
227   if (!strcmp(vendor, "CyrixInstead")) return VENDOR_CYRIX;
228   if (!strcmp(vendor, "NexGenDriven")) return VENDOR_NEXGEN;
229   if (!strcmp(vendor, "CentaurHauls")) return VENDOR_CENTAUR;
230   if (!strcmp(vendor, "RiseRiseRise")) return VENDOR_RISE;
231   if (!strcmp(vendor, " SiS SiS SiS")) return VENDOR_SIS;
232   if (!strcmp(vendor, "GenuineTMx86")) return VENDOR_TRANSMETA;
233   if (!strcmp(vendor, "Geode by NSC")) return VENDOR_NSC;
234
235   if ((eax == 0) || ((eax & 0x500) != 0)) return VENDOR_INTEL;
236
237   return VENDOR_UNKNOWN;
238 }
239
240 int get_cputype(int gettype){
241   int eax, ebx, ecx, edx;
242   int extend_family, family;
243   int extend_model, model;
244   int type, stepping;
245   int feature = 0;
246
247   cpuid(1, &eax, &ebx, &ecx, &edx);
248
249   switch (gettype) {
250   case GET_EXFAMILY :
251     return BITMASK(eax, 20, 0xff);
252   case GET_EXMODEL :
253     return BITMASK(eax, 16, 0x0f);
254   case GET_TYPE :
255     return BITMASK(eax, 12, 0x03);
256   case GET_FAMILY :
257     return BITMASK(eax,  8, 0x0f);
258   case GET_MODEL :
259     return BITMASK(eax,  4, 0x0f);
260   case GET_APICID :
261     return BITMASK(ebx, 24, 0x0f);
262   case GET_LCOUNT :
263     return BITMASK(ebx, 16, 0x0f);
264   case GET_CHUNKS :
265     return BITMASK(ebx,  8, 0x0f);
266   case GET_STEPPING :
267     return BITMASK(eax,  0, 0x0f);
268   case GET_BLANDID :
269     return BITMASK(ebx,  0, 0xff);
270   case GET_NUMSHARE :
271     if (have_cpuid() < 4) return 0;
272     cpuid(4, &eax, &ebx, &ecx, &edx);
273     return BITMASK(eax, 14, 0xfff);
274   case GET_NUMCORES :
275     if (have_cpuid() < 4) return 0;
276     cpuid(4, &eax, &ebx, &ecx, &edx);
277     return BITMASK(eax, 26, 0x3f);
278
279   case GET_FEATURE :
280     if ((edx & (1 <<  3)) != 0) feature |= HAVE_PSE;
281     if ((edx & (1 << 15)) != 0) feature |= HAVE_CMOV;
282     if ((edx & (1 << 19)) != 0) feature |= HAVE_CFLUSH;
283     if ((edx & (1 << 23)) != 0) feature |= HAVE_MMX;
284     if ((edx & (1 << 25)) != 0) feature |= HAVE_SSE;
285     if ((edx & (1 << 26)) != 0) feature |= HAVE_SSE2;
286     if ((edx & (1 << 27)) != 0) {
287       if (BITMASK(ebx, 16, 0x0f) > 0) feature |= HAVE_HIT;
288     }
289     if ((ecx & (1 <<  0)) != 0) feature |= HAVE_SSE3;
290     if ((ecx & (1 <<  9)) != 0) feature |= HAVE_SSSE3;
291     if ((ecx & (1 << 19)) != 0) feature |= HAVE_SSE4_1;
292     if ((ecx & (1 << 20)) != 0) feature |= HAVE_SSE4_2;
293 #ifndef NO_AVX
294     if (support_avx()) feature |= HAVE_AVX;
295     if ((ecx & (1 << 12)) != 0) feature |= HAVE_FMA3;
296 #endif
297
298     if (have_excpuid() >= 0x01) {
299       cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
300       if ((ecx & (1 <<  6)) != 0) feature |= HAVE_SSE4A;
301       if ((ecx & (1 <<  7)) != 0) feature |= HAVE_MISALIGNSSE;
302 #ifndef NO_AVX
303       if ((ecx & (1 <<  16)) != 0) feature |= HAVE_FMA4;
304 #endif
305       if ((edx & (1 << 30)) != 0) feature |= HAVE_3DNOWEX;
306       if ((edx & (1 << 31)) != 0) feature |= HAVE_3DNOW;
307     }
308
309     if (have_excpuid() >= 0x1a) {
310       cpuid(0x8000001a, &eax, &ebx, &ecx, &edx);
311       if ((eax & (1 <<  0)) != 0) feature |= HAVE_128BITFPU;
312       if ((eax & (1 <<  1)) != 0) feature |= HAVE_FASTMOVU;
313     }
314
315   }
316   return feature;
317 }
318
319 int get_cacheinfo(int type, cache_info_t *cacheinfo){
320   int eax, ebx, ecx, edx, cpuid_level;
321   int info[15];
322   int i;
323   cache_info_t LC1, LD1, L2, L3,
324     ITB, DTB, LITB, LDTB,
325     L2ITB, L2DTB, L2LITB, L2LDTB;
326
327   LC1.size    = 0; LC1.associative = 0; LC1.linesize = 0; LC1.shared = 0;
328   LD1.size    = 0; LD1.associative    = 0; LD1.linesize    = 0; LD1.shared    = 0;
329   L2.size     = 0; L2.associative     = 0; L2.linesize     = 0; L2.shared     = 0;
330   L3.size     = 0; L3.associative     = 0; L3.linesize     = 0; L3.shared     = 0;
331   ITB.size    = 0; ITB.associative    = 0; ITB.linesize    = 0; ITB.shared    = 0;
332   DTB.size    = 0; DTB.associative    = 0; DTB.linesize    = 0; DTB.shared    = 0;
333   LITB.size   = 0; LITB.associative   = 0; LITB.linesize   = 0; LITB.shared   = 0;
334   LDTB.size   = 0; LDTB.associative   = 0; LDTB.linesize   = 0; LDTB.shared   = 0;
335   L2ITB.size  = 0; L2ITB.associative  = 0; L2ITB.linesize  = 0; L2ITB.shared  = 0;
336   L2DTB.size  = 0; L2DTB.associative  = 0; L2DTB.linesize  = 0; L2DTB.shared  = 0;
337   L2LITB.size = 0; L2LITB.associative = 0; L2LITB.linesize = 0; L2LITB.shared = 0;
338   L2LDTB.size = 0; L2LDTB.associative = 0; L2LDTB.linesize = 0; L2LDTB.shared = 0;
339
340   cpuid(0, &cpuid_level, &ebx, &ecx, &edx);
341
342   if (cpuid_level > 1) {
343     int numcalls =0 ;
344     cpuid(2, &eax, &ebx, &ecx, &edx);
345     numcalls = BITMASK(eax, 0, 0xff); //FIXME some systems may require repeated calls to read all entries
346     info[ 0] = BITMASK(eax,  8, 0xff);
347     info[ 1] = BITMASK(eax, 16, 0xff);
348     info[ 2] = BITMASK(eax, 24, 0xff);
349
350     info[ 3] = BITMASK(ebx,  0, 0xff);
351     info[ 4] = BITMASK(ebx,  8, 0xff);
352     info[ 5] = BITMASK(ebx, 16, 0xff);
353     info[ 6] = BITMASK(ebx, 24, 0xff);
354
355     info[ 7] = BITMASK(ecx,  0, 0xff);
356     info[ 8] = BITMASK(ecx,  8, 0xff);
357     info[ 9] = BITMASK(ecx, 16, 0xff);
358     info[10] = BITMASK(ecx, 24, 0xff);
359
360     info[11] = BITMASK(edx,  0, 0xff);
361     info[12] = BITMASK(edx,  8, 0xff);
362     info[13] = BITMASK(edx, 16, 0xff);
363     info[14] = BITMASK(edx, 24, 0xff);
364
365     for (i = 0; i < 15; i++){
366       switch (info[i]){
367
368         /* This table is from http://www.sandpile.org/ia32/cpuid.htm */
369
370       case 0x01 :
371         ITB.size        =     4;
372         ITB.associative =     4;
373         ITB.linesize     =   32;
374         break;
375       case 0x02 :
376         LITB.size        = 4096;
377         LITB.associative =    0;
378         LITB.linesize    =    2;
379         break;
380       case 0x03 :
381         DTB.size        =     4;
382         DTB.associative =     4;
383         DTB.linesize     =   64;
384         break;
385       case 0x04 :
386         LDTB.size        = 4096;
387         LDTB.associative =    4;
388         LDTB.linesize    =    8;
389         break;
390       case 0x05 :
391         LDTB.size        = 4096;
392         LDTB.associative =    4;
393         LDTB.linesize    =   32;
394         break;
395       case 0x06 :
396         LC1.size        = 8;
397         LC1.associative = 4;
398         LC1.linesize    = 32;
399         break;
400       case 0x08 :
401         LC1.size        = 16;
402         LC1.associative = 4;
403         LC1.linesize    = 32;
404         break;
405       case 0x09 :
406         LC1.size        = 32;
407         LC1.associative = 4;
408         LC1.linesize    = 64;
409         break;
410       case 0x0a :
411         LD1.size        = 8;
412         LD1.associative = 2;
413         LD1.linesize    = 32;
414         break;
415       case 0x0c :
416         LD1.size        = 16;
417         LD1.associative = 4;
418         LD1.linesize    = 32;
419         break;
420       case 0x0d :
421         LD1.size        = 16;
422         LD1.associative = 4;
423         LD1.linesize    = 64;
424         break;
425       case 0x0e :
426         LD1.size        = 24;
427         LD1.associative = 6;
428         LD1.linesize    = 64;
429         break;
430       case 0x10 :
431         LD1.size        = 16;
432         LD1.associative = 4;
433         LD1.linesize    = 32;
434         break;
435       case 0x15 :
436         LC1.size        = 16;
437         LC1.associative = 4;
438         LC1.linesize    = 32;
439         break;
440       case 0x1a :
441         L2.size         = 96;
442         L2.associative  = 6;
443         L2.linesize     = 64;
444         break;
445       case 0x21 :
446         L2.size         = 256;
447         L2.associative  = 8;
448         L2.linesize     = 64;
449         break;
450       case 0x22 :
451         L3.size         = 512;
452         L3.associative  = 4;
453         L3.linesize     = 64;
454         break;
455       case 0x23 :
456         L3.size         = 1024;
457         L3.associative  = 8;
458         L3.linesize     = 64;
459         break;
460       case 0x25 :
461         L3.size         = 2048;
462         L3.associative  = 8;
463         L3.linesize     = 64;
464         break;
465       case 0x29 :
466         L3.size         = 4096;
467         L3.associative  = 8;
468         L3.linesize     = 64;
469         break;
470       case 0x2c :
471         LD1.size        = 32;
472         LD1.associative = 8;
473         LD1.linesize    = 64;
474         break;
475       case 0x30 :
476         LC1.size        = 32;
477         LC1.associative = 8;
478         LC1.linesize    = 64;
479         break;
480       case 0x39 :
481         L2.size         = 128;
482         L2.associative  = 4;
483         L2.linesize     = 64;
484         break;
485       case 0x3a :
486         L2.size         = 192;
487         L2.associative  = 6;
488         L2.linesize     = 64;
489         break;
490       case 0x3b :
491         L2.size         = 128;
492         L2.associative  = 2;
493         L2.linesize     = 64;
494         break;
495       case 0x3c :
496         L2.size         = 256;
497         L2.associative  = 4;
498         L2.linesize     = 64;
499         break;
500       case 0x3d :
501         L2.size         = 384;
502         L2.associative  = 6;
503         L2.linesize     = 64;
504         break;
505       case 0x3e :
506         L2.size         = 512;
507         L2.associative  = 4;
508         L2.linesize     = 64;
509         break;
510       case 0x41 :
511         L2.size         = 128;
512         L2.associative  = 4;
513         L2.linesize     = 32;
514         break;
515       case 0x42 :
516         L2.size         = 256;
517         L2.associative  = 4;
518         L2.linesize     = 32;
519         break;
520       case 0x43 :
521         L2.size         = 512;
522         L2.associative  = 4;
523         L2.linesize     = 32;
524         break;
525       case 0x44 :
526         L2.size         = 1024;
527         L2.associative  = 4;
528         L2.linesize     = 32;
529         break;
530       case 0x45 :
531         L2.size         = 2048;
532         L2.associative  = 4;
533         L2.linesize     = 32;
534         break;
535       case 0x46 :
536         L3.size         = 4096;
537         L3.associative  = 4;
538         L3.linesize     = 64;
539         break;
540       case 0x47 :
541         L3.size         = 8192;
542         L3.associative  = 8;
543         L3.linesize     = 64;
544         break;
545       case 0x48 :
546         L2.size         = 3184;
547         L2.associative  = 12;
548         L2.linesize     = 64;
549         break;
550       case 0x49 :
551         if ((get_cputype(GET_FAMILY) == 0x0f) && (get_cputype(GET_MODEL) == 0x06)) {
552           L3.size         = 4096;
553           L3.associative  = 16;
554           L3.linesize     = 64;
555         } else {
556           L2.size         = 4096;
557           L2.associative  = 16;
558           L2.linesize     = 64;
559         }
560         break;
561       case 0x4a :
562         L3.size         = 6144;
563         L3.associative  = 12;
564         L3.linesize     = 64;
565         break;
566       case 0x4b :
567         L3.size         = 8192;
568         L3.associative  = 16;
569         L3.linesize     = 64;
570         break;
571       case 0x4c :
572         L3.size         = 12280;
573         L3.associative  = 12;
574         L3.linesize     = 64;
575         break;
576       case 0x4d :
577         L3.size         = 16384;
578         L3.associative  = 16;
579         L3.linesize     = 64;
580         break;
581       case 0x4e :
582         L2.size         = 6144;
583         L2.associative  = 24;
584         L2.linesize     = 64;
585         break;
586       case 0x4f :
587         ITB.size         = 4;
588         ITB.associative  = 0;
589         ITB.linesize     = 32;
590         break;
591       case 0x50 :
592         ITB.size         = 4;
593         ITB.associative  = 0;
594         ITB.linesize     = 64;
595         LITB.size        = 4096;
596         LITB.associative = 0;
597         LITB.linesize    = 64;
598         LITB.shared      = 1;
599         break;
600       case 0x51 :
601         ITB.size        = 4;
602         ITB.associative = 0;
603         ITB.linesize     = 128;
604         LITB.size        = 4096;
605         LITB.associative = 0;
606         LITB.linesize    = 128;
607         LITB.shared      = 1;
608         break;
609       case 0x52 :
610         ITB.size         = 4;
611         ITB.associative  = 0;
612         ITB.linesize     = 256;
613         LITB.size        = 4096;
614         LITB.associative = 0;
615         LITB.linesize    = 256;
616         LITB.shared      = 1;
617         break;
618       case 0x55 :
619         LITB.size        = 4096;
620         LITB.associative = 0;
621         LITB.linesize    = 7;
622         LITB.shared      = 1;
623         break;
624       case 0x56 :
625         LDTB.size        = 4096;
626         LDTB.associative = 4;
627         LDTB.linesize    = 16;
628         break;
629       case 0x57 :
630         LDTB.size        = 4096;
631         LDTB.associative = 4;
632         LDTB.linesize    = 16;
633         break;
634       case 0x5b :
635         DTB.size         = 4;
636         DTB.associative  = 0;
637         DTB.linesize     = 64;
638         LDTB.size        = 4096;
639         LDTB.associative = 0;
640         LDTB.linesize    = 64;
641         LDTB.shared      = 1;
642         break;
643       case 0x5c :
644         DTB.size         = 4;
645         DTB.associative  = 0;
646         DTB.linesize     = 128;
647         LDTB.size        = 4096;
648         LDTB.associative = 0;
649         LDTB.linesize    = 128;
650         LDTB.shared      = 1;
651         break;
652       case 0x5d :
653         DTB.size         = 4;
654         DTB.associative  = 0;
655         DTB.linesize     = 256;
656         LDTB.size        = 4096;
657         LDTB.associative = 0;
658         LDTB.linesize    = 256;
659         LDTB.shared      = 1;
660         break;
661       case 0x60 :
662         LD1.size        = 16;
663         LD1.associative = 8;
664         LD1.linesize    = 64;
665         break;
666       case 0x63 :
667         DTB.size        = 2048;
668         DTB.associative = 4;
669         DTB.linesize    = 32;
670         LDTB.size       = 4096;
671         LDTB.associative= 4;
672         LDTB.linesize   = 32;
673         break;
674       case 0x66 :
675         LD1.size        = 8;
676         LD1.associative = 4;
677         LD1.linesize    = 64;
678         break;
679       case 0x67 :
680         LD1.size        = 16;
681         LD1.associative = 4;
682         LD1.linesize    = 64;
683         break;
684       case 0x68 :
685         LD1.size        = 32;
686         LD1.associative = 4;
687         LD1.linesize    = 64;
688         break;
689       case 0x70 :
690         LC1.size        = 12;
691         LC1.associative = 8;
692         break;
693       case 0x71 :
694         LC1.size        = 16;
695         LC1.associative = 8;
696         break;
697       case 0x72 :
698         LC1.size        = 32;
699         LC1.associative = 8;
700         break;
701       case 0x73 :
702         LC1.size        = 64;
703         LC1.associative = 8;
704         break;
705       case 0x76 :
706         ITB.size        = 2048;
707         ITB.associative = 0;
708         ITB.linesize    = 8;
709         LITB.size       = 4096;
710         LITB.associative= 0;
711         LITB.linesize   = 8;
712         break;
713       case 0x77 :
714         LC1.size        = 16;
715         LC1.associative = 4;
716         LC1.linesize    = 64;
717         break;
718       case 0x78 :
719         L2.size        = 1024;
720         L2.associative = 4;
721         L2.linesize    = 64;
722         break;
723       case 0x79 :
724         L2.size         = 128;
725         L2.associative  = 8;
726         L2.linesize     = 64;
727         break;
728       case 0x7a :
729         L2.size         = 256;
730         L2.associative  = 8;
731         L2.linesize     = 64;
732         break;
733       case 0x7b :
734         L2.size         = 512;
735         L2.associative  = 8;
736         L2.linesize     = 64;
737         break;
738       case 0x7c :
739         L2.size         = 1024;
740         L2.associative  = 8;
741         L2.linesize     = 64;
742         break;
743       case 0x7d :
744         L2.size         = 2048;
745         L2.associative  = 8;
746         L2.linesize     = 64;
747         break;
748       case 0x7e :
749         L2.size         = 256;
750         L2.associative  = 8;
751         L2.linesize     = 128;
752         break;
753       case 0x7f :
754         L2.size         = 512;
755         L2.associative  = 2;
756         L2.linesize     = 64;
757         break;
758       case 0x81 :
759         L2.size         = 128;
760         L2.associative  = 8;
761         L2.linesize     = 32;
762         break;
763       case 0x82 :
764         L2.size         = 256;
765         L2.associative  = 8;
766         L2.linesize     = 32;
767         break;
768       case 0x83 :
769         L2.size         = 512;
770         L2.associative  = 8;
771         L2.linesize     = 32;
772         break;
773       case 0x84 :
774         L2.size         = 1024;
775         L2.associative  = 8;
776         L2.linesize     = 32;
777         break;
778       case 0x85 :
779         L2.size         = 2048;
780         L2.associative  = 8;
781         L2.linesize     = 32;
782         break;
783       case 0x86 :
784         L2.size         = 512;
785         L2.associative  = 4;
786         L2.linesize     = 64;
787         break;
788       case 0x87 :
789         L2.size         = 1024;
790         L2.associative  = 8;
791         L2.linesize     = 64;
792         break;
793       case 0x88 :
794         L3.size         = 2048;
795         L3.associative  = 4;
796         L3.linesize     = 64;
797         break;
798       case 0x89 :
799         L3.size         = 4096;
800         L3.associative  = 4;
801         L3.linesize     = 64;
802         break;
803       case 0x8a :
804         L3.size         = 8192;
805         L3.associative  = 4;
806         L3.linesize     = 64;
807         break;
808       case 0x8d :
809         L3.size         = 3096;
810         L3.associative  = 12;
811         L3.linesize     = 128;
812         break;
813       case 0x90 :
814         ITB.size        = 4;
815         ITB.associative = 0;
816         ITB.linesize    = 64;
817         break;
818       case 0x96 :
819         DTB.size        = 4;
820         DTB.associative = 0;
821         DTB.linesize    = 32;
822         break;
823       case 0x9b :
824         L2DTB.size        = 4;
825         L2DTB.associative = 0;
826         L2DTB.linesize    = 96;
827         break;
828       case 0xb0 :
829         ITB.size        = 4;
830         ITB.associative = 4;
831         ITB.linesize    = 128;
832         break;
833       case 0xb1 :
834         LITB.size        = 4096;
835         LITB.associative = 4;
836         LITB.linesize    = 4;
837         break;
838       case 0xb2 :
839         ITB.size        = 4;
840         ITB.associative = 4;
841         ITB.linesize    = 64;
842         break;
843       case 0xb3 :
844         DTB.size        = 4;
845         DTB.associative = 4;
846         DTB.linesize    = 128;
847         break;
848       case 0xb4 :
849         DTB.size        = 4;
850         DTB.associative = 4;
851         DTB.linesize    = 256;
852         break;
853       case 0xba :
854         DTB.size        = 4;
855         DTB.associative = 4;
856         DTB.linesize    = 64;
857         break;
858       case 0xd0 :
859         L3.size         = 512;
860         L3.associative  = 4;
861         L3.linesize     = 64;
862         break;
863       case 0xd1 :
864         L3.size         = 1024;
865         L3.associative  = 4;
866         L3.linesize     = 64;
867         break;
868       case 0xd2 :
869         L3.size         = 2048;
870         L3.associative  = 4;
871         L3.linesize     = 64;
872         break;
873       case 0xd6 :
874         L3.size         = 1024;
875         L3.associative  = 8;
876         L3.linesize     = 64;
877         break;
878       case 0xd7 :
879         L3.size         = 2048;
880         L3.associative  = 8;
881         L3.linesize     = 64;
882         break;
883       case 0xd8 :
884         L3.size         = 4096;
885         L3.associative  = 8;
886         L3.linesize     = 64;
887         break;
888       case 0xdc :
889         L3.size         = 2048;
890         L3.associative  = 12;
891         L3.linesize     = 64;
892         break;
893       case 0xdd :
894         L3.size         = 4096;
895         L3.associative  = 12;
896         L3.linesize     = 64;
897         break;
898       case 0xde :
899         L3.size         = 8192;
900         L3.associative  = 12;
901         L3.linesize     = 64;
902         break;
903       case 0xe2 :
904         L3.size         = 2048;
905         L3.associative  = 16;
906         L3.linesize     = 64;
907         break;
908       case 0xe3 :
909         L3.size         = 4096;
910         L3.associative  = 16;
911         L3.linesize     = 64;
912         break;
913       case 0xe4 :
914         L3.size         = 8192;
915         L3.associative  = 16;
916         L3.linesize     = 64;
917         break;
918       }
919     }
920   }
921
922   if (get_vendor() == VENDOR_INTEL) {
923       if(LD1.size<=0 || LC1.size<=0){
924         //If we didn't detect L1 correctly before,
925         int count;
926         for (count=0;count <4;count++) {
927         cpuid_count(4, count, &eax, &ebx, &ecx, &edx);
928         switch (eax &0x1f) {
929         case 0:
930           continue;
931           case 1:
932           case 3:
933           {
934             switch ((eax >>5) &0x07)
935             {
936             case 1:
937             {
938 //            fprintf(stderr,"L1 data cache...\n");
939             int sets = ecx+1;
940             int lines = (ebx & 0x0fff) +1;
941             ebx>>=12;
942             int part = (ebx&0x03ff)+1;
943             ebx >>=10;
944             int assoc = (ebx&0x03ff)+1;
945             LD1.size = (assoc*part*lines*sets)/1024;
946             LD1.associative = assoc;
947             LD1.linesize= lines;
948             break;
949             }
950             default: 
951               break;
952            }
953           break;
954           }
955          case 2:
956           {
957             switch ((eax >>5) &0x07)
958             {
959             case 1:
960             {
961 //            fprintf(stderr,"L1 instruction cache...\n");
962             int sets = ecx+1;
963             int lines = (ebx & 0x0fff) +1;
964             ebx>>=12;
965             int part = (ebx&0x03ff)+1;
966             ebx >>=10;
967             int assoc = (ebx&0x03ff)+1;
968             LC1.size = (assoc*part*lines*sets)/1024;
969             LC1.associative = assoc;
970             LC1.linesize= lines;
971             break;
972             }
973             default: 
974               break;
975            }
976           break;
977           
978           }
979           default:
980           break;
981         }
982       }
983     }
984     cpuid(0x80000000, &cpuid_level, &ebx, &ecx, &edx);
985     if (cpuid_level >= 0x80000006) {
986       if(L2.size<=0){
987         //If we didn't detect L2 correctly before,
988         cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
989
990         L2.size         = BITMASK(ecx, 16, 0xffff);
991         L2.associative  = BITMASK(ecx, 12, 0x0f);
992
993         switch (L2.associative){
994         case 0x06:
995           L2.associative = 8;
996           break;
997         case 0x08:
998           L2.associative = 16;
999           break;
1000         }
1001
1002         L2.linesize     = BITMASK(ecx,  0, 0xff);
1003       }
1004     }
1005   }
1006
1007   if ((get_vendor() == VENDOR_AMD) || (get_vendor() == VENDOR_CENTAUR)) {
1008     cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
1009
1010     LDTB.size        = 4096;
1011     LDTB.associative = BITMASK(eax, 24, 0xff);
1012     if (LDTB.associative == 0xff) LDTB.associative = 0;
1013     LDTB.linesize    = BITMASK(eax, 16, 0xff);
1014
1015     LITB.size        = 4096;
1016     LITB.associative = BITMASK(eax,  8, 0xff);
1017     if (LITB.associative == 0xff) LITB.associative = 0;
1018     LITB.linesize    = BITMASK(eax,  0, 0xff);
1019
1020     DTB.size        = 4;
1021     DTB.associative = BITMASK(ebx, 24, 0xff);
1022     if (DTB.associative == 0xff) DTB.associative = 0;
1023     DTB.linesize    = BITMASK(ebx, 16, 0xff);
1024
1025     ITB.size        = 4;
1026     ITB.associative = BITMASK(ebx,  8, 0xff);
1027     if (ITB.associative == 0xff) ITB.associative = 0;
1028     ITB.linesize    = BITMASK(ebx,  0, 0xff);
1029
1030     LD1.size        = BITMASK(ecx, 24, 0xff);
1031     LD1.associative = BITMASK(ecx, 16, 0xff);
1032     if (LD1.associative == 0xff) LD1.associative = 0;
1033     LD1.linesize    = BITMASK(ecx,  0, 0xff);
1034
1035     LC1.size        = BITMASK(ecx, 24, 0xff);
1036     LC1.associative = BITMASK(ecx, 16, 0xff);
1037     if (LC1.associative == 0xff) LC1.associative = 0;
1038     LC1.linesize    = BITMASK(ecx,  0, 0xff);
1039
1040     cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
1041
1042     L2LDTB.size        = 4096;
1043     L2LDTB.associative = BITMASK(eax, 24, 0xff);
1044     if (L2LDTB.associative == 0xff) L2LDTB.associative = 0;
1045     L2LDTB.linesize    = BITMASK(eax, 16, 0xff);
1046
1047     L2LITB.size        = 4096;
1048     L2LITB.associative = BITMASK(eax,  8, 0xff);
1049     if (L2LITB.associative == 0xff) L2LITB.associative = 0;
1050     L2LITB.linesize    = BITMASK(eax,  0, 0xff);
1051
1052     L2DTB.size        = 4;
1053     L2DTB.associative = BITMASK(ebx, 24, 0xff);
1054     if (L2DTB.associative == 0xff) L2DTB.associative = 0;
1055     L2DTB.linesize    = BITMASK(ebx, 16, 0xff);
1056
1057     L2ITB.size        = 4;
1058     L2ITB.associative = BITMASK(ebx,  8, 0xff);
1059     if (L2ITB.associative == 0xff) L2ITB.associative = 0;
1060     L2ITB.linesize    = BITMASK(ebx,  0, 0xff);
1061
1062     if(L2.size <= 0){
1063       //If we didn't detect L2 correctly before,
1064       L2.size        = BITMASK(ecx, 16, 0xffff);
1065       L2.associative = BITMASK(ecx, 12, 0xf);
1066       switch (L2.associative){
1067       case 0x06:
1068         L2.associative = 8;
1069         break;
1070       case 0x08:
1071         L2.associative = 16;
1072         break;
1073       }
1074
1075       if (L2.associative == 0xff) L2.associative = 0;
1076       L2.linesize    = BITMASK(ecx,  0, 0xff);
1077     }
1078
1079     L3.size        = BITMASK(edx, 18, 0x3fff) * 512;
1080     L3.associative = BITMASK(edx, 12, 0xf);
1081     if (L3.associative == 0xff) L2.associative = 0;
1082     L3.linesize    = BITMASK(edx,  0, 0xff);
1083
1084   }
1085
1086     switch (type) {
1087
1088     case CACHE_INFO_L1_I :
1089       *cacheinfo = LC1;
1090       break;
1091     case CACHE_INFO_L1_D :
1092       *cacheinfo = LD1;
1093       break;
1094     case CACHE_INFO_L2 :
1095       *cacheinfo = L2;
1096       break;
1097     case CACHE_INFO_L3 :
1098       *cacheinfo = L3;
1099       break;
1100     case CACHE_INFO_L1_DTB :
1101       *cacheinfo = DTB;
1102       break;
1103     case CACHE_INFO_L1_ITB :
1104       *cacheinfo = ITB;
1105       break;
1106     case CACHE_INFO_L1_LDTB :
1107       *cacheinfo = LDTB;
1108       break;
1109     case CACHE_INFO_L1_LITB :
1110       *cacheinfo = LITB;
1111       break;
1112     case CACHE_INFO_L2_DTB :
1113       *cacheinfo = L2DTB;
1114       break;
1115     case CACHE_INFO_L2_ITB :
1116       *cacheinfo = L2ITB;
1117       break;
1118     case CACHE_INFO_L2_LDTB :
1119       *cacheinfo = L2LDTB;
1120       break;
1121     case CACHE_INFO_L2_LITB :
1122       *cacheinfo = L2LITB;
1123       break;
1124     }
1125   return 0;
1126 }
1127
1128 int get_cpuname(void){
1129
1130   int family, exfamily, model, vendor, exmodel;
1131
1132   if (!have_cpuid()) return CPUTYPE_80386;
1133
1134   family   = get_cputype(GET_FAMILY);
1135   exfamily = get_cputype(GET_EXFAMILY);
1136   model    = get_cputype(GET_MODEL);
1137   exmodel  = get_cputype(GET_EXMODEL);
1138
1139   vendor = get_vendor();
1140
1141   if (vendor == VENDOR_INTEL){
1142     switch (family) {
1143     case 0x4:
1144       return CPUTYPE_80486;
1145     case 0x5:
1146       return CPUTYPE_PENTIUM;
1147     case 0x6:
1148       switch (exmodel) {
1149       case 0:
1150         switch (model) {
1151         case  1:
1152         case  3:
1153         case  5:
1154         case  6:
1155           return CPUTYPE_PENTIUM2;
1156         case  7:
1157         case  8:
1158         case 10:
1159         case 11:
1160           return CPUTYPE_PENTIUM3;
1161         case  9:
1162         case 13:
1163         case 14:
1164           return CPUTYPE_PENTIUMM;
1165         case 15:
1166           return CPUTYPE_CORE2;
1167         }
1168         break;
1169       case 1:
1170         switch (model) {
1171         case  6:
1172           return CPUTYPE_CORE2;
1173         case  7:
1174           return CPUTYPE_PENRYN;
1175         case 10:
1176         case 11:
1177         case 14:
1178         case 15:
1179           return CPUTYPE_NEHALEM;
1180         case 12:
1181           return CPUTYPE_ATOM;
1182         case 13:
1183           return CPUTYPE_DUNNINGTON;
1184         }
1185         break;
1186       case  2:
1187         switch (model) {
1188         case 5:
1189           //Intel Core (Clarkdale) / Core (Arrandale)
1190           // Pentium (Clarkdale) / Pentium Mobile (Arrandale)
1191           // Xeon (Clarkdale), 32nm
1192           return CPUTYPE_NEHALEM;
1193         case 10:
1194           //Intel Core i5-2000 /i7-2000 (Sandy Bridge)
1195           if(support_avx())
1196             return CPUTYPE_SANDYBRIDGE;
1197           else
1198             return CPUTYPE_NEHALEM; //OS doesn't support AVX
1199         case 12:
1200           //Xeon Processor 5600 (Westmere-EP)
1201           return CPUTYPE_NEHALEM;
1202         case 13:
1203           //Intel Core i7-3000 / Xeon E5 (Sandy Bridge)
1204           if(support_avx())
1205             return CPUTYPE_SANDYBRIDGE;
1206           else
1207             return CPUTYPE_NEHALEM;
1208         case 14:
1209           // Xeon E7540
1210         case 15:
1211           //Xeon Processor E7 (Westmere-EX)
1212           return CPUTYPE_NEHALEM;
1213         }
1214         break;
1215       case 3:
1216         switch (model) {
1217         case  7:
1218             // Bay Trail        
1219             return CPUTYPE_ATOM;        
1220         case 10:
1221         case 14:
1222           // Ivy Bridge
1223           if(support_avx())
1224             return CPUTYPE_SANDYBRIDGE;
1225           else
1226             return CPUTYPE_NEHALEM;
1227         case 12:
1228         case 15:
1229           if(support_avx())
1230 #ifndef NO_AVX2
1231             return CPUTYPE_HASWELL;
1232 #else
1233             return CPUTYPE_SANDYBRIDGE;
1234 #endif
1235           else
1236             return CPUTYPE_NEHALEM;
1237         case 13:
1238           //Broadwell
1239           if(support_avx())
1240 #ifndef NO_AVX2
1241             return CPUTYPE_HASWELL;
1242 #else
1243             return CPUTYPE_SANDYBRIDGE;
1244 #endif
1245           else
1246             return CPUTYPE_NEHALEM;
1247         }
1248         break;
1249       case 4:
1250         switch (model) {
1251         case 5:
1252         case 6:
1253           if(support_avx())
1254 #ifndef NO_AVX2
1255             return CPUTYPE_HASWELL;
1256 #else
1257             return CPUTYPE_SANDYBRIDGE;
1258 #endif
1259           else
1260             return CPUTYPE_NEHALEM;
1261         case 7:
1262         case 15:
1263           //Broadwell
1264           if(support_avx())
1265 #ifndef NO_AVX2
1266             return CPUTYPE_HASWELL;
1267 #else
1268             return CPUTYPE_SANDYBRIDGE;
1269 #endif
1270           else
1271             return CPUTYPE_NEHALEM;
1272         case 14:
1273           //Skylake
1274           if(support_avx())
1275 #ifndef NO_AVX2
1276             return CPUTYPE_HASWELL;
1277 #else
1278             return CPUTYPE_SANDYBRIDGE;
1279 #endif
1280           else
1281             return CPUTYPE_NEHALEM;
1282         case 12:
1283           // Braswell
1284         case 13:
1285           // Avoton
1286             return CPUTYPE_NEHALEM;
1287         }
1288         break;
1289       case 5:
1290         switch (model) {
1291         case 6:
1292           //Broadwell
1293           if(support_avx())
1294 #ifndef NO_AVX2
1295             return CPUTYPE_HASWELL;
1296 #else
1297             return CPUTYPE_SANDYBRIDGE;
1298 #endif
1299           else
1300             return CPUTYPE_NEHALEM;
1301         case 5:
1302         case 14:
1303           // Skylake
1304           if(support_avx())
1305 #ifndef NO_AVX2
1306             return CPUTYPE_HASWELL;
1307 #else
1308             return CPUTYPE_SANDYBRIDGE;
1309 #endif
1310           else
1311             return CPUTYPE_NEHALEM;
1312         case 7:
1313             // Xeon Phi Knights Landing
1314           if(support_avx())
1315 #ifndef NO_AVX2
1316             return CPUTYPE_HASWELL;
1317 #else
1318             return CPUTYPE_SANDYBRIDGE;
1319 #endif
1320           else
1321             return CPUTYPE_NEHALEM;
1322         case 12:
1323             // Apollo Lake
1324             return CPUTYPE_NEHALEM;
1325         }
1326         break;
1327       case 9:
1328       case 8: 
1329         switch (model) {
1330         case 14: // Kaby Lake
1331           if(support_avx())
1332 #ifndef NO_AVX2
1333             return CPUTYPE_HASWELL;
1334 #else
1335             return CPUTYPE_SANDYBRIDGE;
1336 #endif
1337           else
1338             return CPUTYPE_NEHALEM;
1339         }
1340         break;    
1341       }
1342       break;
1343     case 0x7:
1344       return CPUTYPE_ITANIUM;
1345     case 0xf:
1346       switch (exfamily) {
1347       case 0 :
1348         return CPUTYPE_PENTIUM4;
1349       case 1 :
1350         return CPUTYPE_ITANIUM;
1351       }
1352       break;
1353     }
1354     return CPUTYPE_INTEL_UNKNOWN;
1355   }
1356
1357   if (vendor == VENDOR_AMD){
1358     switch (family) {
1359     case 0x4:
1360       return CPUTYPE_AMD5X86;
1361     case 0x5:
1362       return CPUTYPE_AMDK6;
1363     case 0x6:
1364       return CPUTYPE_ATHLON;
1365     case 0xf:
1366       switch (exfamily) {
1367       case  0:
1368       case  2:
1369         return CPUTYPE_OPTERON;
1370       case  1:
1371       case  3:
1372       case  7:
1373       case 10:
1374         return CPUTYPE_BARCELONA;
1375       case  5:
1376         return CPUTYPE_BOBCAT;
1377       case  6:
1378         switch (model) {
1379         case 1:
1380           //AMD Bulldozer Opteron 6200 / Opteron 4200 / AMD FX-Series
1381           if(support_avx())
1382             return CPUTYPE_BULLDOZER;
1383           else
1384             return CPUTYPE_BARCELONA; //OS don't support AVX.
1385         case 2: //AMD Piledriver
1386         case 3: //AMD Richland
1387           if(support_avx())
1388             return CPUTYPE_PILEDRIVER;
1389           else
1390             return CPUTYPE_BARCELONA; //OS don't support AVX.
1391         case 5: // New EXCAVATOR CPUS
1392           if(support_avx())
1393             return CPUTYPE_EXCAVATOR;
1394           else
1395             return CPUTYPE_BARCELONA; //OS don't support AVX.
1396         case 0:
1397         case 8:
1398           switch(exmodel){
1399           case 1: //AMD Trinity
1400             if(support_avx())
1401               return CPUTYPE_PILEDRIVER;
1402             else
1403               return CPUTYPE_BARCELONA; //OS don't support AVX.
1404           case 3:
1405             if(support_avx())
1406               return CPUTYPE_STEAMROLLER;
1407             else
1408               return CPUTYPE_BARCELONA; //OS don't support AVX.
1409
1410           case 6:
1411             if(support_avx())
1412               return CPUTYPE_EXCAVATOR;
1413             else
1414               return CPUTYPE_BARCELONA; //OS don't support AVX.
1415           }
1416           break;
1417         }
1418         break;
1419       case 8:
1420         switch (model) {
1421         case 1:
1422           // AMD Ryzen
1423           if(support_avx())
1424 #ifndef NO_AVX2
1425             return CPUTYPE_ZEN;
1426 #else
1427             return CPUTYPE_SANDYBRIDGE; // Zen is closer in architecture to Sandy Bridge than to Excavator
1428 #endif
1429           else
1430             return CPUTYPE_BARCELONA;
1431         }
1432       }
1433       break;
1434     }
1435     return CPUTYPE_AMD_UNKNOWN;
1436   }
1437
1438   if (vendor == VENDOR_CYRIX){
1439     switch (family) {
1440     case 0x4:
1441       return CPUTYPE_CYRIX5X86;
1442     case 0x5:
1443       return CPUTYPE_CYRIXM1;
1444     case 0x6:
1445       return CPUTYPE_CYRIXM2;
1446     }
1447     return CPUTYPE_CYRIX_UNKNOWN;
1448   }
1449
1450   if (vendor == VENDOR_NEXGEN){
1451     switch (family) {
1452     case 0x5:
1453       return CPUTYPE_NEXGENNX586;
1454     }
1455     return CPUTYPE_NEXGEN_UNKNOWN;
1456   }
1457
1458   if (vendor == VENDOR_CENTAUR){
1459     switch (family) {
1460     case 0x5:
1461       return CPUTYPE_CENTAURC6;
1462       break;
1463     case 0x6:
1464       return CPUTYPE_NANO;
1465       break;
1466
1467     }
1468     return CPUTYPE_VIAC3;
1469   }
1470
1471   if (vendor == VENDOR_RISE){
1472     switch (family) {
1473     case 0x5:
1474       return CPUTYPE_RISEMP6;
1475     }
1476     return CPUTYPE_RISE_UNKNOWN;
1477   }
1478
1479   if (vendor == VENDOR_SIS){
1480     switch (family) {
1481     case 0x5:
1482       return CPUTYPE_SYS55X;
1483     }
1484     return CPUTYPE_SIS_UNKNOWN;
1485   }
1486
1487   if (vendor == VENDOR_TRANSMETA){
1488     switch (family) {
1489     case 0x5:
1490       return CPUTYPE_CRUSOETM3X;
1491     }
1492     return CPUTYPE_TRANSMETA_UNKNOWN;
1493   }
1494
1495   if (vendor == VENDOR_NSC){
1496     switch (family) {
1497     case 0x5:
1498       return CPUTYPE_NSGEODE;
1499     }
1500     return CPUTYPE_NSC_UNKNOWN;
1501   }
1502
1503   return CPUTYPE_UNKNOWN;
1504 }
1505
1506 static char *cpuname[] = {
1507   "UNKNOWN",
1508   "INTEL_UNKNOWN",
1509   "UMC_UNKNOWN",
1510   "AMD_UNKNOWN",
1511   "CYRIX_UNKNOWN",
1512   "NEXGEN_UNKNOWN",
1513   "CENTAUR_UNKNOWN",
1514   "RISE_UNKNOWN",
1515   "SIS_UNKNOWN",
1516   "TRANSMETA_UNKNOWN",
1517   "NSC_UNKNOWN",
1518   "80386",
1519   "80486",
1520   "PENTIUM",
1521   "PENTIUM2",
1522   "PENTIUM3",
1523   "PENTIUMM",
1524   "PENTIUM4",
1525   "CORE2",
1526   "PENRYN",
1527   "DUNNINGTON",
1528   "NEHALEM",
1529   "ATOM",
1530   "ITANIUM",
1531   "ITANIUM2",
1532   "5X86",
1533   "K6",
1534   "ATHLON",
1535   "DURON",
1536   "OPTERON",
1537   "BARCELONA",
1538   "SHANGHAI",
1539   "ISTANBUL",
1540   "CYRIX5X86",
1541   "CYRIXM1",
1542   "CYRIXM2",
1543   "NEXGENNX586",
1544   "CENTAURC6",
1545   "RISEMP6",
1546   "SYS55X",
1547   "TM3X00",
1548   "NSGEODE",
1549   "VIAC3",
1550   "NANO",
1551   "SANDYBRIDGE",
1552   "BOBCAT",
1553   "BULLDOZER",
1554   "PILEDRIVER",
1555   "HASWELL",
1556   "STEAMROLLER",
1557   "EXCAVATOR",
1558   "ZEN",
1559 };
1560
1561 static char *lowercpuname[] = {
1562   "unknown",
1563   "intel_unknown",
1564   "umc_unknown",
1565   "amd_unknown",
1566   "cyrix_unknown",
1567   "nexgen_unknown",
1568   "centaur_unknown",
1569   "rise_unknown",
1570   "sis_unknown",
1571   "transmeta_unknown",
1572   "nsc_unknown",
1573   "80386",
1574   "80486",
1575   "pentium",
1576   "pentium2",
1577   "pentium3",
1578   "pentiumm",
1579   "pentium4",
1580   "core2",
1581   "penryn",
1582   "dunnington",
1583   "nehalem",
1584   "atom",
1585   "itanium",
1586   "itanium2",
1587   "5x86",
1588   "k6",
1589   "athlon",
1590   "duron",
1591   "opteron",
1592   "barcelona",
1593   "shanghai",
1594   "istanbul",
1595   "cyrix5x86",
1596   "cyrixm1",
1597   "cyrixm2",
1598   "nexgennx586",
1599   "centaurc6",
1600   "risemp6",
1601   "sys55x",
1602   "tms3x00",
1603   "nsgeode",
1604   "nano",
1605   "sandybridge",
1606   "bobcat",
1607   "bulldozer",
1608   "piledriver",
1609   "haswell",
1610   "steamroller",
1611   "excavator",
1612   "zen",
1613 };
1614
1615 static char *corename[] = {
1616   "UNKOWN",
1617   "80486",
1618   "P5",
1619   "P6",
1620   "KATMAI",
1621   "COPPERMINE",
1622   "NORTHWOOD",
1623   "PRESCOTT",
1624   "BANIAS",
1625   "ATHLON",
1626   "OPTERON",
1627   "BARCELONA",
1628   "VIAC3",
1629   "YONAH",
1630   "CORE2",
1631   "PENRYN",
1632   "DUNNINGTON",
1633   "NEHALEM",
1634   "ATOM",
1635   "NANO",
1636   "SANDYBRIDGE",
1637   "BOBCAT",
1638   "BULLDOZER",
1639   "PILEDRIVER",
1640   "HASWELL",
1641   "STEAMROLLER",
1642   "EXCAVATOR",
1643   "ZEN",
1644 };
1645
1646 static char *corename_lower[] = {
1647   "unknown",
1648   "80486",
1649   "p5",
1650   "p6",
1651   "katmai",
1652   "coppermine",
1653   "northwood",
1654   "prescott",
1655   "banias",
1656   "athlon",
1657   "opteron",
1658   "barcelona",
1659   "viac3",
1660   "yonah",
1661   "core2",
1662   "penryn",
1663   "dunnington",
1664   "nehalem",
1665   "atom",
1666   "nano",
1667   "sandybridge",
1668   "bobcat",
1669   "bulldozer",
1670   "piledriver",
1671   "haswell",
1672   "steamroller",
1673   "excavator",
1674   "zen",
1675 };
1676
1677
1678 char *get_cpunamechar(void){
1679   return cpuname[get_cpuname()];
1680 }
1681
1682 char *get_lower_cpunamechar(void){
1683   return lowercpuname[get_cpuname()];
1684 }
1685
1686
1687 int get_coretype(void){
1688
1689   int family, exfamily, model, exmodel, vendor;
1690
1691   if (!have_cpuid()) return CORE_80486;
1692
1693   family   = get_cputype(GET_FAMILY);
1694   exfamily = get_cputype(GET_EXFAMILY);
1695   model    = get_cputype(GET_MODEL);
1696   exmodel  = get_cputype(GET_EXMODEL);
1697
1698   vendor = get_vendor();
1699
1700   if (vendor == VENDOR_INTEL){
1701     switch (family) {
1702     case  4:
1703       return CORE_80486;
1704     case  5:
1705       return CORE_P5;
1706     case  6:
1707       switch (exmodel) {
1708       case  0:
1709         switch (model) {
1710         case  0:
1711         case  1:
1712         case  2:
1713         case  3:
1714         case  4:
1715         case  5:
1716         case  6:
1717           return CORE_P6;
1718         case  7:
1719           return CORE_KATMAI;
1720         case  8:
1721         case 10:
1722         case 11:
1723           return CORE_COPPERMINE;
1724         case  9:
1725         case 13:
1726         case 14:
1727           return CORE_BANIAS;
1728         case 15:
1729           return CORE_CORE2;
1730         }
1731         break;
1732       case  1:
1733         switch (model) {
1734         case  6:
1735           return CORE_CORE2;
1736         case  7:
1737           return CORE_PENRYN;
1738         case 10:
1739         case 11:
1740         case 14:
1741         case 15:
1742           return CORE_NEHALEM;
1743         case 12:
1744           return CORE_ATOM;
1745         case 13:
1746           return CORE_DUNNINGTON;
1747         }
1748         break;
1749       case  2:
1750         switch (model) {
1751         case 5:
1752           //Intel Core (Clarkdale) / Core (Arrandale)
1753           // Pentium (Clarkdale) / Pentium Mobile (Arrandale)
1754           // Xeon (Clarkdale), 32nm
1755           return CORE_NEHALEM;
1756         case 10:
1757           //Intel Core i5-2000 /i7-2000 (Sandy Bridge)
1758           if(support_avx())
1759             return CORE_SANDYBRIDGE;
1760           else
1761             return CORE_NEHALEM; //OS doesn't support AVX
1762         case 12:
1763           //Xeon Processor 5600 (Westmere-EP)
1764           return CORE_NEHALEM;
1765         case 13:
1766           //Intel Core i7-3000 / Xeon E5 (Sandy Bridge)
1767           if(support_avx())
1768             return CORE_SANDYBRIDGE;
1769           else
1770             return CORE_NEHALEM; //OS doesn't support AVX
1771         case 14:
1772           //Xeon E7540
1773         case 15:
1774           //Xeon Processor E7 (Westmere-EX)
1775           return CORE_NEHALEM;
1776         }
1777         break;
1778       case 3:
1779         switch (model) {
1780         case 10:
1781         case 14:
1782           if(support_avx())
1783             return CORE_SANDYBRIDGE;
1784           else
1785             return CORE_NEHALEM; //OS doesn't support AVX
1786         case 12:
1787         case 15:
1788           if(support_avx())
1789 #ifndef NO_AVX2
1790             return CORE_HASWELL;
1791 #else
1792             return CORE_SANDYBRIDGE;
1793 #endif
1794           else
1795             return CORE_NEHALEM;
1796         case 13:
1797           //broadwell
1798           if(support_avx())
1799 #ifndef NO_AVX2
1800             return CORE_HASWELL;
1801 #else
1802             return CORE_SANDYBRIDGE;
1803 #endif
1804           else
1805             return CORE_NEHALEM;
1806         }
1807         break;
1808       case 4:
1809         switch (model) {
1810         case 5:
1811         case 6:
1812           if(support_avx())
1813 #ifndef NO_AVX2
1814             return CORE_HASWELL;
1815 #else
1816             return CORE_SANDYBRIDGE;
1817 #endif
1818           else
1819             return CORE_NEHALEM;
1820         case 7:
1821         case 15:
1822           //broadwell
1823           if(support_avx())
1824 #ifndef NO_AVX2
1825             return CORE_HASWELL;
1826 #else
1827             return CORE_SANDYBRIDGE;
1828 #endif
1829           else
1830             return CORE_NEHALEM;
1831         case 14:
1832           //Skylake
1833           if(support_avx())
1834 #ifndef NO_AVX2
1835             return CORE_HASWELL;
1836 #else
1837             return CORE_SANDYBRIDGE;
1838 #endif
1839           else
1840             return CORE_NEHALEM;
1841         case 12:
1842           // Braswell
1843         case 13:
1844           // Avoton
1845             return CORE_NEHALEM;
1846         }
1847         break;
1848       case 5:
1849         switch (model) {
1850         case 6:
1851           //broadwell
1852           if(support_avx())
1853 #ifndef NO_AVX2
1854             return CORE_HASWELL;
1855 #else
1856             return CORE_SANDYBRIDGE;
1857 #endif
1858           else
1859             return CORE_NEHALEM;
1860         case 5:
1861         case 14:
1862           // Skylake
1863           if(support_avx())
1864 #ifndef NO_AVX2
1865             return CORE_HASWELL;
1866 #else
1867             return CORE_SANDYBRIDGE;
1868 #endif
1869           else
1870             return CORE_NEHALEM;
1871         case 7:
1872           // Phi Knights Landing
1873           if(support_avx())
1874 #ifndef NO_AVX2
1875             return CORE_HASWELL;
1876 #else
1877             return CORE_SANDYBRIDGE;
1878 #endif
1879           else
1880             return CORE_NEHALEM;
1881         case 12:
1882           // Apollo Lake
1883             return CORE_NEHALEM;
1884         }
1885         break;
1886       case 9:
1887       case 8:
1888         if (model == 14) { // Kaby Lake 
1889           if(support_avx())
1890 #ifndef NO_AVX2
1891             return CORE_HASWELL;
1892 #else
1893             return CORE_SANDYBRIDGE;
1894 #endif
1895           else
1896             return CORE_NEHALEM;
1897         }
1898       }
1899       break;
1900
1901       case 15:
1902         if (model <= 0x2) return CORE_NORTHWOOD;
1903         else return CORE_PRESCOTT;
1904     }
1905   }
1906
1907   if (vendor == VENDOR_AMD){
1908     if (family <= 0x5) return CORE_80486;
1909     if (family <= 0xe) return CORE_ATHLON;
1910     if (family == 0xf){
1911       if ((exfamily == 0) || (exfamily == 2)) return CORE_OPTERON;
1912       else if (exfamily == 5) return CORE_BOBCAT;
1913       else if (exfamily == 6) {
1914         switch (model) {
1915         case 1:
1916           //AMD Bulldozer Opteron 6200 / Opteron 4200 / AMD FX-Series
1917           if(support_avx())
1918             return CORE_BULLDOZER;
1919           else
1920             return CORE_BARCELONA; //OS don't support AVX.
1921         case 2: //AMD Piledriver
1922         case 3: //AMD Richland
1923           if(support_avx())
1924             return CORE_PILEDRIVER;
1925           else
1926             return CORE_BARCELONA; //OS don't support AVX.
1927     case 5: // New EXCAVATOR
1928           if(support_avx())
1929             return CORE_EXCAVATOR;
1930           else
1931             return CORE_BARCELONA; //OS don't support AVX.
1932         case 0:
1933         case 8:
1934           switch(exmodel){
1935           case 1: //AMD Trinity
1936             if(support_avx())
1937               return CORE_PILEDRIVER;
1938             else
1939               return CORE_BARCELONA; //OS don't support AVX.
1940
1941           case 3:
1942             if(support_avx())
1943               return CORE_STEAMROLLER;
1944             else
1945               return CORE_BARCELONA; //OS don't support AVX.
1946
1947           case 6:
1948             if(support_avx())
1949               return CORE_EXCAVATOR;
1950             else
1951               return CORE_BARCELONA; //OS don't support AVX.
1952           }
1953           break;
1954         }
1955       } else if (exfamily == 8) {
1956         switch (model) {
1957         case 1:
1958           // AMD Ryzen
1959           if(support_avx())
1960 #ifndef NO_AVX2
1961             return CORE_ZEN;
1962 #else
1963             return CORE_SANDYBRIDGE; // Zen is closer in architecture to Sandy Bridge than to Excavator
1964 #endif
1965           else
1966             return CORE_BARCELONA;
1967         }
1968       } else {
1969         return CORE_BARCELONA;
1970       }
1971     }
1972   }
1973
1974   if (vendor == VENDOR_CENTAUR) {
1975     switch (family) {
1976     case 0x6:
1977       return CORE_NANO;
1978       break;
1979     }
1980     return CORE_VIAC3;
1981   }
1982
1983   return CORE_UNKNOWN;
1984 }
1985
1986 void get_cpuconfig(void){
1987
1988   cache_info_t info;
1989   int features;
1990
1991   printf("#define %s\n", cpuname[get_cpuname()]);
1992
1993
1994   if (get_coretype() != CORE_P5) {
1995
1996     get_cacheinfo(CACHE_INFO_L1_I, &info);
1997     if (info.size > 0) {
1998       printf("#define L1_CODE_SIZE %d\n", info.size * 1024);
1999       printf("#define L1_CODE_ASSOCIATIVE %d\n", info.associative);
2000       printf("#define L1_CODE_LINESIZE %d\n", info.linesize);
2001     }
2002
2003     get_cacheinfo(CACHE_INFO_L1_D, &info);
2004     if (info.size > 0) {
2005       printf("#define L1_DATA_SIZE %d\n", info.size * 1024);
2006       printf("#define L1_DATA_ASSOCIATIVE %d\n", info.associative);
2007       printf("#define L1_DATA_LINESIZE %d\n", info.linesize);
2008     }
2009
2010     get_cacheinfo(CACHE_INFO_L2, &info);
2011     if (info.size > 0) {
2012       printf("#define L2_SIZE %d\n", info.size * 1024);
2013       printf("#define L2_ASSOCIATIVE %d\n", info.associative);
2014       printf("#define L2_LINESIZE %d\n", info.linesize);
2015     } else {
2016       //fall back for some virtual machines.
2017       printf("#define L2_SIZE 1048576\n");
2018       printf("#define L2_ASSOCIATIVE 6\n");
2019       printf("#define L2_LINESIZE 64\n");
2020     }
2021
2022
2023     get_cacheinfo(CACHE_INFO_L3, &info);
2024     if (info.size > 0) {
2025       printf("#define L3_SIZE %d\n", info.size * 1024);
2026       printf("#define L3_ASSOCIATIVE %d\n", info.associative);
2027       printf("#define L3_LINESIZE %d\n", info.linesize);
2028     }
2029
2030     get_cacheinfo(CACHE_INFO_L1_ITB, &info);
2031     if (info.size > 0) {
2032       printf("#define ITB_SIZE %d\n", info.size * 1024);
2033       printf("#define ITB_ASSOCIATIVE %d\n", info.associative);
2034       printf("#define ITB_ENTRIES %d\n", info.linesize);
2035     }
2036
2037     get_cacheinfo(CACHE_INFO_L1_DTB, &info);
2038     if (info.size > 0) {
2039       printf("#define DTB_SIZE %d\n", info.size * 1024);
2040       printf("#define DTB_ASSOCIATIVE %d\n", info.associative);
2041       printf("#define DTB_DEFAULT_ENTRIES %d\n", info.linesize);
2042     } else {
2043       //fall back for some virtual machines.
2044       printf("#define DTB_DEFAULT_ENTRIES 32\n");
2045     }
2046
2047     features = get_cputype(GET_FEATURE);
2048
2049     if (features & HAVE_CMOV )   printf("#define HAVE_CMOV\n");
2050     if (features & HAVE_MMX  )   printf("#define HAVE_MMX\n");
2051     if (features & HAVE_SSE  )   printf("#define HAVE_SSE\n");
2052     if (features & HAVE_SSE2 )   printf("#define HAVE_SSE2\n");
2053     if (features & HAVE_SSE3 )   printf("#define HAVE_SSE3\n");
2054     if (features & HAVE_SSSE3)   printf("#define HAVE_SSSE3\n");
2055     if (features & HAVE_SSE4_1)   printf("#define HAVE_SSE4_1\n");
2056     if (features & HAVE_SSE4_2)   printf("#define HAVE_SSE4_2\n");
2057     if (features & HAVE_SSE4A)   printf("#define HAVE_SSE4A\n");
2058     if (features & HAVE_SSE5 )   printf("#define HAVE_SSSE5\n");
2059     if (features & HAVE_AVX )    printf("#define HAVE_AVX\n");
2060     if (features & HAVE_3DNOWEX) printf("#define HAVE_3DNOWEX\n");
2061     if (features & HAVE_3DNOW)   printf("#define HAVE_3DNOW\n");
2062     if (features & HAVE_FMA4 )    printf("#define HAVE_FMA4\n");
2063     if (features & HAVE_FMA3 )    printf("#define HAVE_FMA3\n");
2064     if (features & HAVE_CFLUSH)  printf("#define HAVE_CFLUSH\n");
2065     if (features & HAVE_HIT)     printf("#define HAVE_HIT 1\n");
2066     if (features & HAVE_MISALIGNSSE) printf("#define HAVE_MISALIGNSSE\n");
2067     if (features & HAVE_128BITFPU)   printf("#define HAVE_128BITFPU\n");
2068     if (features & HAVE_FASTMOVU)    printf("#define HAVE_FASTMOVU\n");
2069
2070     printf("#define NUM_SHAREDCACHE %d\n", get_cputype(GET_NUMSHARE) + 1);
2071     printf("#define NUM_CORES %d\n", get_cputype(GET_NUMCORES) + 1);
2072
2073     features = get_coretype();
2074     if (features > 0) printf("#define CORE_%s\n", corename[features]);
2075   } else {
2076     printf("#define DTB_DEFAULT_ENTRIES 16\n");
2077     printf("#define L1_CODE_SIZE 8192\n");
2078     printf("#define L1_DATA_SIZE 8192\n");
2079     printf("#define L2_SIZE 0\n");
2080   }
2081 }
2082
2083 void get_architecture(void){
2084 #ifndef __64BIT__
2085     printf("X86");
2086 #else
2087     printf("X86_64");
2088 #endif
2089 }
2090
2091 void get_subarchitecture(void){
2092     printf("%s", get_cpunamechar());
2093 }
2094
2095 void get_subdirname(void){
2096 #ifndef __64BIT__
2097     printf("x86");
2098 #else
2099     printf("x86_64");
2100 #endif
2101 }
2102
2103 char *get_corename(void){
2104   return corename[get_coretype()];
2105 }
2106
2107 void get_libname(void){
2108   printf("%s",   corename_lower[get_coretype()]);
2109 }
2110
2111 /* This if for Makefile */
2112 void get_sse(void){
2113
2114   int features;
2115
2116   features = get_cputype(GET_FEATURE);
2117
2118   if (features & HAVE_MMX  )   printf("HAVE_MMX=1\n");
2119   if (features & HAVE_SSE  )   printf("HAVE_SSE=1\n");
2120   if (features & HAVE_SSE2 )   printf("HAVE_SSE2=1\n");
2121   if (features & HAVE_SSE3 )   printf("HAVE_SSE3=1\n");
2122   if (features & HAVE_SSSE3)   printf("HAVE_SSSE3=1\n");
2123   if (features & HAVE_SSE4_1)   printf("HAVE_SSE4_1=1\n");
2124   if (features & HAVE_SSE4_2)   printf("HAVE_SSE4_2=1\n");
2125   if (features & HAVE_SSE4A)   printf("HAVE_SSE4A=1\n");
2126   if (features & HAVE_SSE5 )   printf("HAVE_SSSE5=1\n");
2127   if (features & HAVE_AVX )    printf("HAVE_AVX=1\n");
2128   if (features & HAVE_3DNOWEX) printf("HAVE_3DNOWEX=1\n");
2129   if (features & HAVE_3DNOW)   printf("HAVE_3DNOW=1\n");
2130   if (features & HAVE_FMA4 )    printf("HAVE_FMA4=1\n");
2131   if (features & HAVE_FMA3 )    printf("HAVE_FMA3=1\n");
2132
2133 }