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/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