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