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 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 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 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 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 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 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 212 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 261 const ArmInstructionSetFeatures* InstructionSetFeatures::AsArmInstructionSetFeatures() const { 262 DCHECK_EQ(kArm, GetInstructionSet()); 263 return down_cast<const ArmInstructionSetFeatures*>(this); 264 } 265 266 const Arm64InstructionSetFeatures* InstructionSetFeatures::AsArm64InstructionSetFeatures() const { 267 DCHECK_EQ(kArm64, GetInstructionSet()); 268 return down_cast<const Arm64InstructionSetFeatures*>(this); 269 } 270 271 const MipsInstructionSetFeatures* InstructionSetFeatures::AsMipsInstructionSetFeatures() const { 272 DCHECK_EQ(kMips, GetInstructionSet()); 273 return down_cast<const MipsInstructionSetFeatures*>(this); 274 } 275 276 const Mips64InstructionSetFeatures* InstructionSetFeatures::AsMips64InstructionSetFeatures() const { 277 DCHECK_EQ(kMips64, GetInstructionSet()); 278 return down_cast<const Mips64InstructionSetFeatures*>(this); 279 } 280 281 const X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const { 282 DCHECK(kX86 == GetInstructionSet() || kX86_64 == GetInstructionSet()); 283 return down_cast<const X86InstructionSetFeatures*>(this); 284 } 285 286 const X86_64InstructionSetFeatures* InstructionSetFeatures::AsX86_64InstructionSetFeatures() const { 287 DCHECK_EQ(kX86_64, GetInstructionSet()); 288 return down_cast<const X86_64InstructionSetFeatures*>(this); 289 } 290 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 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