duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

cpu-features.cc (5397B)


      1 // Copyright 2018, VIXL authors
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are met:
      6 //
      7 //   * Redistributions of source code must retain the above copyright notice,
      8 //     this list of conditions and the following disclaimer.
      9 //   * Redistributions in binary form must reproduce the above copyright notice,
     10 //     this list of conditions and the following disclaimer in the documentation
     11 //     and/or other materials provided with the distribution.
     12 //   * Neither the name of ARM Limited nor the names of its contributors may be
     13 //     used to endorse or promote products derived from this software without
     14 //     specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 #include "cpu-features.h"
     28 
     29 #include <ostream>
     30 
     31 #include "globals-vixl.h"
     32 #include "utils-vixl.h"
     33 
     34 #if defined(__aarch64__) && defined(VIXL_INCLUDE_TARGET_AARCH64)
     35 #include "aarch64/cpu-aarch64.h"
     36 #define VIXL_USE_AARCH64_CPU_HELPERS
     37 #endif
     38 
     39 namespace vixl {
     40 
     41 CPUFeatures CPUFeatures::All() {
     42   CPUFeatures all;
     43   all.features_.set();
     44   return all;
     45 }
     46 
     47 CPUFeatures CPUFeatures::InferFromIDRegisters() {
     48   // This function assumes that kIDRegisterEmulation is available.
     49   CPUFeatures features(CPUFeatures::kIDRegisterEmulation);
     50 #ifdef VIXL_USE_AARCH64_CPU_HELPERS
     51   // Note that the Linux kernel filters these values during emulation, so the
     52   // results may not exactly match the expected hardware support.
     53   features.Combine(aarch64::CPU::InferCPUFeaturesFromIDRegisters());
     54 #endif
     55   return features;
     56 }
     57 
     58 CPUFeatures CPUFeatures::InferFromOS(QueryIDRegistersOption option) {
     59 #ifdef VIXL_USE_AARCH64_CPU_HELPERS
     60   return aarch64::CPU::InferCPUFeaturesFromOS(option);
     61 #else
     62   USE(option);
     63   return CPUFeatures();
     64 #endif
     65 }
     66 
     67 void CPUFeatures::Combine(const CPUFeatures& other) {
     68   features_ |= other.features_;
     69 }
     70 
     71 void CPUFeatures::Combine(Feature feature) {
     72   if (feature != CPUFeatures::kNone) features_.set(feature);
     73 }
     74 
     75 void CPUFeatures::Remove(const CPUFeatures& other) {
     76   features_ &= ~other.features_;
     77 }
     78 
     79 void CPUFeatures::Remove(Feature feature) {
     80   if (feature != CPUFeatures::kNone) features_.reset(feature);
     81 }
     82 
     83 bool CPUFeatures::Has(const CPUFeatures& other) const {
     84   return (features_ & other.features_) == other.features_;
     85 }
     86 
     87 bool CPUFeatures::Has(Feature feature) const {
     88   return (feature == CPUFeatures::kNone) || features_[feature];
     89 }
     90 
     91 size_t CPUFeatures::Count() const { return features_.count(); }
     92 
     93 std::ostream& operator<<(std::ostream& os, CPUFeatures::Feature feature) {
     94   // clang-format off
     95   switch (feature) {
     96 #define VIXL_FORMAT_FEATURE(SYMBOL, NAME, CPUINFO) \
     97     case CPUFeatures::SYMBOL:                      \
     98       return os << NAME;
     99 VIXL_CPU_FEATURE_LIST(VIXL_FORMAT_FEATURE)
    100 #undef VIXL_FORMAT_FEATURE
    101     case CPUFeatures::kNone:
    102       return os << "none";
    103     case CPUFeatures::kNumberOfFeatures:
    104       VIXL_UNREACHABLE();
    105   }
    106   // clang-format on
    107   VIXL_UNREACHABLE();
    108   return os;
    109 }
    110 
    111 CPUFeatures::const_iterator CPUFeatures::begin() const {
    112   // For iterators in general, it's undefined to increment `end()`, but here we
    113   // control the implementation and it is safe to do this.
    114   return ++end();
    115 }
    116 
    117 CPUFeatures::const_iterator CPUFeatures::end() const {
    118   return const_iterator(this, kNone);
    119 }
    120 
    121 std::ostream& operator<<(std::ostream& os, const CPUFeatures& features) {
    122   bool need_separator = false;
    123   for (CPUFeatures::Feature feature : features) {
    124     if (need_separator) os << ", ";
    125     need_separator = true;
    126     os << feature;
    127   }
    128   return os;
    129 }
    130 
    131 bool CPUFeaturesConstIterator::operator==(
    132     const CPUFeaturesConstIterator& other) const {
    133   VIXL_ASSERT(IsValid());
    134   return (cpu_features_ == other.cpu_features_) && (feature_ == other.feature_);
    135 }
    136 
    137 CPUFeaturesConstIterator& CPUFeaturesConstIterator::operator++() {  // Prefix
    138   VIXL_ASSERT(IsValid());
    139   do {
    140     // Find the next feature. The order is unspecified.
    141     feature_ = static_cast<CPUFeatures::Feature>(feature_ + 1);
    142     if (feature_ == CPUFeatures::kNumberOfFeatures) {
    143       feature_ = CPUFeatures::kNone;
    144       VIXL_STATIC_ASSERT(CPUFeatures::kNone == -1);
    145     }
    146     VIXL_ASSERT(CPUFeatures::kNone <= feature_);
    147     VIXL_ASSERT(feature_ < CPUFeatures::kNumberOfFeatures);
    148     // cpu_features_->Has(kNone) is always true, so this will terminate even if
    149     // the features list is empty.
    150   } while (!cpu_features_->Has(feature_));
    151   return *this;
    152 }
    153 
    154 CPUFeaturesConstIterator CPUFeaturesConstIterator::operator++(int) {  // Postfix
    155   CPUFeaturesConstIterator result = *this;
    156   ++(*this);
    157   return result;
    158 }
    159 
    160 }  // namespace vixl