blob: c5c2d31158adeadf66ccdbb38ba626cbe4057dc4 [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
xueliang.zhong7f88c1a2018-11-06 11:42:41 +000017#include <algorithm>
18
Ian Rogersd582fa42014-11-05 23:46:43 -080019#include "instruction_set_features.h"
20
Andreas Gampe8764dc32019-01-07 15:20:12 -080021#include <algorithm>
22#include <ostream>
23
Andreas Gampe9186ced2016-12-12 14:28:21 -080024#include "android-base/strings.h"
25
Ian Rogersd582fa42014-11-05 23:46:43 -080026#include "base/casts.h"
David Sehrc431b9d2018-03-02 12:01:51 -080027#include "base/utils.h"
Ian Rogersd582fa42014-11-05 23:46:43 -080028
Ian Rogersd582fa42014-11-05 23:46:43 -080029#include "arm/instruction_set_features_arm.h"
30#include "arm64/instruction_set_features_arm64.h"
31#include "mips/instruction_set_features_mips.h"
Andreas Gampe57b34292015-01-14 15:45:59 -080032#include "mips64/instruction_set_features_mips64.h"
Ian Rogersd582fa42014-11-05 23:46:43 -080033#include "x86/instruction_set_features_x86.h"
34#include "x86_64/instruction_set_features_x86_64.h"
35
36namespace art {
37
Andreas Gampe0415b4e2015-01-06 15:17:07 -080038std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromVariant(
39 InstructionSet isa, const std::string& variant, std::string* error_msg) {
Ian Rogersd582fa42014-11-05 23:46:43 -080040 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +000041 case InstructionSet::kArm:
42 case InstructionSet::kThumb2:
Andreas Gampe8d01c372017-05-30 13:21:28 -070043 return ArmInstructionSetFeatures::FromVariant(variant, error_msg);
Vladimir Marko33bff252017-11-01 14:35:42 +000044 case InstructionSet::kArm64:
Andreas Gampe8d01c372017-05-30 13:21:28 -070045 return Arm64InstructionSetFeatures::FromVariant(variant, error_msg);
Vladimir Marko33bff252017-11-01 14:35:42 +000046 case InstructionSet::kMips:
Andreas Gampe8d01c372017-05-30 13:21:28 -070047 return MipsInstructionSetFeatures::FromVariant(variant, error_msg);
Vladimir Marko33bff252017-11-01 14:35:42 +000048 case InstructionSet::kMips64:
Andreas Gampe8d01c372017-05-30 13:21:28 -070049 return Mips64InstructionSetFeatures::FromVariant(variant, error_msg);
Vladimir Marko33bff252017-11-01 14:35:42 +000050 case InstructionSet::kX86:
Andreas Gampe8d01c372017-05-30 13:21:28 -070051 return X86InstructionSetFeatures::FromVariant(variant, error_msg);
Vladimir Marko33bff252017-11-01 14:35:42 +000052 case InstructionSet::kX86_64:
Andreas Gampe8d01c372017-05-30 13:21:28 -070053 return X86_64InstructionSetFeatures::FromVariant(variant, error_msg);
54
Vladimir Marko33bff252017-11-01 14:35:42 +000055 case InstructionSet::kNone:
Ian Rogersd582fa42014-11-05 23:46:43 -080056 break;
Ian Rogersd582fa42014-11-05 23:46:43 -080057 }
Andreas Gampe8d01c372017-05-30 13:21:28 -070058 UNIMPLEMENTED(FATAL) << isa;
59 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -080060}
61
Andreas Gampe0415b4e2015-01-06 15:17:07 -080062std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromBitmap(InstructionSet isa,
63 uint32_t bitmap) {
64 std::unique_ptr<const InstructionSetFeatures> result;
Ian Rogersd582fa42014-11-05 23:46:43 -080065 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +000066 case InstructionSet::kArm:
67 case InstructionSet::kThumb2:
Andreas Gampe8d01c372017-05-30 13:21:28 -070068 result = ArmInstructionSetFeatures::FromBitmap(bitmap);
Ian Rogersd582fa42014-11-05 23:46:43 -080069 break;
Vladimir Marko33bff252017-11-01 14:35:42 +000070 case InstructionSet::kArm64:
Andreas Gampe8d01c372017-05-30 13:21:28 -070071 result = Arm64InstructionSetFeatures::FromBitmap(bitmap);
Ian Rogersd582fa42014-11-05 23:46:43 -080072 break;
Vladimir Marko33bff252017-11-01 14:35:42 +000073 case InstructionSet::kMips:
Andreas Gampe8d01c372017-05-30 13:21:28 -070074 result = MipsInstructionSetFeatures::FromBitmap(bitmap);
Ian Rogersd582fa42014-11-05 23:46:43 -080075 break;
Vladimir Marko33bff252017-11-01 14:35:42 +000076 case InstructionSet::kMips64:
Andreas Gampe57b34292015-01-14 15:45:59 -080077 result = Mips64InstructionSetFeatures::FromBitmap(bitmap);
78 break;
Vladimir Marko33bff252017-11-01 14:35:42 +000079 case InstructionSet::kX86:
Andreas Gampe8d01c372017-05-30 13:21:28 -070080 result = X86InstructionSetFeatures::FromBitmap(bitmap);
Ian Rogersd582fa42014-11-05 23:46:43 -080081 break;
Vladimir Marko33bff252017-11-01 14:35:42 +000082 case InstructionSet::kX86_64:
Andreas Gampe8d01c372017-05-30 13:21:28 -070083 result = X86_64InstructionSetFeatures::FromBitmap(bitmap);
Ian Rogersd582fa42014-11-05 23:46:43 -080084 break;
Andreas Gampe8d01c372017-05-30 13:21:28 -070085
Vladimir Marko33bff252017-11-01 14:35:42 +000086 case InstructionSet::kNone:
Ian Rogersd582fa42014-11-05 23:46:43 -080087 default:
88 UNIMPLEMENTED(FATAL) << isa;
89 UNREACHABLE();
90 }
91 CHECK_EQ(bitmap, result->AsBitmap());
92 return result;
93}
94
Andreas Gampe0415b4e2015-01-06 15:17:07 -080095std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCppDefines() {
Ian Rogersd582fa42014-11-05 23:46:43 -080096 switch (kRuntimeISA) {
Vladimir Marko33bff252017-11-01 14:35:42 +000097 case InstructionSet::kArm:
98 case InstructionSet::kThumb2:
Andreas Gampe8d01c372017-05-30 13:21:28 -070099 return ArmInstructionSetFeatures::FromCppDefines();
Vladimir Marko33bff252017-11-01 14:35:42 +0000100 case InstructionSet::kArm64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700101 return Arm64InstructionSetFeatures::FromCppDefines();
Vladimir Marko33bff252017-11-01 14:35:42 +0000102 case InstructionSet::kMips:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700103 return MipsInstructionSetFeatures::FromCppDefines();
Vladimir Marko33bff252017-11-01 14:35:42 +0000104 case InstructionSet::kMips64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700105 return Mips64InstructionSetFeatures::FromCppDefines();
Vladimir Marko33bff252017-11-01 14:35:42 +0000106 case InstructionSet::kX86:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700107 return X86InstructionSetFeatures::FromCppDefines();
Vladimir Marko33bff252017-11-01 14:35:42 +0000108 case InstructionSet::kX86_64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700109 return X86_64InstructionSetFeatures::FromCppDefines();
110
Vladimir Marko33bff252017-11-01 14:35:42 +0000111 case InstructionSet::kNone:
Ian Rogersd582fa42014-11-05 23:46:43 -0800112 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800113 }
Andreas Gampe8d01c372017-05-30 13:21:28 -0700114 UNIMPLEMENTED(FATAL) << kRuntimeISA;
115 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -0800116}
117
xueliang.zhong7f88c1a2018-11-06 11:42:41 +0000118std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromRuntimeDetection() {
119 switch (kRuntimeISA) {
120#ifdef ART_TARGET_ANDROID
121 case InstructionSet::kArm64:
122 return Arm64InstructionSetFeatures::FromHwcap();
123#endif
124 default:
125 return nullptr;
126 }
127}
Ian Rogersd582fa42014-11-05 23:46:43 -0800128
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800129std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCpuInfo() {
Ian Rogersd582fa42014-11-05 23:46:43 -0800130 switch (kRuntimeISA) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000131 case InstructionSet::kArm:
132 case InstructionSet::kThumb2:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700133 return ArmInstructionSetFeatures::FromCpuInfo();
Vladimir Marko33bff252017-11-01 14:35:42 +0000134 case InstructionSet::kArm64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700135 return Arm64InstructionSetFeatures::FromCpuInfo();
Vladimir Marko33bff252017-11-01 14:35:42 +0000136 case InstructionSet::kMips:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700137 return MipsInstructionSetFeatures::FromCpuInfo();
Vladimir Marko33bff252017-11-01 14:35:42 +0000138 case InstructionSet::kMips64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700139 return Mips64InstructionSetFeatures::FromCpuInfo();
Vladimir Marko33bff252017-11-01 14:35:42 +0000140 case InstructionSet::kX86:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700141 return X86InstructionSetFeatures::FromCpuInfo();
Vladimir Marko33bff252017-11-01 14:35:42 +0000142 case InstructionSet::kX86_64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700143 return X86_64InstructionSetFeatures::FromCpuInfo();
144
Vladimir Marko33bff252017-11-01 14:35:42 +0000145 case InstructionSet::kNone:
Ian Rogersd582fa42014-11-05 23:46:43 -0800146 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800147 }
Andreas Gampe8d01c372017-05-30 13:21:28 -0700148 UNIMPLEMENTED(FATAL) << kRuntimeISA;
149 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -0800150}
151
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800152std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromHwcap() {
Ian Rogersd582fa42014-11-05 23:46:43 -0800153 switch (kRuntimeISA) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000154 case InstructionSet::kArm:
155 case InstructionSet::kThumb2:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700156 return ArmInstructionSetFeatures::FromHwcap();
Vladimir Marko33bff252017-11-01 14:35:42 +0000157 case InstructionSet::kArm64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700158 return Arm64InstructionSetFeatures::FromHwcap();
Vladimir Marko33bff252017-11-01 14:35:42 +0000159 case InstructionSet::kMips:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700160 return MipsInstructionSetFeatures::FromHwcap();
Vladimir Marko33bff252017-11-01 14:35:42 +0000161 case InstructionSet::kMips64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700162 return Mips64InstructionSetFeatures::FromHwcap();
Vladimir Marko33bff252017-11-01 14:35:42 +0000163 case InstructionSet::kX86:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700164 return X86InstructionSetFeatures::FromHwcap();
Vladimir Marko33bff252017-11-01 14:35:42 +0000165 case InstructionSet::kX86_64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700166 return X86_64InstructionSetFeatures::FromHwcap();
167
Vladimir Marko33bff252017-11-01 14:35:42 +0000168 case InstructionSet::kNone:
Ian Rogersd582fa42014-11-05 23:46:43 -0800169 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800170 }
Andreas Gampe8d01c372017-05-30 13:21:28 -0700171 UNIMPLEMENTED(FATAL) << kRuntimeISA;
172 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -0800173}
174
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800175std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromAssembly() {
Ian Rogersd582fa42014-11-05 23:46:43 -0800176 switch (kRuntimeISA) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000177 case InstructionSet::kArm:
178 case InstructionSet::kThumb2:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700179 return ArmInstructionSetFeatures::FromAssembly();
Vladimir Marko33bff252017-11-01 14:35:42 +0000180 case InstructionSet::kArm64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700181 return Arm64InstructionSetFeatures::FromAssembly();
Vladimir Marko33bff252017-11-01 14:35:42 +0000182 case InstructionSet::kMips:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700183 return MipsInstructionSetFeatures::FromAssembly();
Vladimir Marko33bff252017-11-01 14:35:42 +0000184 case InstructionSet::kMips64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700185 return Mips64InstructionSetFeatures::FromAssembly();
Vladimir Marko33bff252017-11-01 14:35:42 +0000186 case InstructionSet::kX86:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700187 return X86InstructionSetFeatures::FromAssembly();
Vladimir Marko33bff252017-11-01 14:35:42 +0000188 case InstructionSet::kX86_64:
Andreas Gampe8d01c372017-05-30 13:21:28 -0700189 return X86_64InstructionSetFeatures::FromAssembly();
190
Vladimir Marko33bff252017-11-01 14:35:42 +0000191 case InstructionSet::kNone:
Ian Rogersd582fa42014-11-05 23:46:43 -0800192 break;
Ian Rogersd582fa42014-11-05 23:46:43 -0800193 }
Andreas Gampe8d01c372017-05-30 13:21:28 -0700194 UNIMPLEMENTED(FATAL) << kRuntimeISA;
195 UNREACHABLE();
Ian Rogersd582fa42014-11-05 23:46:43 -0800196}
197
Andreas Gampe0415b4e2015-01-06 15:17:07 -0800198std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::AddFeaturesFromString(
xueliang.zhong7f88c1a2018-11-06 11:42:41 +0000199 const std::string& feature_list, /* out */ std::string* error_msg) const {
Ian Rogersd582fa42014-11-05 23:46:43 -0800200 std::vector<std::string> features;
201 Split(feature_list, ',', &features);
xueliang.zhong7f88c1a2018-11-06 11:42:41 +0000202 std::transform(std::begin(features), std::end(features), std::begin(features),
203 [](const std::string &s) { return android::base::Trim(s); });
204 auto empty_strings_begin = std::copy_if(std::begin(features), std::end(features),
205 std::begin(features),
206 [](const std::string& s) { return !s.empty(); });
207 features.erase(empty_strings_begin, std::end(features));
208 if (features.empty()) {
209 *error_msg = "No instruction set features specified";
210 return nullptr;
Ian Rogersd582fa42014-11-05 23:46:43 -0800211 }
Goran Jakovljevica7d38fc2015-03-12 15:32:55 +0100212
xueliang.zhong7f88c1a2018-11-06 11:42:41 +0000213 bool use_default = false;
214 bool use_runtime_detection = false;
215 for (const std::string& feature : features) {
216 if (feature == "default") {
217 if (features.size() > 1) {
218 *error_msg = "Specific instruction set feature(s) cannot be used when 'default' is used.";
219 return nullptr;
220 }
221 use_default = true;
222 features.pop_back();
223 break;
224 } else if (feature == "runtime") {
225 if (features.size() > 1) {
226 *error_msg = "Specific instruction set feature(s) cannot be used when 'runtime' is used.";
227 return nullptr;
228 }
229 use_runtime_detection = true;
230 features.pop_back();
231 break;
232 }
233 }
234 // Expectation: "default" and "runtime" are standalone, no other feature names.
235 // But an empty features vector after processing can also come along if the
236 // handled feature names are the only ones in the list. So
237 // logically, we check "default or runtime => features.empty."
238 DCHECK((!use_default && !use_runtime_detection) || features.empty());
239
240 std::unique_ptr<const InstructionSetFeatures> runtime_detected_features;
241 if (use_runtime_detection) {
242 runtime_detected_features = FromRuntimeDetection();
243 }
244
245 if (runtime_detected_features != nullptr) {
246 return AddRuntimeDetectedFeatures(runtime_detected_features.get());
247 } else {
248 return AddFeaturesFromSplitString(features, error_msg);
249 }
Ian Rogersd582fa42014-11-05 23:46:43 -0800250}
251
252const ArmInstructionSetFeatures* InstructionSetFeatures::AsArmInstructionSetFeatures() const {
Vladimir Marko33bff252017-11-01 14:35:42 +0000253 DCHECK_EQ(InstructionSet::kArm, GetInstructionSet());
Ian Rogersd582fa42014-11-05 23:46:43 -0800254 return down_cast<const ArmInstructionSetFeatures*>(this);
255}
256
257const Arm64InstructionSetFeatures* InstructionSetFeatures::AsArm64InstructionSetFeatures() const {
Vladimir Marko33bff252017-11-01 14:35:42 +0000258 DCHECK_EQ(InstructionSet::kArm64, GetInstructionSet());
Ian Rogersd582fa42014-11-05 23:46:43 -0800259 return down_cast<const Arm64InstructionSetFeatures*>(this);
260}
261
262const MipsInstructionSetFeatures* InstructionSetFeatures::AsMipsInstructionSetFeatures() const {
Vladimir Marko33bff252017-11-01 14:35:42 +0000263 DCHECK_EQ(InstructionSet::kMips, GetInstructionSet());
Ian Rogersd582fa42014-11-05 23:46:43 -0800264 return down_cast<const MipsInstructionSetFeatures*>(this);
265}
266
Andreas Gampe57b34292015-01-14 15:45:59 -0800267const Mips64InstructionSetFeatures* InstructionSetFeatures::AsMips64InstructionSetFeatures() const {
Vladimir Marko33bff252017-11-01 14:35:42 +0000268 DCHECK_EQ(InstructionSet::kMips64, GetInstructionSet());
Andreas Gampe57b34292015-01-14 15:45:59 -0800269 return down_cast<const Mips64InstructionSetFeatures*>(this);
270}
271
Ian Rogersd582fa42014-11-05 23:46:43 -0800272const X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const {
Vladimir Marko33bff252017-11-01 14:35:42 +0000273 DCHECK(InstructionSet::kX86 == GetInstructionSet() ||
274 InstructionSet::kX86_64 == GetInstructionSet());
Ian Rogersd582fa42014-11-05 23:46:43 -0800275 return down_cast<const X86InstructionSetFeatures*>(this);
276}
277
278const X86_64InstructionSetFeatures* InstructionSetFeatures::AsX86_64InstructionSetFeatures() const {
Vladimir Marko33bff252017-11-01 14:35:42 +0000279 DCHECK_EQ(InstructionSet::kX86_64, GetInstructionSet());
Ian Rogersd582fa42014-11-05 23:46:43 -0800280 return down_cast<const X86_64InstructionSetFeatures*>(this);
281}
282
Andreas Gampe24a05f42015-04-03 13:46:54 -0700283bool InstructionSetFeatures::FindVariantInArray(const char* const variants[], size_t num_variants,
Ian Rogersd582fa42014-11-05 23:46:43 -0800284 const std::string& variant) {
Andreas Gampe24a05f42015-04-03 13:46:54 -0700285 const char* const * begin = variants;
286 const char* const * end = begin + num_variants;
Ian Rogersd582fa42014-11-05 23:46:43 -0800287 return std::find(begin, end, variant) != end;
288}
289
xueliang.zhong7f88c1a2018-11-06 11:42:41 +0000290std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::AddRuntimeDetectedFeatures(
291 const InstructionSetFeatures *features ATTRIBUTE_UNUSED) const {
292 UNIMPLEMENTED(FATAL) << kRuntimeISA;
293 UNREACHABLE();
294}
295
Ian Rogersd582fa42014-11-05 23:46:43 -0800296std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs) {
297 os << "ISA: " << rhs.GetInstructionSet() << " Feature string: " << rhs.GetFeatureString();
298 return os;
299}
300
301} // namespace art