• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <ostream>
28 
29 #include "cpu-features.h"
30 #include "globals-vixl.h"
31 #include "utils-vixl.h"
32 
33 #if defined(__aarch64__) && defined(VIXL_INCLUDE_TARGET_AARCH64)
34 #include "aarch64/cpu-aarch64.h"
35 #define VIXL_USE_AARCH64_CPU_HELPERS
36 #endif
37 
38 namespace vixl {
39 
All()40 CPUFeatures CPUFeatures::All() {
41   CPUFeatures all;
42   all.features_.set();
43   return all;
44 }
45 
InferFromIDRegisters()46 CPUFeatures CPUFeatures::InferFromIDRegisters() {
47   // This function assumes that kIDRegisterEmulation is available.
48   CPUFeatures features(CPUFeatures::kIDRegisterEmulation);
49 #ifdef VIXL_USE_AARCH64_CPU_HELPERS
50   // Note that the Linux kernel filters these values during emulation, so the
51   // results may not exactly match the expected hardware support.
52   features.Combine(aarch64::CPU::InferCPUFeaturesFromIDRegisters());
53 #endif
54   return features;
55 }
56 
InferFromOS(QueryIDRegistersOption option)57 CPUFeatures CPUFeatures::InferFromOS(QueryIDRegistersOption option) {
58 #ifdef VIXL_USE_AARCH64_CPU_HELPERS
59   return aarch64::CPU::InferCPUFeaturesFromOS(option);
60 #else
61   USE(option);
62   return CPUFeatures();
63 #endif
64 }
65 
Combine(const CPUFeatures & other)66 void CPUFeatures::Combine(const CPUFeatures& other) {
67   features_ |= other.features_;
68 }
69 
Combine(Feature feature)70 void CPUFeatures::Combine(Feature feature) {
71   if (feature != CPUFeatures::kNone) features_.set(feature);
72 }
73 
Remove(const CPUFeatures & other)74 void CPUFeatures::Remove(const CPUFeatures& other) {
75   features_ &= ~other.features_;
76 }
77 
Remove(Feature feature)78 void CPUFeatures::Remove(Feature feature) {
79   if (feature != CPUFeatures::kNone) features_.reset(feature);
80 }
81 
Has(const CPUFeatures & other) const82 bool CPUFeatures::Has(const CPUFeatures& other) const {
83   return (features_ & other.features_) == other.features_;
84 }
85 
Has(Feature feature) const86 bool CPUFeatures::Has(Feature feature) const {
87   return (feature == CPUFeatures::kNone) || features_[feature];
88 }
89 
Count() const90 size_t CPUFeatures::Count() const { return features_.count(); }
91 
operator <<(std::ostream & os,CPUFeatures::Feature feature)92 std::ostream& operator<<(std::ostream& os, CPUFeatures::Feature feature) {
93   // clang-format off
94   switch (feature) {
95 #define VIXL_FORMAT_FEATURE(SYMBOL, NAME, CPUINFO) \
96     case CPUFeatures::SYMBOL:                      \
97       return os << NAME;
98 VIXL_CPU_FEATURE_LIST(VIXL_FORMAT_FEATURE)
99 #undef VIXL_FORMAT_FEATURE
100     case CPUFeatures::kNone:
101       return os << "none";
102     case CPUFeatures::kNumberOfFeatures:
103       VIXL_UNREACHABLE();
104   }
105   // clang-format on
106   VIXL_UNREACHABLE();
107   return os;
108 }
109 
begin() const110 CPUFeatures::const_iterator CPUFeatures::begin() const {
111   // For iterators in general, it's undefined to increment `end()`, but here we
112   // control the implementation and it is safe to do this.
113   return ++end();
114 }
115 
end() const116 CPUFeatures::const_iterator CPUFeatures::end() const {
117   return const_iterator(this, kNone);
118 }
119 
operator <<(std::ostream & os,const CPUFeatures & features)120 std::ostream& operator<<(std::ostream& os, const CPUFeatures& features) {
121   bool need_separator = false;
122   for (CPUFeatures::Feature feature : features) {
123     if (need_separator) os << ", ";
124     need_separator = true;
125     os << feature;
126   }
127   return os;
128 }
129 
operator ==(const CPUFeaturesConstIterator & other) const130 bool CPUFeaturesConstIterator::operator==(
131     const CPUFeaturesConstIterator& other) const {
132   VIXL_ASSERT(IsValid());
133   return (cpu_features_ == other.cpu_features_) && (feature_ == other.feature_);
134 }
135 
operator ++()136 CPUFeaturesConstIterator& CPUFeaturesConstIterator::operator++() {  // Prefix
137   VIXL_ASSERT(IsValid());
138   do {
139     // Find the next feature. The order is unspecified.
140     feature_ = static_cast<CPUFeatures::Feature>(feature_ + 1);
141     if (feature_ == CPUFeatures::kNumberOfFeatures) {
142       feature_ = CPUFeatures::kNone;
143       VIXL_STATIC_ASSERT(CPUFeatures::kNone == -1);
144     }
145     VIXL_ASSERT(CPUFeatures::kNone <= feature_);
146     VIXL_ASSERT(feature_ < CPUFeatures::kNumberOfFeatures);
147     // cpu_features_->Has(kNone) is always true, so this will terminate even if
148     // the features list is empty.
149   } while (!cpu_features_->Has(feature_));
150   return *this;
151 }
152 
operator ++(int)153 CPUFeaturesConstIterator CPUFeaturesConstIterator::operator++(int) {  // Postfix
154   CPUFeaturesConstIterator result = *this;
155   ++(*this);
156   return result;
157 }
158 
159 }  // namespace vixl
160