Home | History | Annotate | Download | only in arch
      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