1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/cpu.h" 6 7 #if defined(ARCH_CPU_X86_FAMILY) 8 #if defined(_MSC_VER) 9 #include <intrin.h> 10 #endif 11 #endif 12 13 #include <string.h> 14 15 namespace base { 16 17 CPU::CPU() 18 : type_(0), 19 family_(0), 20 model_(0), 21 stepping_(0), 22 ext_model_(0), 23 ext_family_(0), 24 has_mmx_(false), 25 has_sse_(false), 26 has_sse2_(false), 27 has_sse3_(false), 28 has_ssse3_(false), 29 has_sse41_(false), 30 has_sse42_(false), 31 cpu_vendor_("unknown") { 32 Initialize(); 33 } 34 35 #if defined(ARCH_CPU_X86_FAMILY) 36 #ifndef _MSC_VER 37 38 #if defined(__pic__) && defined(__i386__) 39 40 void __cpuid(int cpu_info[4], int info_type) { 41 __asm__ volatile ( 42 "mov %%ebx, %%edi\n" 43 "cpuid\n" 44 "xchg %%edi, %%ebx\n" 45 : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) 46 : "a"(info_type) 47 ); 48 } 49 50 void __cpuidex(int cpu_info[4], int info_type, int info_index) { 51 __asm__ volatile ( 52 "mov %%ebx, %%edi\n" 53 "cpuid\n" 54 "xchg %%edi, %%ebx\n" 55 : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) 56 : "a"(info_type), "c"(info_index) 57 ); 58 } 59 60 #else 61 62 void __cpuid(int cpu_info[4], int info_type) { 63 __asm__ volatile ( 64 "cpuid \n\t" 65 : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) 66 : "a"(info_type) 67 ); 68 } 69 70 void __cpuidex(int cpu_info[4], int info_type, int info_index) { 71 __asm__ volatile ( 72 "cpuid \n\t" 73 : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3]) 74 : "a"(info_type), "c"(info_index) 75 ); 76 } 77 78 #endif 79 #endif // _MSC_VER 80 #endif // ARCH_CPU_X86_FAMILY 81 82 void CPU::Initialize() { 83 #if defined(ARCH_CPU_X86_FAMILY) 84 int cpu_info[4] = {-1}; 85 char cpu_string[0x20]; 86 87 // __cpuid with an InfoType argument of 0 returns the number of 88 // valid Ids in CPUInfo[0] and the CPU identification string in 89 // the other three array elements. The CPU identification string is 90 // not in linear order. The code below arranges the information 91 // in a human readable form. 92 // 93 // More info can be found here: 94 // http://msdn.microsoft.com/en-us/library/hskdteyh.aspx 95 __cpuid(cpu_info, 0); 96 int num_ids = cpu_info[0]; 97 memset(cpu_string, 0, sizeof(cpu_string)); 98 *(reinterpret_cast<int*>(cpu_string)) = cpu_info[1]; 99 *(reinterpret_cast<int*>(cpu_string+4)) = cpu_info[3]; 100 *(reinterpret_cast<int*>(cpu_string+8)) = cpu_info[2]; 101 102 // Interpret CPU feature information. 103 if (num_ids > 0) { 104 __cpuid(cpu_info, 1); 105 stepping_ = cpu_info[0] & 0xf; 106 model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0); 107 family_ = (cpu_info[0] >> 8) & 0xf; 108 type_ = (cpu_info[0] >> 12) & 0x3; 109 ext_model_ = (cpu_info[0] >> 16) & 0xf; 110 ext_family_ = (cpu_info[0] >> 20) & 0xff; 111 cpu_vendor_ = cpu_string; 112 has_mmx_ = (cpu_info[3] & 0x00800000) != 0; 113 has_sse_ = (cpu_info[3] & 0x02000000) != 0; 114 has_sse2_ = (cpu_info[3] & 0x04000000) != 0; 115 has_sse3_ = (cpu_info[2] & 0x00000001) != 0; 116 has_ssse3_ = (cpu_info[2] & 0x00000200) != 0; 117 has_sse41_ = (cpu_info[2] & 0x00080000) != 0; 118 has_sse42_ = (cpu_info[2] & 0x00100000) != 0; 119 } 120 #endif 121 } 122 123 } // namespace base 124