1 /* 2 * Copyright (C) 2014 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_mips.h" 18 19 #include <fstream> 20 #include <sstream> 21 22 #include "android-base/stringprintf.h" 23 #include "android-base/strings.h" 24 25 #include "base/logging.h" 26 #include "base/stl_util.h" 27 28 namespace art { 29 30 using android::base::StringPrintf; 31 32 // An enum for the Mips revision. 33 enum class MipsLevel { 34 kBase, 35 kR2, 36 kR5, 37 kR6 38 }; 39 40 #if defined(_MIPS_ARCH_MIPS32R6) 41 static constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kR6; 42 #elif defined(_MIPS_ARCH_MIPS32R5) 43 static constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kR5; 44 #elif defined(_MIPS_ARCH_MIPS32R2) 45 static constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kR2; 46 #else 47 static constexpr MipsLevel kRuntimeMipsLevel = MipsLevel::kBase; 48 #endif 49 50 static void GetFlagsFromCppDefined(bool* mips_isa_gte2, bool* r6, bool* fpu_32bit) { 51 // Override defaults based on compiler flags. 52 if (kRuntimeMipsLevel >= MipsLevel::kR2) { 53 *mips_isa_gte2 = true; 54 } else { 55 *mips_isa_gte2 = false; 56 } 57 58 if (kRuntimeMipsLevel >= MipsLevel::kR5) { 59 *fpu_32bit = false; 60 } else { 61 *fpu_32bit = true; 62 } 63 64 if (kRuntimeMipsLevel >= MipsLevel::kR6) { 65 *r6 = true; 66 } else { 67 *r6 = false; 68 } 69 } 70 71 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromVariant( 72 const std::string& variant, std::string* error_msg ATTRIBUTE_UNUSED) { 73 74 // Override defaults based on compiler flags. 75 // This is needed when running ART test where the variant is not defined. 76 bool fpu_32bit; 77 bool mips_isa_gte2; 78 bool r6; 79 GetFlagsFromCppDefined(&mips_isa_gte2, &r6, &fpu_32bit); 80 81 // Override defaults based on variant string. 82 // Only care if it is R1, R2, R5 or R6 and we assume all CPUs will have a FP unit. 83 constexpr const char* kMips32Prefix = "mips32r"; 84 const size_t kPrefixLength = strlen(kMips32Prefix); 85 if (variant.compare(0, kPrefixLength, kMips32Prefix, kPrefixLength) == 0 && 86 variant.size() > kPrefixLength) { 87 r6 = (variant[kPrefixLength] >= '6'); 88 fpu_32bit = (variant[kPrefixLength] < '5'); 89 mips_isa_gte2 = (variant[kPrefixLength] >= '2'); 90 } else if (variant == "default") { 91 // Default variant has FPU, is gte2. This is the traditional setting. 92 // 93 // Note, we get FPU bitness and R6-ness from the build (using cpp defines, see above) 94 // and don't override them because many things depend on the "default" variant being 95 // sufficient for most purposes. That is, "default" should work for both R2 and R6. 96 // Use "mips32r#" to get a specific configuration, possibly not matching the runtime 97 // ISA (e.g. for ISA-specific testing of dex2oat internals). 98 mips_isa_gte2 = true; 99 } else { 100 LOG(WARNING) << "Unexpected CPU variant for Mips32 using defaults: " << variant; 101 } 102 103 return MipsFeaturesUniquePtr(new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6)); 104 } 105 106 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromBitmap(uint32_t bitmap) { 107 bool fpu_32bit = (bitmap & kFpu32Bitfield) != 0; 108 bool mips_isa_gte2 = (bitmap & kIsaRevGte2Bitfield) != 0; 109 bool r6 = (bitmap & kR6) != 0; 110 return MipsFeaturesUniquePtr(new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6)); 111 } 112 113 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromCppDefines() { 114 bool fpu_32bit; 115 bool mips_isa_gte2; 116 bool r6; 117 GetFlagsFromCppDefined(&mips_isa_gte2, &r6, &fpu_32bit); 118 119 return MipsFeaturesUniquePtr(new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6)); 120 } 121 122 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromCpuInfo() { 123 bool fpu_32bit; 124 bool mips_isa_gte2; 125 bool r6; 126 GetFlagsFromCppDefined(&mips_isa_gte2, &r6, &fpu_32bit); 127 128 return MipsFeaturesUniquePtr(new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6)); 129 } 130 131 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromHwcap() { 132 UNIMPLEMENTED(WARNING); 133 return FromCppDefines(); 134 } 135 136 MipsFeaturesUniquePtr MipsInstructionSetFeatures::FromAssembly() { 137 UNIMPLEMENTED(WARNING); 138 return FromCppDefines(); 139 } 140 141 bool MipsInstructionSetFeatures::Equals(const InstructionSetFeatures* other) const { 142 if (kMips != other->GetInstructionSet()) { 143 return false; 144 } 145 const MipsInstructionSetFeatures* other_as_mips = other->AsMipsInstructionSetFeatures(); 146 return (fpu_32bit_ == other_as_mips->fpu_32bit_) && 147 (mips_isa_gte2_ == other_as_mips->mips_isa_gte2_) && 148 (r6_ == other_as_mips->r6_); 149 } 150 151 uint32_t MipsInstructionSetFeatures::AsBitmap() const { 152 return (fpu_32bit_ ? kFpu32Bitfield : 0) | 153 (mips_isa_gte2_ ? kIsaRevGte2Bitfield : 0) | 154 (r6_ ? kR6 : 0); 155 } 156 157 std::string MipsInstructionSetFeatures::GetFeatureString() const { 158 std::string result; 159 if (fpu_32bit_) { 160 result += "fpu32"; 161 } else { 162 result += "-fpu32"; 163 } 164 if (mips_isa_gte2_) { 165 result += ",mips2"; 166 } else { 167 result += ",-mips2"; 168 } 169 if (r6_) { 170 result += ",r6"; 171 } // Suppress non-r6. 172 return result; 173 } 174 175 std::unique_ptr<const InstructionSetFeatures> 176 MipsInstructionSetFeatures::AddFeaturesFromSplitString( 177 const std::vector<std::string>& features, std::string* error_msg) const { 178 bool fpu_32bit = fpu_32bit_; 179 bool mips_isa_gte2 = mips_isa_gte2_; 180 bool r6 = r6_; 181 for (auto i = features.begin(); i != features.end(); i++) { 182 std::string feature = android::base::Trim(*i); 183 if (feature == "fpu32") { 184 fpu_32bit = true; 185 } else if (feature == "-fpu32") { 186 fpu_32bit = false; 187 } else if (feature == "mips2") { 188 mips_isa_gte2 = true; 189 } else if (feature == "-mips2") { 190 mips_isa_gte2 = false; 191 } else if (feature == "r6") { 192 r6 = true; 193 } else if (feature == "-r6") { 194 r6 = false; 195 } else { 196 *error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str()); 197 return nullptr; 198 } 199 } 200 return std::unique_ptr<const InstructionSetFeatures>( 201 new MipsInstructionSetFeatures(fpu_32bit, mips_isa_gte2, r6)); 202 } 203 204 } // namespace art 205