1d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers/*
2d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * Copyright (C) 2014 The Android Open Source Project
3d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers *
4d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * Licensed under the Apache License, Version 2.0 (the "License");
5d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * you may not use this file except in compliance with the License.
6d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * You may obtain a copy of the License at
7d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers *
8d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers *      http://www.apache.org/licenses/LICENSE-2.0
9d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers *
10d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * Unless required by applicable law or agreed to in writing, software
11d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * distributed under the License is distributed on an "AS IS" BASIS,
12d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * See the License for the specific language governing permissions and
14d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * limitations under the License.
15d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers */
16d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
17d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "instruction_set_features_x86.h"
18d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
19d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include <fstream>
20d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include <sstream>
21d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
22d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/x86_64/instruction_set_features_x86_64.h"
23d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "base/stringprintf.h"
24d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "utils.h"  // For Trim.
25d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
26d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersnamespace art {
27d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
2824a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe// Feature-support arrays.
2924a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe
3024a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampestatic constexpr const char* x86_known_variants[] = {
3124a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe    "atom",
3224a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe    "silvermont",
3324a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe};
3424a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe
3524a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampestatic constexpr const char* x86_variants_with_ssse3[] = {
3624a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe    "atom",
3724a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe    "silvermont",
3824a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe};
3924a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe
4024a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampestatic constexpr const char* x86_variants_with_sse4_1[] = {
4124a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe    "silvermont",
4224a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe};
4324a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe
4424a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampestatic constexpr const char* x86_variants_with_sse4_2[] = {
4524a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe    "silvermont",
4624a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe};
4724a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe
4817077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendellstatic constexpr const char* x86_variants_prefer_locked_add_sync[] = {
4917077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    "atom",
5017077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    "silvermont",
5117077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell};
5217077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell
533f67e692860d281858485d48a4f1f81b907f1444Aart Bikstatic constexpr const char* x86_variants_with_popcnt[] = {
543f67e692860d281858485d48a4f1f81b907f1444Aart Bik    "silvermont",
553f67e692860d281858485d48a4f1f81b907f1444Aart Bik};
563f67e692860d281858485d48a4f1f81b907f1444Aart Bik
57d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst X86InstructionSetFeatures* X86InstructionSetFeatures::FromVariant(
58ca71458862be8505330b7fd5649a062f31d143dcAndreas Gampe    const std::string& variant, std::string* error_msg ATTRIBUTE_UNUSED,
59d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    bool x86_64) {
60d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool smp = true;  // Conservative default.
61d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSSE3 = FindVariantInArray(x86_variants_with_ssse3, arraysize(x86_variants_with_ssse3),
62d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers                                      variant);
6324a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe  bool has_SSE4_1 = FindVariantInArray(x86_variants_with_sse4_1,
6424a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe                                       arraysize(x86_variants_with_sse4_1),
6524a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe                                       variant);
6624a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe  bool has_SSE4_2 = FindVariantInArray(x86_variants_with_sse4_2,
6724a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe                                       arraysize(x86_variants_with_sse4_2),
6824a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe                                       variant);
69d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_AVX = false;
70d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_AVX2 = false;
7124a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe
7217077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  bool prefers_locked_add = FindVariantInArray(x86_variants_prefer_locked_add_sync,
7317077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell                                               arraysize(x86_variants_prefer_locked_add_sync),
7417077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell                                               variant);
7517077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell
763f67e692860d281858485d48a4f1f81b907f1444Aart Bik  bool has_POPCNT = FindVariantInArray(x86_variants_with_popcnt,
773f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                       arraysize(x86_variants_with_popcnt),
783f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                       variant);
793f67e692860d281858485d48a4f1f81b907f1444Aart Bik
803f67e692860d281858485d48a4f1f81b907f1444Aart Bik  // Verify that variant is known.
8124a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe  bool known_variant = FindVariantInArray(x86_known_variants, arraysize(x86_known_variants),
8224a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe                                          variant);
83d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (!known_variant && variant != "default") {
84d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    LOG(WARNING) << "Unexpected CPU variant for X86 using defaults: " << variant;
85d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
86d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
87d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (x86_64) {
88d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    return new X86_64InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2, has_AVX,
893f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                            has_AVX2, prefers_locked_add, has_POPCNT);
90d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
91d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    return new X86InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2, has_AVX,
923f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                            has_AVX2, prefers_locked_add, has_POPCNT);
93d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
94d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
95d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
96d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst X86InstructionSetFeatures* X86InstructionSetFeatures::FromBitmap(uint32_t bitmap,
97d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers                                                                       bool x86_64) {
98d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool smp = (bitmap & kSmpBitfield) != 0;
99d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSSE3 = (bitmap & kSsse3Bitfield) != 0;
100d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSE4_1 = (bitmap & kSse4_1Bitfield) != 0;
101d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSE4_2 = (bitmap & kSse4_2Bitfield) != 0;
102d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_AVX = (bitmap & kAvxBitfield) != 0;
103d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_AVX2 = (bitmap & kAvxBitfield) != 0;
10417077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  bool prefers_locked_add = (bitmap & kPrefersLockedAdd) != 0;
1053f67e692860d281858485d48a4f1f81b907f1444Aart Bik  bool has_POPCNT = (bitmap & kPopCntBitfield) != 0;
106d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (x86_64) {
10717077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    return new X86_64InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2,
1083f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                            has_AVX, has_AVX2, prefers_locked_add,
1093f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                            has_POPCNT);
110d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
11117077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    return new X86InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2,
1123f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                         has_AVX, has_AVX2, prefers_locked_add,
1133f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                         has_POPCNT);
114d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
115d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
116d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
117d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst X86InstructionSetFeatures* X86InstructionSetFeatures::FromCppDefines(bool x86_64) {
118d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool smp = true;
119d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
120d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#ifndef __SSSE3__
121d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_SSSE3 = false;
122d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#else
123d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_SSSE3 = true;
124d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#endif
125d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
126d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#ifndef __SSE4_1__
127d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_SSE4_1 = false;
128d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#else
129d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_SSE4_1 = true;
130d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#endif
131d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
132d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#ifndef __SSE4_2__
133d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_SSE4_2 = false;
134d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#else
135d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_SSE4_2 = true;
136d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#endif
137d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
138d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#ifndef __AVX__
139d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_AVX = false;
140d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#else
141d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_AVX = true;
142d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#endif
143d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
144d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#ifndef __AVX2__
145d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_AVX2 = false;
146d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#else
147d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const bool has_AVX2 = true;
148d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#endif
149d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
15017077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  // No #define for memory synchronization preference.
15117077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  const bool prefers_locked_add = false;
15217077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell
153715d06b4498af3d4661e0090d606641d65040a08Aart Bik#ifndef __POPCNT__
1543f67e692860d281858485d48a4f1f81b907f1444Aart Bik  const bool has_POPCNT = false;
155715d06b4498af3d4661e0090d606641d65040a08Aart Bik#else
156715d06b4498af3d4661e0090d606641d65040a08Aart Bik  const bool has_POPCNT = true;
157715d06b4498af3d4661e0090d606641d65040a08Aart Bik#endif
1583f67e692860d281858485d48a4f1f81b907f1444Aart Bik
159d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (x86_64) {
16017077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    return new X86_64InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2, has_AVX,
1613f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                            has_AVX2, prefers_locked_add, has_POPCNT);
162d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
163d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    return new X86InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2, has_AVX,
1643f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                         has_AVX2, prefers_locked_add, has_POPCNT);
165d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
166d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
167d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
168d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst X86InstructionSetFeatures* X86InstructionSetFeatures::FromCpuInfo(bool x86_64) {
169d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  // Look in /proc/cpuinfo for features we need.  Only use this when we can guarantee that
170d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  // the kernel puts the appropriate feature flags in here.  Sometimes it doesn't.
171d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool smp = false;
172d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSSE3 = false;
173d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSE4_1 = false;
174d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSE4_2 = false;
175d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_AVX = false;
176d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_AVX2 = false;
17717077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  // No cpuinfo for memory synchronization preference.
17817077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  const bool prefers_locked_add = false;
1793f67e692860d281858485d48a4f1f81b907f1444Aart Bik  bool has_POPCNT = false;
180d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
181d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  std::ifstream in("/proc/cpuinfo");
182d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (!in.fail()) {
183d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    while (!in.eof()) {
184d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      std::string line;
185d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      std::getline(in, line);
186d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      if (!in.eof()) {
187d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        LOG(INFO) << "cpuinfo line: " << line;
188d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        if (line.find("flags") != std::string::npos) {
189d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          LOG(INFO) << "found flags";
190d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          if (line.find("ssse3") != std::string::npos) {
191d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers            has_SSSE3 = true;
192d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          }
193d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          if (line.find("sse4_1") != std::string::npos) {
194d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers            has_SSE4_1 = true;
195d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          }
196d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          if (line.find("sse4_2") != std::string::npos) {
197d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers            has_SSE4_2 = true;
198d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          }
199d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          if (line.find("avx") != std::string::npos) {
200d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers            has_AVX = true;
201d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          }
202d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          if (line.find("avx2") != std::string::npos) {
203d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers            has_AVX2 = true;
204d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          }
2053f67e692860d281858485d48a4f1f81b907f1444Aart Bik          if (line.find("popcnt") != std::string::npos) {
2063f67e692860d281858485d48a4f1f81b907f1444Aart Bik            has_POPCNT = true;
2073f67e692860d281858485d48a4f1f81b907f1444Aart Bik          }
208d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        } else if (line.find("processor") != std::string::npos &&
209d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers            line.find(": 1") != std::string::npos) {
210d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          smp = true;
211d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        }
212d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      }
213d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    }
214d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    in.close();
215d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
216d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    LOG(ERROR) << "Failed to open /proc/cpuinfo";
217d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
218d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (x86_64) {
21917077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    return new X86_64InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2, has_AVX,
2203f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                            has_AVX2, prefers_locked_add, has_POPCNT);
221d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
222d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    return new X86InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2, has_AVX,
2233f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                         has_AVX2, prefers_locked_add, has_POPCNT);
224d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
225d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
226d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
227d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst X86InstructionSetFeatures* X86InstructionSetFeatures::FromHwcap(bool x86_64) {
228d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  UNIMPLEMENTED(WARNING);
229d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return FromCppDefines(x86_64);
230d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
231d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
232d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst X86InstructionSetFeatures* X86InstructionSetFeatures::FromAssembly(bool x86_64) {
233d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  UNIMPLEMENTED(WARNING);
234d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return FromCppDefines(x86_64);
235d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
236d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
237d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersbool X86InstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
238d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (GetInstructionSet() != other->GetInstructionSet()) {
239d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    return false;
240d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
241d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const X86InstructionSetFeatures* other_as_x86 = other->AsX86InstructionSetFeatures();
242d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return (IsSmp() == other->IsSmp()) &&
243d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (has_SSSE3_ == other_as_x86->has_SSSE3_) &&
244d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (has_SSE4_1_ == other_as_x86->has_SSE4_1_) &&
245d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (has_SSE4_2_ == other_as_x86->has_SSE4_2_) &&
246d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (has_AVX_ == other_as_x86->has_AVX_) &&
24717077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell      (has_AVX2_ == other_as_x86->has_AVX2_) &&
2483f67e692860d281858485d48a4f1f81b907f1444Aart Bik      (prefers_locked_add_ == other_as_x86->prefers_locked_add_) &&
2493f67e692860d281858485d48a4f1f81b907f1444Aart Bik      (has_POPCNT_ == other_as_x86->has_POPCNT_);
250d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
251d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
252d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersuint32_t X86InstructionSetFeatures::AsBitmap() const {
253d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return (IsSmp() ? kSmpBitfield : 0) |
254d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (has_SSSE3_ ? kSsse3Bitfield : 0) |
255d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (has_SSE4_1_ ? kSse4_1Bitfield : 0) |
256d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (has_SSE4_2_ ? kSse4_2Bitfield : 0) |
257d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      (has_AVX_ ? kAvxBitfield : 0) |
25817077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell      (has_AVX2_ ? kAvx2Bitfield : 0) |
2593f67e692860d281858485d48a4f1f81b907f1444Aart Bik      (prefers_locked_add_ ? kPrefersLockedAdd : 0) |
2603f67e692860d281858485d48a4f1f81b907f1444Aart Bik      (has_POPCNT_ ? kPopCntBitfield : 0);
261d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
262d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
263d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersstd::string X86InstructionSetFeatures::GetFeatureString() const {
264d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  std::string result;
265d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (IsSmp()) {
266d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += "smp";
267d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
268d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += "-smp";
269d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
270d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (has_SSSE3_) {
271d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",ssse3";
272d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
273d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",-ssse3";
274d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
275d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (has_SSE4_1_) {
276d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",sse4.1";
277d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
278d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",-sse4.1";
279d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
280d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (has_SSE4_2_) {
281d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",sse4.2";
282d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
283d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",-sse4.2";
284d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
285d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (has_AVX_) {
286d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",avx";
287d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
288d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",-avx";
289d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
290d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (has_AVX2_) {
291d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",avx2";
292d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
293d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    result += ",-avx2";
294d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
29517077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  if (prefers_locked_add_) {
29617077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    result += ",lock_add";
29717077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  } else {
29817077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    result += ",-lock_add";
29917077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  }
3003f67e692860d281858485d48a4f1f81b907f1444Aart Bik  if (has_POPCNT_) {
3013f67e692860d281858485d48a4f1f81b907f1444Aart Bik    result += ",popcnt";
3023f67e692860d281858485d48a4f1f81b907f1444Aart Bik  } else {
3033f67e692860d281858485d48a4f1f81b907f1444Aart Bik    result += ",-popcnt";
3043f67e692860d281858485d48a4f1f81b907f1444Aart Bik  }
305d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return result;
306d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
307d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
308d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst InstructionSetFeatures* X86InstructionSetFeatures::AddFeaturesFromSplitString(
309d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    const bool smp, const std::vector<std::string>& features, bool x86_64,
310d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    std::string* error_msg) const {
311d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSSE3 = has_SSSE3_;
312d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSE4_1 = has_SSE4_1_;
313d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_SSE4_2 = has_SSE4_2_;
314d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_AVX = has_AVX_;
315d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool has_AVX2 = has_AVX2_;
31617077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell  bool prefers_locked_add = prefers_locked_add_;
3173f67e692860d281858485d48a4f1f81b907f1444Aart Bik  bool has_POPCNT = has_POPCNT_;
318d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  for (auto i = features.begin(); i != features.end(); i++) {
319d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    std::string feature = Trim(*i);
320d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    if (feature == "ssse3") {
321d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_SSSE3 = true;
322d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "-ssse3") {
323d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_SSSE3 = false;
324d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "sse4.1") {
325d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_SSE4_1 = true;
326d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "-sse4.1") {
327d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_SSE4_1 = false;
328d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "sse4.2") {
329d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_SSE4_2 = true;
330d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "-sse4.2") {
331d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_SSE4_2 = false;
332d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "avx") {
333d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_AVX = true;
334d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "-avx") {
335d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_AVX = false;
336d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "avx2") {
337d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_AVX2 = true;
338d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "-avx2") {
339d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      has_AVX2 = false;
34017077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    } else if (feature == "lock_add") {
34117077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell      prefers_locked_add = true;
34217077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell    } else if (feature == "-lock_add") {
34317077d888a6752a2e5f8161eee1b2c3285783d12Mark P Mendell      prefers_locked_add = false;
3443f67e692860d281858485d48a4f1f81b907f1444Aart Bik    } else if (feature == "popcnt") {
3453f67e692860d281858485d48a4f1f81b907f1444Aart Bik      has_POPCNT = true;
3463f67e692860d281858485d48a4f1f81b907f1444Aart Bik    } else if (feature == "-popcnt") {
3473f67e692860d281858485d48a4f1f81b907f1444Aart Bik      has_POPCNT = false;
348d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else {
349d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      *error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str());
350d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      return nullptr;
351d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    }
352d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
353d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (x86_64) {
354d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    return new X86_64InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2, has_AVX,
3553f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                            has_AVX2, prefers_locked_add, has_POPCNT);
356d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  } else {
357d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    return new X86InstructionSetFeatures(smp, has_SSSE3, has_SSE4_1, has_SSE4_2, has_AVX,
3583f67e692860d281858485d48a4f1f81b907f1444Aart Bik                                         has_AVX2, prefers_locked_add, has_POPCNT);
359d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
360d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
361d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
362d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}  // namespace art
363