• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CPU()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 
__cpuid(int cpu_info[4],int info_type)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 
__cpuidex(int cpu_info[4],int info_type,int info_index)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 
__cpuid(int cpu_info[4],int info_type)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 
__cpuidex(int cpu_info[4],int info_type,int info_index)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 
Initialize()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