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