1d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers/*
2d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers * Copyright (C) 2011 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.h"
18d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
19d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "base/casts.h"
20d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "utils.h"
21d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
22d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
23d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arm/instruction_set_features_arm.h"
24d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arm64/instruction_set_features_arm64.h"
25d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "mips/instruction_set_features_mips.h"
2657b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe#include "mips64/instruction_set_features_mips64.h"
27d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "x86/instruction_set_features_x86.h"
28d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "x86_64/instruction_set_features_x86_64.h"
29d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
30d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersnamespace art {
31d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
32d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst InstructionSetFeatures* InstructionSetFeatures::FromVariant(InstructionSet isa,
33d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers                                                                  const std::string& variant,
34d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers                                                                  std::string* error_msg) {
35d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const InstructionSetFeatures* result;
36d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  switch (isa) {
37d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm:
38d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kThumb2:
39d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = ArmInstructionSetFeatures::FromVariant(variant, error_msg);
40d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
41d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm64:
42d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = Arm64InstructionSetFeatures::FromVariant(variant, error_msg);
43d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
44d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kMips:
45d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = MipsInstructionSetFeatures::FromVariant(variant, error_msg);
46d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
4757b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe    case kMips64:
4857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      result = Mips64InstructionSetFeatures::FromVariant(variant, error_msg);
4957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      break;
50d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86:
51d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86InstructionSetFeatures::FromVariant(variant, error_msg);
52d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
53d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86_64:
54d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86_64InstructionSetFeatures::FromVariant(variant, error_msg);
55d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
56d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    default:
57d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNIMPLEMENTED(FATAL) << isa;
58d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNREACHABLE();
59d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
60d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  CHECK_EQ(result == nullptr, error_msg->size() != 0);
61d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return result;
62d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
63d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
64d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst InstructionSetFeatures* InstructionSetFeatures::FromBitmap(InstructionSet isa,
65d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers                                                                 uint32_t bitmap) {
66d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const InstructionSetFeatures* result;
67d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  switch (isa) {
68d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm:
69d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kThumb2:
70d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = ArmInstructionSetFeatures::FromBitmap(bitmap);
71d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
72d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm64:
73d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = Arm64InstructionSetFeatures::FromBitmap(bitmap);
74d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
75d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kMips:
76d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = MipsInstructionSetFeatures::FromBitmap(bitmap);
77d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
7857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe    case kMips64:
7957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      result = Mips64InstructionSetFeatures::FromBitmap(bitmap);
8057b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      break;
81d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86:
82d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86InstructionSetFeatures::FromBitmap(bitmap);
83d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
84d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86_64:
85d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86_64InstructionSetFeatures::FromBitmap(bitmap);
86d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
87d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    default:
88d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNIMPLEMENTED(FATAL) << isa;
89d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNREACHABLE();
90d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
91d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  CHECK_EQ(bitmap, result->AsBitmap());
92d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return result;
93d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
94d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
95d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst InstructionSetFeatures* InstructionSetFeatures::FromCppDefines() {
96d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const InstructionSetFeatures* result;
97d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  switch (kRuntimeISA) {
98d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm:
99d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kThumb2:
100d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = ArmInstructionSetFeatures::FromCppDefines();
101d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
102d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm64:
103d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = Arm64InstructionSetFeatures::FromCppDefines();
104d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
105d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kMips:
106d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = MipsInstructionSetFeatures::FromCppDefines();
107d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
10857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe    case kMips64:
10957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      result = Mips64InstructionSetFeatures::FromCppDefines();
11057b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      break;
111d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86:
112d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86InstructionSetFeatures::FromCppDefines();
113d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
114d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86_64:
115d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86_64InstructionSetFeatures::FromCppDefines();
116d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
117d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    default:
118d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNIMPLEMENTED(FATAL) << kRuntimeISA;
119d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNREACHABLE();
120d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
121d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return result;
122d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
123d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
124d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
125d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst InstructionSetFeatures* InstructionSetFeatures::FromCpuInfo() {
126d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const InstructionSetFeatures* result;
127d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  switch (kRuntimeISA) {
128d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm:
129d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kThumb2:
130d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = ArmInstructionSetFeatures::FromCpuInfo();
131d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
132d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm64:
133d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = Arm64InstructionSetFeatures::FromCpuInfo();
134d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
135d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kMips:
136d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = MipsInstructionSetFeatures::FromCpuInfo();
137d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
13857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe    case kMips64:
13957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      result = Mips64InstructionSetFeatures::FromCpuInfo();
14057b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      break;
141d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86:
142d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86InstructionSetFeatures::FromCpuInfo();
143d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
144d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86_64:
145d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86_64InstructionSetFeatures::FromCpuInfo();
146d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
147d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    default:
148d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNIMPLEMENTED(FATAL) << kRuntimeISA;
149d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNREACHABLE();
150d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
151d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return result;
152d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
153d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
154d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst InstructionSetFeatures* InstructionSetFeatures::FromHwcap() {
155d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const InstructionSetFeatures* result;
156d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  switch (kRuntimeISA) {
157d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm:
158d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kThumb2:
159d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = ArmInstructionSetFeatures::FromHwcap();
160d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
161d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm64:
162d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = Arm64InstructionSetFeatures::FromHwcap();
163d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
164d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kMips:
165d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = MipsInstructionSetFeatures::FromHwcap();
166d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
16757b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe    case kMips64:
16857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      result = Mips64InstructionSetFeatures::FromHwcap();
16957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      break;
170d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86:
171d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86InstructionSetFeatures::FromHwcap();
172d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
173d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86_64:
174d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86_64InstructionSetFeatures::FromHwcap();
175d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
176d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    default:
177d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNIMPLEMENTED(FATAL) << kRuntimeISA;
178d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNREACHABLE();
179d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
180d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return result;
181d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
182d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
183d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst InstructionSetFeatures* InstructionSetFeatures::FromAssembly() {
184d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  const InstructionSetFeatures* result;
185d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  switch (kRuntimeISA) {
186d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm:
187d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kThumb2:
188d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = ArmInstructionSetFeatures::FromAssembly();
189d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
190d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kArm64:
191d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = Arm64InstructionSetFeatures::FromAssembly();
192d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
193d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kMips:
194d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = MipsInstructionSetFeatures::FromAssembly();
195d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
19657b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe    case kMips64:
19757b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      result = Mips64InstructionSetFeatures::FromAssembly();
19857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe      break;
199d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86:
200d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86InstructionSetFeatures::FromAssembly();
201d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
202d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    case kX86_64:
203d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      result = X86_64InstructionSetFeatures::FromAssembly();
204d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      break;
205d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    default:
206d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNIMPLEMENTED(FATAL) << kRuntimeISA;
207d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      UNREACHABLE();
208d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
209d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return result;
210d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
211d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
212d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst InstructionSetFeatures* InstructionSetFeatures::AddFeaturesFromString(
213d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    const std::string& feature_list, std::string* error_msg) const {
214d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  if (feature_list.empty()) {
215d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    *error_msg = "No instruction set features specified";
216d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    return nullptr;
217d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
218d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  std::vector<std::string> features;
219d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  Split(feature_list, ',', &features);
220d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool smp = smp_;
221d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool use_default = false;  // Have we seen the 'default' feature?
222d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  bool first = false;  // Is this first feature?
223d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  for (auto it = features.begin(); it != features.end();) {
224d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    if (use_default) {
225d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      *error_msg = "Unexpected instruction set features after 'default'";
226d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      return nullptr;
227d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    }
228d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    std::string feature = Trim(*it);
229d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    bool erase = false;
230d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    if (feature == "default") {
231d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      if (!first) {
232d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        use_default = true;
233d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        erase = true;
234d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      } else {
235d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        *error_msg = "Unexpected instruction set features before 'default'";
236d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers        return nullptr;
237d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      }
238d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "smp") {
239d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      smp = true;
240d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      erase = true;
241d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else if (feature == "-smp") {
242d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      smp = false;
243d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      erase = true;
244d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    }
245d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    // Erase the smp feature once processed.
246d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    if (!erase) {
247d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      ++it;
248d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    } else {
249d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers      it = features.erase(it);
250d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    }
251d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers    first = true;
252d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  }
253a7d38fc6702d2a763e8187b4773d02b63b3229acGoran Jakovljevic  // Expectation: "default" is standalone, no other flags. But an empty features vector after
254a7d38fc6702d2a763e8187b4773d02b63b3229acGoran Jakovljevic  // processing can also come along if the handled flags (at the moment only smp) are the only
255a7d38fc6702d2a763e8187b4773d02b63b3229acGoran Jakovljevic  // ones in the list. So logically, we check "default -> features.empty."
256a7d38fc6702d2a763e8187b4773d02b63b3229acGoran Jakovljevic  DCHECK(!use_default || features.empty());
257a7d38fc6702d2a763e8187b4773d02b63b3229acGoran Jakovljevic
258d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return AddFeaturesFromSplitString(smp, features, error_msg);
259d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
260d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
261d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst ArmInstructionSetFeatures* InstructionSetFeatures::AsArmInstructionSetFeatures() const {
262d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  DCHECK_EQ(kArm, GetInstructionSet());
263d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return down_cast<const ArmInstructionSetFeatures*>(this);
264d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
265d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
266d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst Arm64InstructionSetFeatures* InstructionSetFeatures::AsArm64InstructionSetFeatures() const {
267d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  DCHECK_EQ(kArm64, GetInstructionSet());
268d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return down_cast<const Arm64InstructionSetFeatures*>(this);
269d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
270d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
271d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst MipsInstructionSetFeatures* InstructionSetFeatures::AsMipsInstructionSetFeatures() const {
272d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  DCHECK_EQ(kMips, GetInstructionSet());
273d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return down_cast<const MipsInstructionSetFeatures*>(this);
274d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
275d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
27657b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampeconst Mips64InstructionSetFeatures* InstructionSetFeatures::AsMips64InstructionSetFeatures() const {
27757b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe  DCHECK_EQ(kMips64, GetInstructionSet());
27857b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe  return down_cast<const Mips64InstructionSetFeatures*>(this);
27957b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe}
28057b34294758e9c00993913ebe43c7ee4698a5cc6Andreas Gampe
281d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const {
282d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  DCHECK(kX86 == GetInstructionSet() || kX86_64 == GetInstructionSet());
283d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return down_cast<const X86InstructionSetFeatures*>(this);
284d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
285d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
286d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersconst X86_64InstructionSetFeatures* InstructionSetFeatures::AsX86_64InstructionSetFeatures() const {
287d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  DCHECK_EQ(kX86_64, GetInstructionSet());
288d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return down_cast<const X86_64InstructionSetFeatures*>(this);
289d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
290d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
29124a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampebool InstructionSetFeatures::FindVariantInArray(const char* const variants[], size_t num_variants,
292d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers                                                const std::string& variant) {
29324a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe  const char* const * begin = variants;
29424a05f449a6b4b0e4944c2055f0c7490d6a09861Andreas Gampe  const char* const * end = begin + num_variants;
295d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return std::find(begin, end, variant) != end;
296d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
297d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
298d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogersstd::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs) {
299d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  os << "ISA: " << rhs.GetInstructionSet() << " Feature string: " << rhs.GetFeatureString();
300d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers  return os;
301d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}
302d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
303d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers}  // namespace art
304