OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/cpu.h" | 5 #include "base/cpu.h" |
| 6 |
| 7 #if defined(ARCH_CPU_X86_FAMILY) |
| 8 #if defined(_MSC_VER) |
6 #include <intrin.h> | 9 #include <intrin.h> |
7 #include <string> | 10 #endif |
| 11 #endif |
| 12 |
| 13 #include <string.h> |
8 | 14 |
9 namespace base { | 15 namespace base { |
10 | 16 |
11 CPU::CPU() | 17 CPU::CPU() |
12 : type_(0), | 18 : type_(0), |
13 family_(0), | 19 family_(0), |
14 model_(0), | 20 model_(0), |
15 stepping_(0), | 21 stepping_(0), |
16 ext_model_(0), | 22 ext_model_(0), |
17 ext_family_(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), |
18 cpu_vendor_("unknown") { | 31 cpu_vendor_("unknown") { |
19 Initialize(); | 32 Initialize(); |
20 } | 33 } |
21 | 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 |
22 void CPU::Initialize() { | 82 void CPU::Initialize() { |
| 83 #if defined(ARCH_CPU_X86_FAMILY) |
23 int cpu_info[4] = {-1}; | 84 int cpu_info[4] = {-1}; |
24 char cpu_string[0x20]; | 85 char cpu_string[0x20]; |
25 | 86 |
26 // __cpuid with an InfoType argument of 0 returns the number of | 87 // __cpuid with an InfoType argument of 0 returns the number of |
27 // valid Ids in CPUInfo[0] and the CPU identification string in | 88 // valid Ids in CPUInfo[0] and the CPU identification string in |
28 // the other three array elements. The CPU identification string is | 89 // the other three array elements. The CPU identification string is |
29 // not in linear order. The code below arranges the information | 90 // not in linear order. The code below arranges the information |
30 // in a human readable form. | 91 // in a human readable form. |
31 // | 92 // |
32 // More info can be found here: | 93 // More info can be found here: |
33 // http://msdn.microsoft.com/en-us/library/hskdteyh.aspx | 94 // http://msdn.microsoft.com/en-us/library/hskdteyh.aspx |
34 __cpuid(cpu_info, 0); | 95 __cpuid(cpu_info, 0); |
35 int num_ids = cpu_info[0]; | 96 int num_ids = cpu_info[0]; |
36 memset(cpu_string, 0, sizeof(cpu_string)); | 97 memset(cpu_string, 0, sizeof(cpu_string)); |
37 *(reinterpret_cast<int*>(cpu_string)) = cpu_info[1]; | 98 *(reinterpret_cast<int*>(cpu_string)) = cpu_info[1]; |
38 *(reinterpret_cast<int*>(cpu_string+4)) = cpu_info[3]; | 99 *(reinterpret_cast<int*>(cpu_string+4)) = cpu_info[3]; |
39 *(reinterpret_cast<int*>(cpu_string+8)) = cpu_info[2]; | 100 *(reinterpret_cast<int*>(cpu_string+8)) = cpu_info[2]; |
40 | 101 |
41 // Interpret CPU feature information. | 102 // Interpret CPU feature information. |
42 if (num_ids > 0) { | 103 if (num_ids > 0) { |
43 __cpuid(cpu_info, 1); | 104 __cpuid(cpu_info, 1); |
44 stepping_ = cpu_info[0] & 0xf; | 105 stepping_ = cpu_info[0] & 0xf; |
45 model_ = (cpu_info[0] >> 4) & 0xf; | 106 model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0); |
46 family_ = (cpu_info[0] >> 8) & 0xf; | 107 family_ = (cpu_info[0] >> 8) & 0xf; |
47 type_ = (cpu_info[0] >> 12) & 0x3; | 108 type_ = (cpu_info[0] >> 12) & 0x3; |
48 ext_model_ = (cpu_info[0] >> 16) & 0xf; | 109 ext_model_ = (cpu_info[0] >> 16) & 0xf; |
49 ext_family_ = (cpu_info[0] >> 20) & 0xff; | 110 ext_family_ = (cpu_info[0] >> 20) & 0xff; |
50 cpu_vendor_ = cpu_string; | 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; |
51 } | 119 } |
| 120 #endif |
52 } | 121 } |
53 | 122 |
| 123 |
| 124 |
54 } // namespace base | 125 } // namespace base |
OLD | NEW |