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