@@ -27,10 +27,10 @@ void cpuid(uint32_t eax, int32_t ecx, int32_t val[4])
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
3636bool has_feature (int32_t val, int32_t bit)
@@ -41,34 +41,86 @@ bool has_feature(int32_t val, int32_t bit)
4141
4242Model getModel ()
4343{
44+ Model result;
45+
46+ int32_t cpu_HFP = 0 ; // Highest Function Parameter
47+ int32_t cpu_HEFP = 0 ; // Highest Extended Function Parameter
4448 int32_t cpu_info[4 ];
4549 char cpustr[13 ] = {0 };
50+ char brandstr[13 ] = {0 };
4651
4752 cpuid (0 , 0 , cpu_info);
53+ cpu_HFP = cpu_info[0 ];
4854 std::memcpy (cpustr, &cpu_info[1 ], 4 );
4955 std::memcpy (cpustr + 4 , &cpu_info[3 ], 4 );
5056 std::memcpy (cpustr + 8 , &cpu_info[2 ], 4 );
5157
52- Model result;
53-
5458 cpuid (1 , 0 , cpu_info);
55-
59+ result. model = get_masked (cpu_info[ 0 ], 8 , 4 );
5660 result.family = get_masked (cpu_info[0 ], 12 , 8 );
57- result.model = get_masked (cpu_info[0 ], 8 , 4 ) | get_masked (cpu_info[0 ], 20 , 16 ) << 4 ;
58- result.type_name = cpustr;
61+ if (result.family == 0x6 || result.family == 0xF )
62+ {
63+ result.model += get_masked (cpu_info[0 ], 20 , 16 ) << 4 ;
64+ }
65+ if (result.family != 0xF )
66+ {
67+ result.family += get_masked (cpu_info[0 ], 28 , 20 );
68+ }
5969
60- // feature bits https://en.wikipedia.org/wiki/CPUID
61- // sse2
70+ // feature bits https://en.wikipedia.org/wiki/CPUID#EAX=1:_Processor_Info_and_Feature_Bits
71+ // sse2/sse3/ssse3
6272 result.sse2 = has_feature (cpu_info[3 ], 26 );
73+ result.sse3 = has_feature (cpu_info[2 ], 0 );
74+ result.ssse3 = has_feature (cpu_info[2 ], 9 );
6375 // aes-ni
6476 result.aes = has_feature (cpu_info[2 ], 25 );
6577 // avx - 27 is the check if the OS overwrote cpu features
6678 result.avx = has_feature (cpu_info[2 ], 28 ) && has_feature (cpu_info[2 ], 27 );
6779
80+ // extended feature bits https://en.wikipedia.org/wiki/CPUID#EAX=7,_ECX=0:_Extended_Features
81+ if (cpu_HFP >= 7 )
82+ {
83+ cpuid (7 , 0 , cpu_info);
84+ result.avx2 = has_feature (cpu_info[1 ], 5 );
85+ }
86+ // extended function support https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented
87+ cpuid (0x80000000 , 0 , cpu_info);
88+ cpu_HEFP = cpu_info[0 ];
89+
90+ // processor brand string https://en.wikipedia.org/wiki/CPUID#EAX=80000002h,80000003h,80000004h:_Processor_Brand_String
91+ if (cpu_HEFP >= 0x80000004 )
92+ {
93+ for (uint32_t efp=0x80000002 ; efp<0x80000004 ; efp++){
94+ cpuid (0x80000002 , 0 , cpu_info);
95+ std::memcpy (brandstr+(16 *(efp-0x80000002 )), &cpu_info, 16 );
96+ }
97+ result.brand_name = brandstr;
98+ }
99+
100+ if (strcmp (cpustr, " GenuineIntel" ) == 0 )
101+ {
102+ if (result.family == 0x6 ){
103+ result.isIntelXBridge = (
104+ result.model == 0x2A // Sandy Bridge
105+ || result.model == 0x3A // Ivy Bridge
106+ );
107+ result.isIntelXWell = (
108+ result.model == 0x3C || result.model == 0x45 || result.model == 0x46 // Haswell
109+ || result.model == 0x47 || result.model == 0x3D // Broadwell
110+ );
111+ result.isIntelXLake = (
112+ result.model == 0x4E || result.model == 0x5E // Skylake
113+ || result.model == 0x8E // Kaby/Coffee/Whiskey/Amber Lake
114+ || result.model == 0x9E // Kaby/Coffee Lake
115+ || result.model == 0x66 // Cannon Lake
116+ );
117+ }
118+ }
68119 if (strcmp (cpustr, " AuthenticAMD" ) == 0 )
69120 {
70- if (result.family == 0xF )
71- result.family += get_masked (cpu_info[0 ], 28 , 20 );
121+ result.isAMDHammer = (result.family != 0x15 && result.family >= 0xF && result.family <= 0x16 );
122+ result.isAMDBulldozer = (result.family == 0x15 );
123+ result.isAMDZen = (result.family == 0x17 );
72124 }
73125
74126 return result;
0 commit comments