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