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