blob: 1fd1deadef67597a3b44f41b5c73e925edbe5de8 [file] [log] [blame]
Ian Rogersd582fa42014-11-05 23:46:43 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "instruction_set_features.h"
18
19#include "base/casts.h"
20#include "utils.h"
21
22
23#include "arm/instruction_set_features_arm.h"
24#include "arm64/instruction_set_features_arm64.h"
25#include "mips/instruction_set_features_mips.h"
Andreas Gampe57b34292015-01-14 15:45:59 -080026#include "mips64/instruction_set_features_mips64.h"
Ian Rogersd582fa42014-11-05 23:46:43 -080027#include "x86/instruction_set_features_x86.h"
28#include "x86_64/instruction_set_features_x86_64.h"
29
30namespace art {
31
32const InstructionSetFeatures* InstructionSetFeatures::FromVariant(InstructionSet isa,
33 const std::string& variant,
34 std::string* error_msg) {
35 const InstructionSetFeatures* result;
36 switch (isa) {
37 case kArm:
38 case kThumb2:
39 result = ArmInstructionSetFeatures::FromVariant(variant, error_msg);
40 break;
41 case kArm64:
42 result = Arm64InstructionSetFeatures::FromVariant(variant, error_msg);
43 break;
44 case kMips:
45 result = MipsInstructionSetFeatures::FromVariant(variant, error_msg);
46 break;
Andreas Gampe57b34292015-01-14 15:45:59 -080047 case kMips64:
48 result = Mips64InstructionSetFeatures::FromVariant(variant, error_msg);
49 break;
Ian Rogersd582fa42014-11-05 23:46:43 -080050 case kX86:
51 result = X86InstructionSetFeatures::FromVariant(variant, error_msg);
52 break;
53 case kX86_64:
54 result = X86_64InstructionSetFeatures::FromVariant(variant, error_msg);
55 break;
56 default:
57 UNIMPLEMENTED(FATAL) << isa;
58 UNREACHABLE();
59 }
60 CHECK_EQ(result == nullptr, error_msg->size() != 0);
61 return result;
62}
63
64const InstructionSetFeatures* InstructionSetFeatures::FromBitmap(InstructionSet isa,
65 uint32_t bitmap) {
66 const InstructionSetFeatures* result;
67 switch (isa) {
68 case kArm:
69 case kThumb2:
70 result = ArmInstructionSetFeatures::FromBitmap(bitmap);
71 break;
72 case kArm64:
73 result = Arm64InstructionSetFeatures::FromBitmap(bitmap);
74 break;
75 case kMips:
76 result = MipsInstructionSetFeatures::FromBitmap(bitmap);
77 break;
Andreas Gampe57b34292015-01-14 15:45:59 -080078 case kMips64:
79 result = Mips64InstructionSetFeatures::FromBitmap(bitmap);
80 break;
Ian Rogersd582fa42014-11-05 23:46:43 -080081 case kX86:
82 result = X86InstructionSetFeatures::FromBitmap(bitmap);
83 break;
84 case kX86_64:
85 result = X86_64InstructionSetFeatures::FromBitmap(bitmap);
86 break;
87 default:
88 UNIMPLEMENTED(FATAL) << isa;
89 UNREACHABLE();
90 }
91 CHECK_EQ(bitmap, result->AsBitmap());
92 return result;
93}
94
95const InstructionSetFeatures* InstructionSetFeatures::FromCppDefines() {
96 const InstructionSetFeatures* result;
97 switch (kRuntimeISA) {
98 case kArm:
99 case kThumb2:
100 result = ArmInstructionSetFeatures::FromCppDefines();
101 break;
102 case kArm64:
103 result = Arm64InstructionSetFeatures::FromCppDefines();
104 break;
105 case kMips:
106 result = MipsInstructionSetFeatures::FromCppDefines();
107 break;
Andreas Gampe57b34292015-01-14 15:45:59 -0800108 case kMips64:
109 result = Mips64InstructionSetFeatures::FromCppDefines();
110 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800111 case kX86:
112 result = X86InstructionSetFeatures::FromCppDefines();
113 break;
114 case kX86_64:
115 result = X86_64InstructionSetFeatures::FromCppDefines();
116 break;
117 default:
118 UNIMPLEMENTED(FATAL) << kRuntimeISA;
119 UNREACHABLE();
120 }
121 return result;
122}
123
124
125const InstructionSetFeatures* InstructionSetFeatures::FromCpuInfo() {
126 const InstructionSetFeatures* result;
127 switch (kRuntimeISA) {
128 case kArm:
129 case kThumb2:
130 result = ArmInstructionSetFeatures::FromCpuInfo();
131 break;
132 case kArm64:
133 result = Arm64InstructionSetFeatures::FromCpuInfo();
134 break;
135 case kMips:
136 result = MipsInstructionSetFeatures::FromCpuInfo();
137 break;
Andreas Gampe57b34292015-01-14 15:45:59 -0800138 case kMips64:
139 result = Mips64InstructionSetFeatures::FromCpuInfo();
140 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800141 case kX86:
142 result = X86InstructionSetFeatures::FromCpuInfo();
143 break;
144 case kX86_64:
145 result = X86_64InstructionSetFeatures::FromCpuInfo();
146 break;
147 default:
148 UNIMPLEMENTED(FATAL) << kRuntimeISA;
149 UNREACHABLE();
150 }
151 return result;
152}
153
154const InstructionSetFeatures* InstructionSetFeatures::FromHwcap() {
155 const InstructionSetFeatures* result;
156 switch (kRuntimeISA) {
157 case kArm:
158 case kThumb2:
159 result = ArmInstructionSetFeatures::FromHwcap();
160 break;
161 case kArm64:
162 result = Arm64InstructionSetFeatures::FromHwcap();
163 break;
164 case kMips:
165 result = MipsInstructionSetFeatures::FromHwcap();
166 break;
Andreas Gampe57b34292015-01-14 15:45:59 -0800167 case kMips64:
168 result = Mips64InstructionSetFeatures::FromHwcap();
169 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800170 case kX86:
171 result = X86InstructionSetFeatures::FromHwcap();
172 break;
173 case kX86_64:
174 result = X86_64InstructionSetFeatures::FromHwcap();
175 break;
176 default:
177 UNIMPLEMENTED(FATAL) << kRuntimeISA;
178 UNREACHABLE();
179 }
180 return result;
181}
182
183const InstructionSetFeatures* InstructionSetFeatures::FromAssembly() {
184 const InstructionSetFeatures* result;
185 switch (kRuntimeISA) {
186 case kArm:
187 case kThumb2:
188 result = ArmInstructionSetFeatures::FromAssembly();
189 break;
190 case kArm64:
191 result = Arm64InstructionSetFeatures::FromAssembly();
192 break;
193 case kMips:
194 result = MipsInstructionSetFeatures::FromAssembly();
195 break;
Andreas Gampe57b34292015-01-14 15:45:59 -0800196 case kMips64:
197 result = Mips64InstructionSetFeatures::FromAssembly();
198 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800199 case kX86:
200 result = X86InstructionSetFeatures::FromAssembly();
201 break;
202 case kX86_64:
203 result = X86_64InstructionSetFeatures::FromAssembly();
204 break;
205 default:
206 UNIMPLEMENTED(FATAL) << kRuntimeISA;
207 UNREACHABLE();
208 }
209 return result;
210}
211
212const InstructionSetFeatures* InstructionSetFeatures::AddFeaturesFromString(
213 const std::string& feature_list, std::string* error_msg) const {
214 if (feature_list.empty()) {
215 *error_msg = "No instruction set features specified";
216 return nullptr;
217 }
218 std::vector<std::string> features;
219 Split(feature_list, ',', &features);
220 bool smp = smp_;
221 bool use_default = false; // Have we seen the 'default' feature?
222 bool first = false; // Is this first feature?
223 for (auto it = features.begin(); it != features.end();) {
224 if (use_default) {
225 *error_msg = "Unexpected instruction set features after 'default'";
226 return nullptr;
227 }
228 std::string feature = Trim(*it);
229 bool erase = false;
230 if (feature == "default") {
231 if (!first) {
232 use_default = true;
233 erase = true;
234 } else {
235 *error_msg = "Unexpected instruction set features before 'default'";
236 return nullptr;
237 }
238 } else if (feature == "smp") {
239 smp = true;
240 erase = true;
241 } else if (feature == "-smp") {
242 smp = false;
243 erase = true;
244 }
245 // Erase the smp feature once processed.
246 if (!erase) {
247 ++it;
248 } else {
249 it = features.erase(it);
250 }
251 first = true;
252 }
253 DCHECK_EQ(use_default, features.empty());
254 return AddFeaturesFromSplitString(smp, features, error_msg);
255}
256
257const ArmInstructionSetFeatures* InstructionSetFeatures::AsArmInstructionSetFeatures() const {
258 DCHECK_EQ(kArm, GetInstructionSet());
259 return down_cast<const ArmInstructionSetFeatures*>(this);
260}
261
262const Arm64InstructionSetFeatures* InstructionSetFeatures::AsArm64InstructionSetFeatures() const {
263 DCHECK_EQ(kArm64, GetInstructionSet());
264 return down_cast<const Arm64InstructionSetFeatures*>(this);
265}
266
267const MipsInstructionSetFeatures* InstructionSetFeatures::AsMipsInstructionSetFeatures() const {
268 DCHECK_EQ(kMips, GetInstructionSet());
269 return down_cast<const MipsInstructionSetFeatures*>(this);
270}
271
Andreas Gampe57b34292015-01-14 15:45:59 -0800272const Mips64InstructionSetFeatures* InstructionSetFeatures::AsMips64InstructionSetFeatures() const {
273 DCHECK_EQ(kMips64, GetInstructionSet());
274 return down_cast<const Mips64InstructionSetFeatures*>(this);
275}
276
Ian Rogersd582fa42014-11-05 23:46:43 -0800277const X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const {
278 DCHECK(kX86 == GetInstructionSet() || kX86_64 == GetInstructionSet());
279 return down_cast<const X86InstructionSetFeatures*>(this);
280}
281
282const X86_64InstructionSetFeatures* InstructionSetFeatures::AsX86_64InstructionSetFeatures() const {
283 DCHECK_EQ(kX86_64, GetInstructionSet());
284 return down_cast<const X86_64InstructionSetFeatures*>(this);
285}
286
287bool InstructionSetFeatures::FindVariantInArray(const char* variants[], size_t num_variants,
288 const std::string& variant) {
289 const char** begin = variants;
290 const char** end = begin + num_variants;
291 return std::find(begin, end, variant) != end;
292}
293
294std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs) {
295 os << "ISA: " << rhs.GetInstructionSet() << " Feature string: " << rhs.GetFeatureString();
296 return os;
297}
298
299} // namespace art