blob: e1bd0f15d4d3bb6fece52070af7fe89c2a6b9a28 [file] [log] [blame]
Jacob Bramley2af191d2018-05-16 10:22:44 +01001// 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
mmc28a1a2c1d32024-02-01 16:43:49 +000027#include "cpu-features.h"
28
Jacob Bramley2af191d2018-05-16 10:22:44 +010029#include <ostream>
30
Jacob Bramley2af191d2018-05-16 10:22:44 +010031#include "globals-vixl.h"
32#include "utils-vixl.h"
33
Jacob Bramley48934322019-02-04 18:27:53 +000034#if defined(__aarch64__) && defined(VIXL_INCLUDE_TARGET_AARCH64)
35#include "aarch64/cpu-aarch64.h"
36#define VIXL_USE_AARCH64_CPU_HELPERS
37#endif
38
Jacob Bramley2af191d2018-05-16 10:22:44 +010039namespace vixl {
40
Jacob Bramley2af191d2018-05-16 10:22:44 +010041CPUFeatures CPUFeatures::All() {
42 CPUFeatures all;
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010043 all.features_.set();
Jacob Bramley2af191d2018-05-16 10:22:44 +010044 return all;
45}
46
Jacob Bramley48934322019-02-04 18:27:53 +000047CPUFeatures 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
58CPUFeatures CPUFeatures::InferFromOS(QueryIDRegistersOption option) {
59#ifdef VIXL_USE_AARCH64_CPU_HELPERS
60 return aarch64::CPU::InferCPUFeaturesFromOS(option);
61#else
62 USE(option);
Jacob Bramley2af191d2018-05-16 10:22:44 +010063 return CPUFeatures();
Jacob Bramley48934322019-02-04 18:27:53 +000064#endif
Jacob Bramley2af191d2018-05-16 10:22:44 +010065}
66
67void CPUFeatures::Combine(const CPUFeatures& other) {
68 features_ |= other.features_;
69}
70
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010071void CPUFeatures::Combine(Feature feature) {
72 if (feature != CPUFeatures::kNone) features_.set(feature);
Jacob Bramley2af191d2018-05-16 10:22:44 +010073}
74
75void CPUFeatures::Remove(const CPUFeatures& other) {
76 features_ &= ~other.features_;
77}
78
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010079void CPUFeatures::Remove(Feature feature) {
80 if (feature != CPUFeatures::kNone) features_.reset(feature);
Jacob Bramley2af191d2018-05-16 10:22:44 +010081}
82
83bool CPUFeatures::Has(const CPUFeatures& other) const {
84 return (features_ & other.features_) == other.features_;
85}
86
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010087bool CPUFeatures::Has(Feature feature) const {
88 return (feature == CPUFeatures::kNone) || features_[feature];
Jacob Bramley2af191d2018-05-16 10:22:44 +010089}
90
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010091size_t CPUFeatures::Count() const { return features_.count(); }
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010092
Jacob Bramley2af191d2018-05-16 10:22:44 +010093std::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;
99VIXL_CPU_FEATURE_LIST(VIXL_FORMAT_FEATURE)
100#undef VIXL_FORMAT_FEATURE
101 case CPUFeatures::kNone:
102 return os << "none";
Jacob Bramleyfdf332a2018-09-17 11:17:54 +0100103 case CPUFeatures::kNumberOfFeatures:
104 VIXL_UNREACHABLE();
Jacob Bramley2af191d2018-05-16 10:22:44 +0100105 }
106 // clang-format on
107 VIXL_UNREACHABLE();
108 return os;
109}
110
111CPUFeatures::const_iterator CPUFeatures::begin() const {
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100112 // 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();
Jacob Bramley2af191d2018-05-16 10:22:44 +0100115}
116
117CPUFeatures::const_iterator CPUFeatures::end() const {
118 return const_iterator(this, kNone);
119}
120
121std::ostream& operator<<(std::ostream& os, const CPUFeatures& features) {
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100122 bool need_separator = false;
123 for (CPUFeatures::Feature feature : features) {
124 if (need_separator) os << ", ";
125 need_separator = true;
126 os << feature;
Jacob Bramley2af191d2018-05-16 10:22:44 +0100127 }
128 return os;
129}
130
131bool CPUFeaturesConstIterator::operator==(
132 const CPUFeaturesConstIterator& other) const {
133 VIXL_ASSERT(IsValid());
134 return (cpu_features_ == other.cpu_features_) && (feature_ == other.feature_);
135}
136
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100137CPUFeaturesConstIterator& CPUFeaturesConstIterator::operator++() { // Prefix
Jacob Bramley2af191d2018-05-16 10:22:44 +0100138 VIXL_ASSERT(IsValid());
139 do {
140 // Find the next feature. The order is unspecified.
Jacob Bramleyfdf332a2018-09-17 11:17:54 +0100141 feature_ = static_cast<CPUFeatures::Feature>(feature_ + 1);
142 if (feature_ == CPUFeatures::kNumberOfFeatures) {
143 feature_ = CPUFeatures::kNone;
144 VIXL_STATIC_ASSERT(CPUFeatures::kNone == -1);
Jacob Bramley2af191d2018-05-16 10:22:44 +0100145 }
Jacob Bramleyfdf332a2018-09-17 11:17:54 +0100146 VIXL_ASSERT(CPUFeatures::kNone <= feature_);
147 VIXL_ASSERT(feature_ < CPUFeatures::kNumberOfFeatures);
Jacob Bramley2af191d2018-05-16 10:22:44 +0100148 // 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_));
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100151 return *this;
Jacob Bramley2af191d2018-05-16 10:22:44 +0100152}
153
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100154CPUFeaturesConstIterator CPUFeaturesConstIterator::operator++(int) { // Postfix
155 CPUFeaturesConstIterator result = *this;
Jacob Bramley2af191d2018-05-16 10:22:44 +0100156 ++(*this);
157 return result;
158}
159
160} // namespace vixl