@@ -27,10 +27,10 @@ namespace cpu
2727 #endif
2828 }
2929
30- int32_t get_masked (int32_t val, int32_t h, int32_t l)
30+ uint32_t get_masked (int32_t val, int32_t h, int32_t l)
3131 {
3232 val &= (0x7FFFFFFF >> (31 -(h-l))) << l;
33- return val >> l;
33+ return static_cast < uint32_t >( val >> l) ;
3434 }
3535
3636 bool has_feature (int32_t val, int32_t bit)
@@ -42,34 +42,86 @@ namespace cpu
4242
4343 Model getModel ()
4444 {
45+ Model result;
46+
47+ int32_t cpu_HFP = 0 ; // Highest Function Parameter
48+ int32_t cpu_HEFP = 0 ; // Highest Extended Function Parameter
4549 int32_t cpu_info[4 ];
4650 char cpustr[13 ] = {0 };
51+ char brandstr[13 ] = {0 };
4752
4853 cpuid (0 , 0 , cpu_info);
54+ cpu_HFP = cpu_info[0 ];
4955 std::memcpy (cpustr, &cpu_info[1 ], 4 );
5056 std::memcpy (cpustr+4 , &cpu_info[3 ], 4 );
5157 std::memcpy (cpustr+8 , &cpu_info[2 ], 4 );
5258
53- Model result;
54-
5559 cpuid (1 , 0 , cpu_info);
56-
60+ result. model = get_masked (cpu_info[ 0 ], 8 , 4 );
5761 result.family = get_masked (cpu_info[0 ], 12 , 8 );
58- result.model = get_masked (cpu_info[0 ], 8 , 4 ) | get_masked (cpu_info[0 ], 20 , 16 ) << 4 ;
59- result.type_name = cpustr;
62+ if (result.family == 0x6 || result.family == 0xF )
63+ {
64+ result.model += get_masked (cpu_info[0 ], 20 , 16 ) << 4 ;
65+ }
66+ if (result.family != 0xF )
67+ {
68+ result.family += get_masked (cpu_info[0 ], 28 , 20 );
69+ }
6070
61- // feature bits https://en.wikipedia.org/wiki/CPUID
62- // sse2
71+ // feature bits https://en.wikipedia.org/wiki/CPUID#EAX=1:_Processor_Info_and_Feature_Bits
72+ // sse2/sse3/ssse3
6373 result.sse2 = has_feature (cpu_info[3 ], 26 );
74+ result.sse3 = has_feature (cpu_info[2 ], 0 );
75+ result.ssse3 = has_feature (cpu_info[2 ], 9 );
6476 // aes-ni
6577 result.aes = has_feature (cpu_info[2 ], 25 );
6678 // avx - 27 is the check if the OS overwrote cpu features
67- result.avx = has_feature (cpu_info[2 ], 28 ) && has_feature (cpu_info[2 ], 27 ) ;
79+ result.avx = has_feature (cpu_info[2 ], 28 ) && has_feature (cpu_info[2 ], 27 );
6880
81+ // extended feature bits https://en.wikipedia.org/wiki/CPUID#EAX=7,_ECX=0:_Extended_Features
82+ if (cpu_HFP >= 7 )
83+ {
84+ cpuid (7 , 0 , cpu_info);
85+ result.avx2 = has_feature (cpu_info[1 ], 5 );
86+ }
87+ // extended function support https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented
88+ cpuid (0x80000000 , 0 , cpu_info);
89+ cpu_HEFP = cpu_info[0 ];
90+
91+ // processor brand string https://en.wikipedia.org/wiki/CPUID#EAX=80000002h,80000003h,80000004h:_Processor_Brand_String
92+ if (cpu_HEFP >= 0x80000004 )
93+ {
94+ for (uint32_t efp=0x80000002 ; efp<0x80000004 ; efp++){
95+ cpuid (0x80000002 , 0 , cpu_info);
96+ std::memcpy (brandstr+(16 *(efp-0x80000002 )), &cpu_info, 16 );
97+ }
98+ result.brand_name = brandstr;
99+ }
100+
101+ if (strcmp (cpustr, " GenuineIntel" ) == 0 )
102+ {
103+ if (result.family == 0x6 ){
104+ result.isIntelXBridge = (
105+ result.model == 0x2A // Sandy Bridge
106+ || result.model == 0x3A // Ivy Bridge
107+ );
108+ result.isIntelXWell = (
109+ result.model == 0x3C || result.model == 0x45 || result.model == 0x46 // Haswell
110+ || result.model == 0x47 || result.model == 0x3D // Broadwell
111+ );
112+ result.isIntelXLake = (
113+ result.model == 0x4E || result.model == 0x5E // Skylake
114+ || result.model == 0x8E // Kaby/Coffee/Whiskey/Amber Lake
115+ || result.model == 0x9E // Kaby/Coffee Lake
116+ || result.model == 0x66 // Cannon Lake
117+ );
118+ }
119+ }
69120 if (strcmp (cpustr, " AuthenticAMD" ) == 0 )
70121 {
71- if (result.family == 0xF )
72- result.family += get_masked (cpu_info[0 ], 28 , 20 );
122+ result.isAMDHammer = (result.family != 0x15 && result.family >= 0xF && result.family <= 0x16 );
123+ result.isAMDBulldozer = (result.family == 0x15 );
124+ result.isAMDZen = (result.family == 0x17 );
73125 }
74126
75127 return result;
0 commit comments