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 "android-base/strings.h" 20 21 #include "base/casts.h" 22 #include "utils.h" 23 24 25 #include "arm/instruction_set_features_arm.h" 26 #include "arm64/instruction_set_features_arm64.h" 27 #include "mips/instruction_set_features_mips.h" 28 #include "mips64/instruction_set_features_mips64.h" 29 #include "x86/instruction_set_features_x86.h" 30 #include "x86_64/instruction_set_features_x86_64.h" 31 32 namespace art { 33 34 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromVariant( 35 InstructionSet isa, const std::string& variant, std::string* error_msg) { 36 std::unique_ptr<const InstructionSetFeatures> result; 37 switch (isa) { 38 case kArm: 39 case kThumb2: 40 result.reset(ArmInstructionSetFeatures::FromVariant(variant, error_msg).release()); 41 break; 42 case kArm64: 43 result.reset(Arm64InstructionSetFeatures::FromVariant(variant, error_msg).release()); 44 break; 45 case kMips: 46 result.reset(MipsInstructionSetFeatures::FromVariant(variant, error_msg).release()); 47 break; 48 case kMips64: 49 result = Mips64InstructionSetFeatures::FromVariant(variant, error_msg); 50 break; 51 case kX86: 52 result.reset(X86InstructionSetFeatures::FromVariant(variant, error_msg).release()); 53 break; 54 case kX86_64: 55 result.reset(X86_64InstructionSetFeatures::FromVariant(variant, error_msg).release()); 56 break; 57 default: 58 UNIMPLEMENTED(FATAL) << isa; 59 UNREACHABLE(); 60 } 61 CHECK_EQ(result == nullptr, error_msg->size() != 0); 62 return result; 63 } 64 65 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromBitmap(InstructionSet isa, 66 uint32_t bitmap) { 67 std::unique_ptr<const InstructionSetFeatures> result; 68 switch (isa) { 69 case kArm: 70 case kThumb2: 71 result.reset(ArmInstructionSetFeatures::FromBitmap(bitmap).release()); 72 break; 73 case kArm64: 74 result.reset(Arm64InstructionSetFeatures::FromBitmap(bitmap).release()); 75 break; 76 case kMips: 77 result.reset(MipsInstructionSetFeatures::FromBitmap(bitmap).release()); 78 break; 79 case kMips64: 80 result = Mips64InstructionSetFeatures::FromBitmap(bitmap); 81 break; 82 case kX86: 83 result.reset(X86InstructionSetFeatures::FromBitmap(bitmap).release()); 84 break; 85 case kX86_64: 86 result.reset(X86_64InstructionSetFeatures::FromBitmap(bitmap).release()); 87 break; 88 default: 89 UNIMPLEMENTED(FATAL) << isa; 90 UNREACHABLE(); 91 } 92 CHECK_EQ(bitmap, result->AsBitmap()); 93 return result; 94 } 95 96 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCppDefines() { 97 std::unique_ptr<const InstructionSetFeatures> result; 98 switch (kRuntimeISA) { 99 case kArm: 100 case kThumb2: 101 result.reset(ArmInstructionSetFeatures::FromCppDefines().release()); 102 break; 103 case kArm64: 104 result.reset(Arm64InstructionSetFeatures::FromCppDefines().release()); 105 break; 106 case kMips: 107 result.reset(MipsInstructionSetFeatures::FromCppDefines().release()); 108 break; 109 case kMips64: 110 result = Mips64InstructionSetFeatures::FromCppDefines(); 111 break; 112 case kX86: 113 result.reset(X86InstructionSetFeatures::FromCppDefines().release()); 114 break; 115 case kX86_64: 116 result.reset(X86_64InstructionSetFeatures::FromCppDefines().release()); 117 break; 118 default: 119 UNIMPLEMENTED(FATAL) << kRuntimeISA; 120 UNREACHABLE(); 121 } 122 return result; 123 } 124 125 126 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCpuInfo() { 127 std::unique_ptr<const InstructionSetFeatures> result; 128 switch (kRuntimeISA) { 129 case kArm: 130 case kThumb2: 131 result.reset(ArmInstructionSetFeatures::FromCpuInfo().release()); 132 break; 133 case kArm64: 134 result.reset(Arm64InstructionSetFeatures::FromCpuInfo().release()); 135 break; 136 case kMips: 137 result.reset(MipsInstructionSetFeatures::FromCpuInfo().release()); 138 break; 139 case kMips64: 140 result = Mips64InstructionSetFeatures::FromCpuInfo(); 141 break; 142 case kX86: 143 result.reset(X86InstructionSetFeatures::FromCpuInfo().release()); 144 break; 145 case kX86_64: 146 result.reset(X86_64InstructionSetFeatures::FromCpuInfo().release()); 147 break; 148 default: 149 UNIMPLEMENTED(FATAL) << kRuntimeISA; 150 UNREACHABLE(); 151 } 152 return result; 153 } 154 155 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromHwcap() { 156 std::unique_ptr<const InstructionSetFeatures> result; 157 switch (kRuntimeISA) { 158 case kArm: 159 case kThumb2: 160 result.reset(ArmInstructionSetFeatures::FromHwcap().release()); 161 break; 162 case kArm64: 163 result.reset(Arm64InstructionSetFeatures::FromHwcap().release()); 164 break; 165 case kMips: 166 result.reset(MipsInstructionSetFeatures::FromHwcap().release()); 167 break; 168 case kMips64: 169 result = Mips64InstructionSetFeatures::FromHwcap(); 170 break; 171 case kX86: 172 result.reset(X86InstructionSetFeatures::FromHwcap().release()); 173 break; 174 case kX86_64: 175 result.reset(X86_64InstructionSetFeatures::FromHwcap().release()); 176 break; 177 default: 178 UNIMPLEMENTED(FATAL) << kRuntimeISA; 179 UNREACHABLE(); 180 } 181 return result; 182 } 183 184 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromAssembly() { 185 std::unique_ptr<const InstructionSetFeatures> result; 186 switch (kRuntimeISA) { 187 case kArm: 188 case kThumb2: 189 result.reset(ArmInstructionSetFeatures::FromAssembly().release()); 190 break; 191 case kArm64: 192 result.reset(Arm64InstructionSetFeatures::FromAssembly().release()); 193 break; 194 case kMips: 195 result.reset(MipsInstructionSetFeatures::FromAssembly().release()); 196 break; 197 case kMips64: 198 result = Mips64InstructionSetFeatures::FromAssembly(); 199 break; 200 case kX86: 201 result.reset(X86InstructionSetFeatures::FromAssembly().release()); 202 break; 203 case kX86_64: 204 result.reset(X86_64InstructionSetFeatures::FromAssembly().release()); 205 break; 206 default: 207 UNIMPLEMENTED(FATAL) << kRuntimeISA; 208 UNREACHABLE(); 209 } 210 return result; 211 } 212 213 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::AddFeaturesFromString( 214 const std::string& feature_list, std::string* error_msg) const { 215 if (feature_list.empty()) { 216 *error_msg = "No instruction set features specified"; 217 return std::unique_ptr<const InstructionSetFeatures>(); 218 } 219 std::vector<std::string> features; 220 Split(feature_list, ',', &features); 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 std::unique_ptr<const InstructionSetFeatures>(); 227 } 228 std::string feature = android::base::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 std::unique_ptr<const InstructionSetFeatures>(); 237 } 238 } 239 if (!erase) { 240 ++it; 241 } else { 242 it = features.erase(it); 243 } 244 first = true; 245 } 246 // Expectation: "default" is standalone, no other flags. But an empty features vector after 247 // processing can also come along if the handled flags are the only ones in the list. So 248 // logically, we check "default -> features.empty." 249 DCHECK(!use_default || features.empty()); 250 251 return AddFeaturesFromSplitString(features, error_msg); 252 } 253 254 const ArmInstructionSetFeatures* InstructionSetFeatures::AsArmInstructionSetFeatures() const { 255 DCHECK_EQ(kArm, GetInstructionSet()); 256 return down_cast<const ArmInstructionSetFeatures*>(this); 257 } 258 259 const Arm64InstructionSetFeatures* InstructionSetFeatures::AsArm64InstructionSetFeatures() const { 260 DCHECK_EQ(kArm64, GetInstructionSet()); 261 return down_cast<const Arm64InstructionSetFeatures*>(this); 262 } 263 264 const MipsInstructionSetFeatures* InstructionSetFeatures::AsMipsInstructionSetFeatures() const { 265 DCHECK_EQ(kMips, GetInstructionSet()); 266 return down_cast<const MipsInstructionSetFeatures*>(this); 267 } 268 269 const Mips64InstructionSetFeatures* InstructionSetFeatures::AsMips64InstructionSetFeatures() const { 270 DCHECK_EQ(kMips64, GetInstructionSet()); 271 return down_cast<const Mips64InstructionSetFeatures*>(this); 272 } 273 274 const X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const { 275 DCHECK(kX86 == GetInstructionSet() || kX86_64 == GetInstructionSet()); 276 return down_cast<const X86InstructionSetFeatures*>(this); 277 } 278 279 const X86_64InstructionSetFeatures* InstructionSetFeatures::AsX86_64InstructionSetFeatures() const { 280 DCHECK_EQ(kX86_64, GetInstructionSet()); 281 return down_cast<const X86_64InstructionSetFeatures*>(this); 282 } 283 284 bool InstructionSetFeatures::FindVariantInArray(const char* const variants[], size_t num_variants, 285 const std::string& variant) { 286 const char* const * begin = variants; 287 const char* const * end = begin + num_variants; 288 return std::find(begin, end, variant) != end; 289 } 290 291 std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs) { 292 os << "ISA: " << rhs.GetInstructionSet() << " Feature string: " << rhs.GetFeatureString(); 293 return os; 294 } 295 296 } // namespace art 297