284 CPU_AVX512DQ = (1 << 27), |
282 CPU_AVX512DQ = (1 << 27), |
285 CPU_AVX512PF = (1 << 28), |
283 CPU_AVX512PF = (1 << 28), |
286 CPU_AVX512ER = (1 << 29), |
284 CPU_AVX512ER = (1 << 29), |
287 CPU_AVX512CD = (1 << 30), |
285 CPU_AVX512CD = (1 << 30), |
288 CPU_AVX512BW = (1 << 31) |
286 CPU_AVX512BW = (1 << 31) |
289 } cpuFeatureFlags; |
287 }; |
290 |
288 |
291 #define CPU_AVX512VL UCONST64(0x100000000) // EVEX instructions with smaller vector length : enums are limited to 32bit |
289 #define CPU_AVX512VL UCONST64(0x100000000) // EVEX instructions with smaller vector length : enums are limited to 32bit |
292 |
290 |
293 enum { |
291 enum Extended_Family { |
294 // AMD |
292 // AMD |
295 CPU_FAMILY_AMD_11H = 0x11, |
293 CPU_FAMILY_AMD_11H = 0x11, |
296 // Intel |
294 // Intel |
297 CPU_FAMILY_INTEL_CORE = 6, |
295 CPU_FAMILY_INTEL_CORE = 6, |
298 CPU_MODEL_NEHALEM = 0x1e, |
296 CPU_MODEL_NEHALEM = 0x1e, |
306 CPU_MODEL_IVYBRIDGE_EP = 0x3a, |
304 CPU_MODEL_IVYBRIDGE_EP = 0x3a, |
307 CPU_MODEL_HASWELL_E3 = 0x3c, |
305 CPU_MODEL_HASWELL_E3 = 0x3c, |
308 CPU_MODEL_HASWELL_E7 = 0x3f, |
306 CPU_MODEL_HASWELL_E7 = 0x3f, |
309 CPU_MODEL_BROADWELL = 0x3d, |
307 CPU_MODEL_BROADWELL = 0x3d, |
310 CPU_MODEL_SKYLAKE = CPU_MODEL_HASWELL_E3 |
308 CPU_MODEL_SKYLAKE = CPU_MODEL_HASWELL_E3 |
311 } cpuExtendedFamily; |
309 }; |
312 |
310 |
313 // cpuid information block. All info derived from executing cpuid with |
311 // cpuid information block. All info derived from executing cpuid with |
314 // various function numbers is stored here. Intel and AMD info is |
312 // various function numbers is stored here. Intel and AMD info is |
315 // merged in this block: accessor methods disentangle it. |
313 // merged in this block: accessor methods disentangle it. |
316 // |
314 // |
596 static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; } |
594 static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; } |
597 static bool is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; } |
595 static bool is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; } |
598 static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; } |
596 static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; } |
599 static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; } |
597 static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; } |
600 |
598 |
601 static void clean_cpuFeatures() { _cpuFeatures = 0; } |
599 static void clean_cpuFeatures() { _features = 0; } |
602 static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); } |
600 static void set_avx_cpuFeatures() { _features = (CPU_SSE | CPU_SSE2 | CPU_AVX); } |
603 static void set_evex_cpuFeatures() { _cpuFeatures = (CPU_AVX512F | CPU_SSE | CPU_SSE2 ); } |
601 static void set_evex_cpuFeatures() { _features = (CPU_AVX512F | CPU_SSE | CPU_SSE2 ); } |
604 |
602 |
605 |
603 |
606 // Initialization |
604 // Initialization |
607 static void initialize(); |
605 static void initialize(); |
608 |
606 |
686 } |
684 } |
687 |
685 |
688 // |
686 // |
689 // Feature identification |
687 // Feature identification |
690 // |
688 // |
691 static bool supports_cpuid() { return _cpuFeatures != 0; } |
689 static bool supports_cpuid() { return _features != 0; } |
692 static bool supports_cmpxchg8() { return (_cpuFeatures & CPU_CX8) != 0; } |
690 static bool supports_cmpxchg8() { return (_features & CPU_CX8) != 0; } |
693 static bool supports_cmov() { return (_cpuFeatures & CPU_CMOV) != 0; } |
691 static bool supports_cmov() { return (_features & CPU_CMOV) != 0; } |
694 static bool supports_fxsr() { return (_cpuFeatures & CPU_FXSR) != 0; } |
692 static bool supports_fxsr() { return (_features & CPU_FXSR) != 0; } |
695 static bool supports_ht() { return (_cpuFeatures & CPU_HT) != 0; } |
693 static bool supports_ht() { return (_features & CPU_HT) != 0; } |
696 static bool supports_mmx() { return (_cpuFeatures & CPU_MMX) != 0; } |
694 static bool supports_mmx() { return (_features & CPU_MMX) != 0; } |
697 static bool supports_sse() { return (_cpuFeatures & CPU_SSE) != 0; } |
695 static bool supports_sse() { return (_features & CPU_SSE) != 0; } |
698 static bool supports_sse2() { return (_cpuFeatures & CPU_SSE2) != 0; } |
696 static bool supports_sse2() { return (_features & CPU_SSE2) != 0; } |
699 static bool supports_sse3() { return (_cpuFeatures & CPU_SSE3) != 0; } |
697 static bool supports_sse3() { return (_features & CPU_SSE3) != 0; } |
700 static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; } |
698 static bool supports_ssse3() { return (_features & CPU_SSSE3)!= 0; } |
701 static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; } |
699 static bool supports_sse4_1() { return (_features & CPU_SSE4_1) != 0; } |
702 static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; } |
700 static bool supports_sse4_2() { return (_features & CPU_SSE4_2) != 0; } |
703 static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; } |
701 static bool supports_popcnt() { return (_features & CPU_POPCNT) != 0; } |
704 static bool supports_avx() { return (_cpuFeatures & CPU_AVX) != 0; } |
702 static bool supports_avx() { return (_features & CPU_AVX) != 0; } |
705 static bool supports_avx2() { return (_cpuFeatures & CPU_AVX2) != 0; } |
703 static bool supports_avx2() { return (_features & CPU_AVX2) != 0; } |
706 static bool supports_tsc() { return (_cpuFeatures & CPU_TSC) != 0; } |
704 static bool supports_tsc() { return (_features & CPU_TSC) != 0; } |
707 static bool supports_aes() { return (_cpuFeatures & CPU_AES) != 0; } |
705 static bool supports_aes() { return (_features & CPU_AES) != 0; } |
708 static bool supports_erms() { return (_cpuFeatures & CPU_ERMS) != 0; } |
706 static bool supports_erms() { return (_features & CPU_ERMS) != 0; } |
709 static bool supports_clmul() { return (_cpuFeatures & CPU_CLMUL) != 0; } |
707 static bool supports_clmul() { return (_features & CPU_CLMUL) != 0; } |
710 static bool supports_rtm() { return (_cpuFeatures & CPU_RTM) != 0; } |
708 static bool supports_rtm() { return (_features & CPU_RTM) != 0; } |
711 static bool supports_bmi1() { return (_cpuFeatures & CPU_BMI1) != 0; } |
709 static bool supports_bmi1() { return (_features & CPU_BMI1) != 0; } |
712 static bool supports_bmi2() { return (_cpuFeatures & CPU_BMI2) != 0; } |
710 static bool supports_bmi2() { return (_features & CPU_BMI2) != 0; } |
713 static bool supports_adx() { return (_cpuFeatures & CPU_ADX) != 0; } |
711 static bool supports_adx() { return (_features & CPU_ADX) != 0; } |
714 static bool supports_evex() { return (_cpuFeatures & CPU_AVX512F) != 0; } |
712 static bool supports_evex() { return (_features & CPU_AVX512F) != 0; } |
715 static bool supports_avx512dq() { return (_cpuFeatures & CPU_AVX512DQ) != 0; } |
713 static bool supports_avx512dq() { return (_features & CPU_AVX512DQ) != 0; } |
716 static bool supports_avx512pf() { return (_cpuFeatures & CPU_AVX512PF) != 0; } |
714 static bool supports_avx512pf() { return (_features & CPU_AVX512PF) != 0; } |
717 static bool supports_avx512er() { return (_cpuFeatures & CPU_AVX512ER) != 0; } |
715 static bool supports_avx512er() { return (_features & CPU_AVX512ER) != 0; } |
718 static bool supports_avx512cd() { return (_cpuFeatures & CPU_AVX512CD) != 0; } |
716 static bool supports_avx512cd() { return (_features & CPU_AVX512CD) != 0; } |
719 static bool supports_avx512bw() { return (_cpuFeatures & CPU_AVX512BW) != 0; } |
717 static bool supports_avx512bw() { return (_features & CPU_AVX512BW) != 0; } |
720 static bool supports_avx512vl() { return (_cpuFeatures & CPU_AVX512VL) != 0; } |
718 static bool supports_avx512vl() { return (_features & CPU_AVX512VL) != 0; } |
721 static bool supports_avx512vlbw() { return (supports_avx512bw() && supports_avx512vl()); } |
719 static bool supports_avx512vlbw() { return (supports_avx512bw() && supports_avx512vl()); } |
722 static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); } |
720 static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); } |
723 static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); } |
721 static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); } |
724 static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } |
722 static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } |
725 static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } |
723 static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } |
744 } |
742 } |
745 return false; |
743 return false; |
746 } |
744 } |
747 |
745 |
748 // AMD features |
746 // AMD features |
749 static bool supports_3dnow_prefetch() { return (_cpuFeatures & CPU_3DNOW_PREFETCH) != 0; } |
747 static bool supports_3dnow_prefetch() { return (_features & CPU_3DNOW_PREFETCH) != 0; } |
750 static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; } |
748 static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; } |
751 static bool supports_lzcnt() { return (_cpuFeatures & CPU_LZCNT) != 0; } |
749 static bool supports_lzcnt() { return (_features & CPU_LZCNT) != 0; } |
752 static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; } |
750 static bool supports_sse4a() { return (_features & CPU_SSE4A) != 0; } |
753 |
751 |
754 static bool is_amd_Barcelona() { return is_amd() && |
752 static bool is_amd_Barcelona() { return is_amd() && |
755 extended_cpu_family() == CPU_FAMILY_AMD_11H; } |
753 extended_cpu_family() == CPU_FAMILY_AMD_11H; } |
756 |
754 |
757 // Intel and AMD newer cores support fast timestamps well |
755 // Intel and AMD newer cores support fast timestamps well |
758 static bool supports_tscinv_bit() { |
756 static bool supports_tscinv_bit() { |
759 return (_cpuFeatures & CPU_TSCINV) != 0; |
757 return (_features & CPU_TSCINV) != 0; |
760 } |
758 } |
761 static bool supports_tscinv() { |
759 static bool supports_tscinv() { |
762 return supports_tscinv_bit() && |
760 return supports_tscinv_bit() && |
763 ( (is_amd() && !is_amd_Barcelona()) || |
761 ( (is_amd() && !is_amd_Barcelona()) || |
764 is_intel_tsc_synched_at_init() ); |
762 is_intel_tsc_synched_at_init() ); |