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