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 switch (isa) { 37 case kArm: 38 case kThumb2: 39 return ArmInstructionSetFeatures::FromVariant(variant, error_msg); 40 case kArm64: 41 return Arm64InstructionSetFeatures::FromVariant(variant, error_msg); 42 case kMips: 43 return MipsInstructionSetFeatures::FromVariant(variant, error_msg); 44 case kMips64: 45 return Mips64InstructionSetFeatures::FromVariant(variant, error_msg); 46 case kX86: 47 return X86InstructionSetFeatures::FromVariant(variant, error_msg); 48 case kX86_64: 49 return X86_64InstructionSetFeatures::FromVariant(variant, error_msg); 50 51 case kNone: 52 break; 53 } 54 UNIMPLEMENTED(FATAL) << isa; 55 UNREACHABLE(); 56 } 57 58 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromBitmap(InstructionSet isa, 59 uint32_t bitmap) { 60 std::unique_ptr<const InstructionSetFeatures> result; 61 switch (isa) { 62 case kArm: 63 case kThumb2: 64 result = ArmInstructionSetFeatures::FromBitmap(bitmap); 65 break; 66 case kArm64: 67 result = Arm64InstructionSetFeatures::FromBitmap(bitmap); 68 break; 69 case kMips: 70 result = MipsInstructionSetFeatures::FromBitmap(bitmap); 71 break; 72 case kMips64: 73 result = Mips64InstructionSetFeatures::FromBitmap(bitmap); 74 break; 75 case kX86: 76 result = X86InstructionSetFeatures::FromBitmap(bitmap); 77 break; 78 case kX86_64: 79 result = X86_64InstructionSetFeatures::FromBitmap(bitmap); 80 break; 81 82 case kNone: 83 default: 84 UNIMPLEMENTED(FATAL) << isa; 85 UNREACHABLE(); 86 } 87 CHECK_EQ(bitmap, result->AsBitmap()); 88 return result; 89 } 90 91 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCppDefines() { 92 switch (kRuntimeISA) { 93 case kArm: 94 case kThumb2: 95 return ArmInstructionSetFeatures::FromCppDefines(); 96 case kArm64: 97 return Arm64InstructionSetFeatures::FromCppDefines(); 98 case kMips: 99 return MipsInstructionSetFeatures::FromCppDefines(); 100 case kMips64: 101 return Mips64InstructionSetFeatures::FromCppDefines(); 102 case kX86: 103 return X86InstructionSetFeatures::FromCppDefines(); 104 case kX86_64: 105 return X86_64InstructionSetFeatures::FromCppDefines(); 106 107 case kNone: 108 break; 109 } 110 UNIMPLEMENTED(FATAL) << kRuntimeISA; 111 UNREACHABLE(); 112 } 113 114 115 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCpuInfo() { 116 switch (kRuntimeISA) { 117 case kArm: 118 case kThumb2: 119 return ArmInstructionSetFeatures::FromCpuInfo(); 120 case kArm64: 121 return Arm64InstructionSetFeatures::FromCpuInfo(); 122 case kMips: 123 return MipsInstructionSetFeatures::FromCpuInfo(); 124 case kMips64: 125 return Mips64InstructionSetFeatures::FromCpuInfo(); 126 case kX86: 127 return X86InstructionSetFeatures::FromCpuInfo(); 128 case kX86_64: 129 return X86_64InstructionSetFeatures::FromCpuInfo(); 130 131 case kNone: 132 break; 133 } 134 UNIMPLEMENTED(FATAL) << kRuntimeISA; 135 UNREACHABLE(); 136 } 137 138 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromHwcap() { 139 switch (kRuntimeISA) { 140 case kArm: 141 case kThumb2: 142 return ArmInstructionSetFeatures::FromHwcap(); 143 case kArm64: 144 return Arm64InstructionSetFeatures::FromHwcap(); 145 case kMips: 146 return MipsInstructionSetFeatures::FromHwcap(); 147 case kMips64: 148 return Mips64InstructionSetFeatures::FromHwcap(); 149 case kX86: 150 return X86InstructionSetFeatures::FromHwcap(); 151 case kX86_64: 152 return X86_64InstructionSetFeatures::FromHwcap(); 153 154 case kNone: 155 break; 156 } 157 UNIMPLEMENTED(FATAL) << kRuntimeISA; 158 UNREACHABLE(); 159 } 160 161 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromAssembly() { 162 switch (kRuntimeISA) { 163 case kArm: 164 case kThumb2: 165 return ArmInstructionSetFeatures::FromAssembly(); 166 case kArm64: 167 return Arm64InstructionSetFeatures::FromAssembly(); 168 case kMips: 169 return MipsInstructionSetFeatures::FromAssembly(); 170 case kMips64: 171 return Mips64InstructionSetFeatures::FromAssembly(); 172 case kX86: 173 return X86InstructionSetFeatures::FromAssembly(); 174 case kX86_64: 175 return X86_64InstructionSetFeatures::FromAssembly(); 176 177 case kNone: 178 break; 179 } 180 UNIMPLEMENTED(FATAL) << kRuntimeISA; 181 UNREACHABLE(); 182 } 183 184 std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::AddFeaturesFromString( 185 const std::string& feature_list, std::string* error_msg) const { 186 if (feature_list.empty()) { 187 *error_msg = "No instruction set features specified"; 188 return std::unique_ptr<const InstructionSetFeatures>(); 189 } 190 std::vector<std::string> features; 191 Split(feature_list, ',', &features); 192 bool use_default = false; // Have we seen the 'default' feature? 193 bool first = false; // Is this first feature? 194 for (auto it = features.begin(); it != features.end();) { 195 if (use_default) { 196 *error_msg = "Unexpected instruction set features after 'default'"; 197 return std::unique_ptr<const InstructionSetFeatures>(); 198 } 199 std::string feature = android::base::Trim(*it); 200 bool erase = false; 201 if (feature == "default") { 202 if (!first) { 203 use_default = true; 204 erase = true; 205 } else { 206 *error_msg = "Unexpected instruction set features before 'default'"; 207 return std::unique_ptr<const InstructionSetFeatures>(); 208 } 209 } 210 if (!erase) { 211 ++it; 212 } else { 213 it = features.erase(it); 214 } 215 first = true; 216 } 217 // Expectation: "default" is standalone, no other flags. But an empty features vector after 218 // processing can also come along if the handled flags are the only ones in the list. So 219 // logically, we check "default -> features.empty." 220 DCHECK(!use_default || features.empty()); 221 222 return AddFeaturesFromSplitString(features, error_msg); 223 } 224 225 const ArmInstructionSetFeatures* InstructionSetFeatures::AsArmInstructionSetFeatures() const { 226 DCHECK_EQ(kArm, GetInstructionSet()); 227 return down_cast<const ArmInstructionSetFeatures*>(this); 228 } 229 230 const Arm64InstructionSetFeatures* InstructionSetFeatures::AsArm64InstructionSetFeatures() const { 231 DCHECK_EQ(kArm64, GetInstructionSet()); 232 return down_cast<const Arm64InstructionSetFeatures*>(this); 233 } 234 235 const MipsInstructionSetFeatures* InstructionSetFeatures::AsMipsInstructionSetFeatures() const { 236 DCHECK_EQ(kMips, GetInstructionSet()); 237 return down_cast<const MipsInstructionSetFeatures*>(this); 238 } 239 240 const Mips64InstructionSetFeatures* InstructionSetFeatures::AsMips64InstructionSetFeatures() const { 241 DCHECK_EQ(kMips64, GetInstructionSet()); 242 return down_cast<const Mips64InstructionSetFeatures*>(this); 243 } 244 245 const X86InstructionSetFeatures* InstructionSetFeatures::AsX86InstructionSetFeatures() const { 246 DCHECK(kX86 == GetInstructionSet() || kX86_64 == GetInstructionSet()); 247 return down_cast<const X86InstructionSetFeatures*>(this); 248 } 249 250 const X86_64InstructionSetFeatures* InstructionSetFeatures::AsX86_64InstructionSetFeatures() const { 251 DCHECK_EQ(kX86_64, GetInstructionSet()); 252 return down_cast<const X86_64InstructionSetFeatures*>(this); 253 } 254 255 bool InstructionSetFeatures::FindVariantInArray(const char* const variants[], size_t num_variants, 256 const std::string& variant) { 257 const char* const * begin = variants; 258 const char* const * end = begin + num_variants; 259 return std::find(begin, end, variant) != end; 260 } 261 262 std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs) { 263 os << "ISA: " << rhs.GetInstructionSet() << " Feature string: " << rhs.GetFeatureString(); 264 return os; 265 } 266 267 } // namespace art 268