| Index: base/cpu.cc
|
| diff --git a/base/cpu.cc b/base/cpu.cc
|
| index 78064e2815f4bed5da737174289374748707e6e5..b7830617fb15cc32dc1ac007bbd22c8a84dfa941 100644
|
| --- a/base/cpu.cc
|
| +++ b/base/cpu.cc
|
| @@ -8,11 +8,13 @@
|
|
|
| #include <algorithm>
|
|
|
| +#include "base/basictypes.h"
|
| #include "build/build_config.h"
|
|
|
| #if defined(ARCH_CPU_X86_FAMILY)
|
| #if defined(_MSC_VER)
|
| #include <intrin.h>
|
| +#include <immintrin.h> // For _xgetbv()
|
| #endif
|
| #endif
|
|
|
| @@ -33,11 +35,15 @@ CPU::CPU()
|
| has_ssse3_(false),
|
| has_sse41_(false),
|
| has_sse42_(false),
|
| + has_avx_(false),
|
| + has_avx_hardware_(false),
|
| has_non_stop_time_stamp_counter_(false),
|
| cpu_vendor_("unknown") {
|
| Initialize();
|
| }
|
|
|
| +namespace {
|
| +
|
| #if defined(ARCH_CPU_X86_FAMILY)
|
| #ifndef _MSC_VER
|
|
|
| @@ -82,9 +88,21 @@ void __cpuidex(int cpu_info[4], int info_type, int info_index) {
|
| }
|
|
|
| #endif
|
| -#endif // _MSC_VER
|
| +
|
| +// _xgetbv returns the value of an Intel Extended Control Register (XCR).
|
| +// Currently only XCR0 is defined by Intel so |xcr| should always be zero.
|
| +uint64 _xgetbv(uint32 xcr) {
|
| + uint32 eax, edx;
|
| +
|
| + __asm__ volatile ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (xcr));
|
| + return (static_cast<uint64>(edx) << 32) | eax;
|
| +}
|
| +
|
| +#endif // !_MSC_VER
|
| #endif // ARCH_CPU_X86_FAMILY
|
|
|
| +} // anonymous namespace
|
| +
|
| void CPU::Initialize() {
|
| #if defined(ARCH_CPU_X86_FAMILY)
|
| int cpu_info[4] = {-1};
|
| @@ -113,14 +131,24 @@ void CPU::Initialize() {
|
| type_ = (cpu_info[0] >> 12) & 0x3;
|
| ext_model_ = (cpu_info[0] >> 16) & 0xf;
|
| ext_family_ = (cpu_info[0] >> 20) & 0xff;
|
| - has_mmx_ = (cpu_info[3] & 0x00800000) != 0;
|
| - has_sse_ = (cpu_info[3] & 0x02000000) != 0;
|
| - has_sse2_ = (cpu_info[3] & 0x04000000) != 0;
|
| - has_sse3_ = (cpu_info[2] & 0x00000001) != 0;
|
| + has_mmx_ = (cpu_info[3] & 0x00800000) != 0;
|
| + has_sse_ = (cpu_info[3] & 0x02000000) != 0;
|
| + has_sse2_ = (cpu_info[3] & 0x04000000) != 0;
|
| + has_sse3_ = (cpu_info[2] & 0x00000001) != 0;
|
| has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
|
| has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
|
| has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
|
| - has_avx_ = (cpu_info[2] & 0x10000000) != 0;
|
| + has_avx_hardware_ =
|
| + (cpu_info[2] & 0x10000000) != 0;
|
| + /* AVX instructions will generate an illegal instruction exception unless
|
| + * a) they are supported by the CPU,
|
| + * b) XSAVE is supported by the CPU and
|
| + * c) XSAVE is enabled by the kernel.
|
| + * See http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled */
|
| + has_avx_ =
|
| + has_avx_hardware_ &&
|
| + (cpu_info[2] & 0x08000000) == 0x08000000 /* OSXSAVE */ &&
|
| + (_xgetbv(0) & 6) == 6 /* XSAVE enabled by kernel */;
|
| }
|
|
|
| // Get the brand string of the cpu.
|
|
|