blob: b32391f6b0b0a35e07fc7b7ba3c262c58a59ffc8 [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
Andreas Gampe0415b4e2015-01-06 15:17:07 -080032std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromVariant(
33 InstructionSet isa, const std::string& variant, std::string* error_msg) {
34 std::unique_ptr<const InstructionSetFeatures> result;
Ian Rogersd582fa42014-11-05 23:46:43 -080035 switch (isa) {
36 case kArm:
37 case kThumb2:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080038 result.reset(ArmInstructionSetFeatures::FromVariant(variant, error_msg).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080039 break;
40 case kArm64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080041 result.reset(Arm64InstructionSetFeatures::FromVariant(variant, error_msg).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080042 break;
43 case kMips:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080044 result.reset(MipsInstructionSetFeatures::FromVariant(variant, error_msg).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080045 break;
Andreas Gampe57b34292015-01-14 15:45:59 -080046 case kMips64:
47 result = Mips64InstructionSetFeatures::FromVariant(variant, error_msg);
48 break;
Ian Rogersd582fa42014-11-05 23:46:43 -080049 case kX86:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080050 result.reset(X86InstructionSetFeatures::FromVariant(variant, error_msg).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080051 break;
52 case kX86_64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080053 result.reset(X86_64InstructionSetFeatures::FromVariant(variant, error_msg).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080054 break;
55 default:
56 UNIMPLEMENTED(FATAL) << isa;
57 UNREACHABLE();
58 }
59 CHECK_EQ(result == nullptr, error_msg->size() != 0);
60 return result;
61}
62
Andreas Gampe0415b4e2015-01-06 15:17:07 -080063std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromBitmap(InstructionSet isa,
64 uint32_t bitmap) {
65 std::unique_ptr<const InstructionSetFeatures> result;
Ian Rogersd582fa42014-11-05 23:46:43 -080066 switch (isa) {
67 case kArm:
68 case kThumb2:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080069 result.reset(ArmInstructionSetFeatures::FromBitmap(bitmap).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080070 break;
71 case kArm64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080072 result.reset(Arm64InstructionSetFeatures::FromBitmap(bitmap).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080073 break;
74 case kMips:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080075 result.reset(MipsInstructionSetFeatures::FromBitmap(bitmap).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080076 break;
Andreas Gampe57b34292015-01-14 15:45:59 -080077 case kMips64:
78 result = Mips64InstructionSetFeatures::FromBitmap(bitmap);
79 break;
Ian Rogersd582fa42014-11-05 23:46:43 -080080 case kX86:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080081 result.reset(X86InstructionSetFeatures::FromBitmap(bitmap).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080082 break;
83 case kX86_64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080084 result.reset(X86_64InstructionSetFeatures::FromBitmap(bitmap).release());
Ian Rogersd582fa42014-11-05 23:46:43 -080085 break;
86 default:
87 UNIMPLEMENTED(FATAL) << isa;
88 UNREACHABLE();
89 }
90 CHECK_EQ(bitmap, result->AsBitmap());
91 return result;
92}
93
Andreas Gampe0415b4e2015-01-06 15:17:07 -080094std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCppDefines() {
95 std::unique_ptr<const InstructionSetFeatures> result;
Ian Rogersd582fa42014-11-05 23:46:43 -080096 switch (kRuntimeISA) {
97 case kArm:
98 case kThumb2:
Andreas Gampe0415b4e2015-01-06 15:17:07 -080099 result.reset(ArmInstructionSetFeatures::FromCppDefines().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800100 break;
101 case kArm64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800102 result.reset(Arm64InstructionSetFeatures::FromCppDefines().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800103 break;
104 case kMips:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800105 result.reset(MipsInstructionSetFeatures::FromCppDefines().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800106 break;
Andreas Gampe57b34292015-01-14 15:45:59 -0800107 case kMips64:
108 result = Mips64InstructionSetFeatures::FromCppDefines();
109 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800110 case kX86:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800111 result.reset(X86InstructionSetFeatures::FromCppDefines().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800112 break;
113 case kX86_64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800114 result.reset(X86_64InstructionSetFeatures::FromCppDefines().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800115 break;
116 default:
117 UNIMPLEMENTED(FATAL) << kRuntimeISA;
118 UNREACHABLE();
119 }
120 return result;
121}
122
123
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800124std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCpuInfo() {
125 std::unique_ptr<const InstructionSetFeatures> result;
Ian Rogersd582fa42014-11-05 23:46:43 -0800126 switch (kRuntimeISA) {
127 case kArm:
128 case kThumb2:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800129 result.reset(ArmInstructionSetFeatures::FromCpuInfo().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800130 break;
131 case kArm64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800132 result.reset(Arm64InstructionSetFeatures::FromCpuInfo().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800133 break;
134 case kMips:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800135 result.reset(MipsInstructionSetFeatures::FromCpuInfo().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800136 break;
Andreas Gampe57b34292015-01-14 15:45:59 -0800137 case kMips64:
138 result = Mips64InstructionSetFeatures::FromCpuInfo();
139 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800140 case kX86:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800141 result.reset(X86InstructionSetFeatures::FromCpuInfo().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800142 break;
143 case kX86_64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800144 result.reset(X86_64InstructionSetFeatures::FromCpuInfo().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800145 break;
146 default:
147 UNIMPLEMENTED(FATAL) << kRuntimeISA;
148 UNREACHABLE();
149 }
150 return result;
151}
152
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800153std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromHwcap() {
154 std::unique_ptr<const InstructionSetFeatures> result;
Ian Rogersd582fa42014-11-05 23:46:43 -0800155 switch (kRuntimeISA) {
156 case kArm:
157 case kThumb2:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800158 result.reset(ArmInstructionSetFeatures::FromHwcap().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800159 break;
160 case kArm64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800161 result.reset(Arm64InstructionSetFeatures::FromHwcap().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800162 break;
163 case kMips:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800164 result.reset(MipsInstructionSetFeatures::FromHwcap().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800165 break;
Andreas Gampe57b34292015-01-14 15:45:59 -0800166 case kMips64:
167 result = Mips64InstructionSetFeatures::FromHwcap();
168 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800169 case kX86:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800170 result.reset(X86InstructionSetFeatures::FromHwcap().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800171 break;
172 case kX86_64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800173 result.reset(X86_64InstructionSetFeatures::FromHwcap().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800174 break;
175 default:
176 UNIMPLEMENTED(FATAL) << kRuntimeISA;
177 UNREACHABLE();
178 }
179 return result;
180}
181
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800182std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromAssembly() {
183 std::unique_ptr<const InstructionSetFeatures> result;
Ian Rogersd582fa42014-11-05 23:46:43 -0800184 switch (kRuntimeISA) {
185 case kArm:
186 case kThumb2:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800187 result.reset(ArmInstructionSetFeatures::FromAssembly().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800188 break;
189 case kArm64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800190 result.reset(Arm64InstructionSetFeatures::FromAssembly().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800191 break;
192 case kMips:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800193 result.reset(MipsInstructionSetFeatures::FromAssembly().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800194 break;
Andreas Gampe57b34292015-01-14 15:45:59 -0800195 case kMips64:
196 result = Mips64InstructionSetFeatures::FromAssembly();
197 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800198 case kX86:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800199 result.reset(X86InstructionSetFeatures::FromAssembly().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800200 break;
201 case kX86_64:
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800202 result.reset(X86_64InstructionSetFeatures::FromAssembly().release());
Ian Rogersd582fa42014-11-05 23:46:43 -0800203 break;
204 default:
205 UNIMPLEMENTED(FATAL) << kRuntimeISA;
206 UNREACHABLE();
207 }
208 return result;
209}
210
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800211std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::AddFeaturesFromString(
Ian Rogersd582fa42014-11-05 23:46:43 -0800212 const std::string& feature_list, std::string* error_msg) const {
213 if (feature_list.empty()) {
214 *error_msg = "No instruction set features specified";
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800215 return std::unique_ptr<const InstructionSetFeatures>();
Ian Rogersd582fa42014-11-05 23:46:43 -0800216 }
217 std::vector<std::string> features;
218 Split(feature_list, ',', &features);
219 bool smp = smp_;
220 bool use_default = false; // Have we seen the 'default' feature?
221 bool first = false; // Is this first feature?
222 for (auto it = features.begin(); it != features.end();) {
223 if (use_default) {
224 *error_msg = "Unexpected instruction set features after 'default'";
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800225 return std::unique_ptr<const InstructionSetFeatures>();
Ian Rogersd582fa42014-11-05 23:46:43 -0800226 }
227 std::string feature = Trim(*it);
228 bool erase = false;
229 if (feature == "default") {
230 if (!first) {
231 use_default = true;
232 erase = true;
233 } else {
234 *error_msg = "Unexpected instruction set features before 'default'";
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800235 return std::unique_ptr<const InstructionSetFeatures>();
Ian Rogersd582fa42014-11-05 23:46:43 -0800236 }
237 } else if (feature == "smp") {
238 smp = true;
239 erase = true;
240 } else if (feature == "-smp") {
241 smp = false;
242 erase = true;
243 }
244 // Erase the smp feature once processed.
245 if (!erase) {
246 ++it;
247 } else {
248 it = features.erase(it);
249 }
250 first = true;
251 }
Goran Jakovljevica7d38fc2015-03-12 15:32:55 +0100252 // Expectation: "default" is standalone, no other flags. But an empty features vector after
253 // processing can also come along if the handled flags (at the moment only smp) are the only
254 // ones in the list. So logically, we check "default -> features.empty."
255 DCHECK(!use_default || features.empty());
256
Ian Rogersd582fa42014-11-05 23:46:43 -0800257 return AddFeaturesFromSplitString(smp, features, error_msg);
258}
259
260const ArmInstructionSetFeatures* InstructionSetFeatures::AsArmInstructionSetFeatures() const {
261 DCHECK_EQ(kArm, GetInstructionSet());
262 return down_cast<const ArmInstructionSetFeatures*>(this);
263}
264
265const Arm64InstructionSetFeatures* InstructionSetFeatures::AsArm64InstructionSetFeatures() const {
266 DCHECK_EQ(kArm64, GetInstructionSet());
267 return down_cast<const Arm64InstructionSetFeatures*>(this);
268}
269
270const MipsInstructionSetFeatures* InstructionSetFeatures::AsMipsInstructionSetFeatures() const {
271 DCHECK_EQ(kMips, GetInstructionSet());
272 return down_cast<const MipsInstructionSetFeatures*>(this);
273}
274
Andreas Gampe57b34292015-01-14 15:45:59 -0800275const Mips64InstructionSetFeatures* InstructionSetFeatures::AsMips64InstructionSetFeatures() const {
276 DCHECK_EQ(kMips64, GetInstructionSet());
277 return down_cast<const Mips64InstructionSetFeatures*>(this);
278}
279
Ian Rogersd582fa42014-11-05 23:46:43 -0800280const X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const {
281 DCHECK(kX86 == GetInstructionSet() || kX86_64 == GetInstructionSet());
282 return down_cast<const X86InstructionSetFeatures*>(this);
283}
284
285const X86_64InstructionSetFeatures* InstructionSetFeatures::AsX86_64InstructionSetFeatures() const {
286 DCHECK_EQ(kX86_64, GetInstructionSet());
287 return down_cast<const X86_64InstructionSetFeatures*>(this);
288}
289
Andreas Gampe24a05f42015-04-03 13:46:54 -0700290bool InstructionSetFeatures::FindVariantInArray(const char* const variants[], size_t num_variants,
Ian Rogersd582fa42014-11-05 23:46:43 -0800291 const std::string& variant) {
Andreas Gampe24a05f42015-04-03 13:46:54 -0700292 const char* const * begin = variants;
293 const char* const * end = begin + num_variants;
Ian Rogersd582fa42014-11-05 23:46:43 -0800294 return std::find(begin, end, variant) != end;
295}
296
297std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs) {
298 os << "ISA: " << rhs.GetInstructionSet() << " Feature string: " << rhs.GetFeatureString();
299 return os;
300}
301
302} // namespace art