blob: 08db3f44b9a6564495322b934ae29299c377cfe0 [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
27#include <ostream>
28
29#include "cpu-features.h"
30#include "globals-vixl.h"
31#include "utils-vixl.h"
32
Jacob Bramley48934322019-02-04 18:27:53 +000033#if defined(__aarch64__) && defined(VIXL_INCLUDE_TARGET_AARCH64)
34#include "aarch64/cpu-aarch64.h"
35#define VIXL_USE_AARCH64_CPU_HELPERS
36#endif
37
Jacob Bramley2af191d2018-05-16 10:22:44 +010038namespace vixl {
39
Jacob Bramley2af191d2018-05-16 10:22:44 +010040CPUFeatures CPUFeatures::All() {
41 CPUFeatures all;
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010042 all.features_.set();
Jacob Bramley2af191d2018-05-16 10:22:44 +010043 return all;
44}
45
Jacob Bramley48934322019-02-04 18:27:53 +000046CPUFeatures 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
57CPUFeatures CPUFeatures::InferFromOS(QueryIDRegistersOption option) {
58#ifdef VIXL_USE_AARCH64_CPU_HELPERS
59 return aarch64::CPU::InferCPUFeaturesFromOS(option);
60#else
61 USE(option);
Jacob Bramley2af191d2018-05-16 10:22:44 +010062 return CPUFeatures();
Jacob Bramley48934322019-02-04 18:27:53 +000063#endif
Jacob Bramley2af191d2018-05-16 10:22:44 +010064}
65
66void CPUFeatures::Combine(const CPUFeatures& other) {
67 features_ |= other.features_;
68}
69
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010070void CPUFeatures::Combine(Feature feature) {
71 if (feature != CPUFeatures::kNone) features_.set(feature);
Jacob Bramley2af191d2018-05-16 10:22:44 +010072}
73
74void CPUFeatures::Remove(const CPUFeatures& other) {
75 features_ &= ~other.features_;
76}
77
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010078void CPUFeatures::Remove(Feature feature) {
79 if (feature != CPUFeatures::kNone) features_.reset(feature);
Jacob Bramley2af191d2018-05-16 10:22:44 +010080}
81
82bool CPUFeatures::Has(const CPUFeatures& other) const {
83 return (features_ & other.features_) == other.features_;
84}
85
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010086bool CPUFeatures::Has(Feature feature) const {
87 return (feature == CPUFeatures::kNone) || features_[feature];
Jacob Bramley2af191d2018-05-16 10:22:44 +010088}
89
Jacob Bramley8c4ceb62020-07-08 20:53:32 +010090size_t CPUFeatures::Count() const { return features_.count(); }
Jacob Bramleyc44ce3d2018-06-12 15:39:09 +010091
Jacob Bramley2af191d2018-05-16 10:22:44 +010092std::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;
98VIXL_CPU_FEATURE_LIST(VIXL_FORMAT_FEATURE)
99#undef VIXL_FORMAT_FEATURE
100 case CPUFeatures::kNone:
101 return os << "none";
Jacob Bramleyfdf332a2018-09-17 11:17:54 +0100102 case CPUFeatures::kNumberOfFeatures:
103 VIXL_UNREACHABLE();
Jacob Bramley2af191d2018-05-16 10:22:44 +0100104 }
105 // clang-format on
106 VIXL_UNREACHABLE();
107 return os;
108}
109
110CPUFeatures::const_iterator CPUFeatures::begin() const {
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100111 // 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();
Jacob Bramley2af191d2018-05-16 10:22:44 +0100114}
115
116CPUFeatures::const_iterator CPUFeatures::end() const {
117 return const_iterator(this, kNone);
118}
119
120std::ostream& operator<<(std::ostream& os, const CPUFeatures& features) {
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100121 bool need_separator = false;
122 for (CPUFeatures::Feature feature : features) {
123 if (need_separator) os << ", ";
124 need_separator = true;
125 os << feature;
Jacob Bramley2af191d2018-05-16 10:22:44 +0100126 }
127 return os;
128}
129
130bool CPUFeaturesConstIterator::operator==(
131 const CPUFeaturesConstIterator& other) const {
132 VIXL_ASSERT(IsValid());
133 return (cpu_features_ == other.cpu_features_) && (feature_ == other.feature_);
134}
135
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100136CPUFeaturesConstIterator& CPUFeaturesConstIterator::operator++() { // Prefix
Jacob Bramley2af191d2018-05-16 10:22:44 +0100137 VIXL_ASSERT(IsValid());
138 do {
139 // Find the next feature. The order is unspecified.
Jacob Bramleyfdf332a2018-09-17 11:17:54 +0100140 feature_ = static_cast<CPUFeatures::Feature>(feature_ + 1);
141 if (feature_ == CPUFeatures::kNumberOfFeatures) {
142 feature_ = CPUFeatures::kNone;
143 VIXL_STATIC_ASSERT(CPUFeatures::kNone == -1);
Jacob Bramley2af191d2018-05-16 10:22:44 +0100144 }
Jacob Bramleyfdf332a2018-09-17 11:17:54 +0100145 VIXL_ASSERT(CPUFeatures::kNone <= feature_);
146 VIXL_ASSERT(feature_ < CPUFeatures::kNumberOfFeatures);
Jacob Bramley2af191d2018-05-16 10:22:44 +0100147 // 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_));
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100150 return *this;
Jacob Bramley2af191d2018-05-16 10:22:44 +0100151}
152
Jacob Bramleycaa40ee2020-07-08 20:46:38 +0100153CPUFeaturesConstIterator CPUFeaturesConstIterator::operator++(int) { // Postfix
154 CPUFeaturesConstIterator result = *this;
Jacob Bramley2af191d2018-05-16 10:22:44 +0100155 ++(*this);
156 return result;
157}
158
159} // namespace vixl