180 CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX) |
180 CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX) |
181 CPU_SSSE3 = (1 << 9), |
181 CPU_SSSE3 = (1 << 9), |
182 CPU_SSE4A = (1 << 10), |
182 CPU_SSE4A = (1 << 10), |
183 CPU_SSE4_1 = (1 << 11), |
183 CPU_SSE4_1 = (1 << 11), |
184 CPU_SSE4_2 = (1 << 12), |
184 CPU_SSE4_2 = (1 << 12), |
185 CPU_POPCNT = (1 << 13) |
185 CPU_POPCNT = (1 << 13), |
|
186 CPU_LZCNT = (1 << 14) |
186 } cpuFeatureFlags; |
187 } cpuFeatureFlags; |
187 |
188 |
188 // cpuid information block. All info derived from executing cpuid with |
189 // cpuid information block. All info derived from executing cpuid with |
189 // various function numbers is stored here. Intel and AMD info is |
190 // various function numbers is stored here. Intel and AMD info is |
190 // merged in this block: accessor methods disentangle it. |
191 // merged in this block: accessor methods disentangle it. |
275 if (threads_per_core() > 1) |
276 if (threads_per_core() > 1) |
276 result |= CPU_HT; |
277 result |= CPU_HT; |
277 if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || is_amd() && |
278 if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || is_amd() && |
278 _cpuid_info.ext_cpuid1_edx.bits.mmx != 0) |
279 _cpuid_info.ext_cpuid1_edx.bits.mmx != 0) |
279 result |= CPU_MMX; |
280 result |= CPU_MMX; |
280 if (is_amd() && _cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) |
|
281 result |= CPU_3DNOW; |
|
282 if (_cpuid_info.std_cpuid1_edx.bits.sse != 0) |
281 if (_cpuid_info.std_cpuid1_edx.bits.sse != 0) |
283 result |= CPU_SSE; |
282 result |= CPU_SSE; |
284 if (_cpuid_info.std_cpuid1_edx.bits.sse2 != 0) |
283 if (_cpuid_info.std_cpuid1_edx.bits.sse2 != 0) |
285 result |= CPU_SSE2; |
284 result |= CPU_SSE2; |
286 if (_cpuid_info.std_cpuid1_ecx.bits.sse3 != 0) |
285 if (_cpuid_info.std_cpuid1_ecx.bits.sse3 != 0) |
287 result |= CPU_SSE3; |
286 result |= CPU_SSE3; |
288 if (_cpuid_info.std_cpuid1_ecx.bits.ssse3 != 0) |
287 if (_cpuid_info.std_cpuid1_ecx.bits.ssse3 != 0) |
289 result |= CPU_SSSE3; |
288 result |= CPU_SSSE3; |
290 if (is_amd() && _cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0) |
|
291 result |= CPU_SSE4A; |
|
292 if (_cpuid_info.std_cpuid1_ecx.bits.sse4_1 != 0) |
289 if (_cpuid_info.std_cpuid1_ecx.bits.sse4_1 != 0) |
293 result |= CPU_SSE4_1; |
290 result |= CPU_SSE4_1; |
294 if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0) |
291 if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0) |
295 result |= CPU_SSE4_2; |
292 result |= CPU_SSE4_2; |
296 if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0) |
293 if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0) |
297 result |= CPU_POPCNT; |
294 result |= CPU_POPCNT; |
|
295 |
|
296 // AMD features. |
|
297 if (is_amd()) { |
|
298 if (_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) |
|
299 result |= CPU_3DNOW; |
|
300 if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) |
|
301 result |= CPU_LZCNT; |
|
302 if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0) |
|
303 result |= CPU_SSE4A; |
|
304 } |
|
305 |
298 return result; |
306 return result; |
299 } |
307 } |
300 |
308 |
301 static void get_processor_features(); |
309 static void get_processor_features(); |
302 |
310 |
389 // AMD features |
397 // AMD features |
390 // |
398 // |
391 static bool supports_3dnow() { return (_cpuFeatures & CPU_3DNOW) != 0; } |
399 static bool supports_3dnow() { return (_cpuFeatures & CPU_3DNOW) != 0; } |
392 static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; } |
400 static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; } |
393 static bool supports_3dnow2() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.tdnow2 != 0; } |
401 static bool supports_3dnow2() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.tdnow2 != 0; } |
|
402 static bool supports_lzcnt() { return (_cpuFeatures & CPU_LZCNT) != 0; } |
394 static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; } |
403 static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; } |
395 |
404 |
396 static bool supports_compare_and_exchange() { return true; } |
405 static bool supports_compare_and_exchange() { return true; } |
397 |
406 |
398 static const char* cpu_features() { return _features_str; } |
407 static const char* cpu_features() { return _features_str; } |