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