1 /*
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"
26 #include "mips64/instruction_set_features_mips64.h"
27 #include "x86/instruction_set_features_x86.h"
28 #include "x86_64/instruction_set_features_x86_64.h"
29
30 namespace art {
31
FromVariant(InstructionSet isa,const std::string & variant,std::string * error_msg)32 const 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;
47 case kMips64:
48 result = Mips64InstructionSetFeatures::FromVariant(variant, error_msg);
49 break;
50 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
FromBitmap(InstructionSet isa,uint32_t bitmap)64 const 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;
78 case kMips64:
79 result = Mips64InstructionSetFeatures::FromBitmap(bitmap);
80 break;
81 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
FromCppDefines()95 const 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;
108 case kMips64:
109 result = Mips64InstructionSetFeatures::FromCppDefines();
110 break;
111 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
FromCpuInfo()125 const 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;
138 case kMips64:
139 result = Mips64InstructionSetFeatures::FromCpuInfo();
140 break;
141 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
FromHwcap()154 const 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;
167 case kMips64:
168 result = Mips64InstructionSetFeatures::FromHwcap();
169 break;
170 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
FromAssembly()183 const 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;
196 case kMips64:
197 result = Mips64InstructionSetFeatures::FromAssembly();
198 break;
199 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
AddFeaturesFromString(const std::string & feature_list,std::string * error_msg) const212 const 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 // Expectation: "default" is standalone, no other flags. But an empty features vector after
254 // processing can also come along if the handled flags (at the moment only smp) are the only
255 // ones in the list. So logically, we check "default -> features.empty."
256 DCHECK(!use_default || features.empty());
257
258 return AddFeaturesFromSplitString(smp, features, error_msg);
259 }
260
AsArmInstructionSetFeatures() const261 const ArmInstructionSetFeatures* InstructionSetFeatures::AsArmInstructionSetFeatures() const {
262 DCHECK_EQ(kArm, GetInstructionSet());
263 return down_cast<const ArmInstructionSetFeatures*>(this);
264 }
265
AsArm64InstructionSetFeatures() const266 const Arm64InstructionSetFeatures* InstructionSetFeatures::AsArm64InstructionSetFeatures() const {
267 DCHECK_EQ(kArm64, GetInstructionSet());
268 return down_cast<const Arm64InstructionSetFeatures*>(this);
269 }
270
AsMipsInstructionSetFeatures() const271 const MipsInstructionSetFeatures* InstructionSetFeatures::AsMipsInstructionSetFeatures() const {
272 DCHECK_EQ(kMips, GetInstructionSet());
273 return down_cast<const MipsInstructionSetFeatures*>(this);
274 }
275
AsMips64InstructionSetFeatures() const276 const Mips64InstructionSetFeatures* InstructionSetFeatures::AsMips64InstructionSetFeatures() const {
277 DCHECK_EQ(kMips64, GetInstructionSet());
278 return down_cast<const Mips64InstructionSetFeatures*>(this);
279 }
280
AsX86InstructionSetFeatures() const281 const X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const {
282 DCHECK(kX86 == GetInstructionSet() || kX86_64 == GetInstructionSet());
283 return down_cast<const X86InstructionSetFeatures*>(this);
284 }
285
AsX86_64InstructionSetFeatures() const286 const X86_64InstructionSetFeatures* InstructionSetFeatures::AsX86_64InstructionSetFeatures() const {
287 DCHECK_EQ(kX86_64, GetInstructionSet());
288 return down_cast<const X86_64InstructionSetFeatures*>(this);
289 }
290
FindVariantInArray(const char * const variants[],size_t num_variants,const std::string & variant)291 bool InstructionSetFeatures::FindVariantInArray(const char* const variants[], size_t num_variants,
292 const std::string& variant) {
293 const char* const * begin = variants;
294 const char* const * end = begin + num_variants;
295 return std::find(begin, end, variant) != end;
296 }
297
operator <<(std::ostream & os,const InstructionSetFeatures & rhs)298 std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs) {
299 os << "ISA: " << rhs.GetInstructionSet() << " Feature string: " << rhs.GetFeatureString();
300 return os;
301 }
302
303 } // namespace art
304