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