1 // AsmJit - Machine code generation for C++
2 //
3 //  * Official AsmJit Home Page: https://asmjit.com
4 //  * Official Github Repository: https://github.com/asmjit/asmjit
5 //
6 // Copyright (c) 2008-2020 The AsmJit Authors
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 //    claim that you wrote the original software. If you use this software
18 //    in a product, an acknowledgment in the product documentation would be
19 //    appreciated but is not required.
20 // 2. Altered source versions must be plainly marked as such, and must not be
21 //    misrepresented as being the original software.
22 // 3. This notice may not be removed or altered from any source distribution.
23 
24 #ifndef ASMJIT_CORE_FEATURES_H_INCLUDED
25 #define ASMJIT_CORE_FEATURES_H_INCLUDED
26 
27 #include "../core/globals.h"
28 #include "../core/support.h"
29 
30 ASMJIT_BEGIN_NAMESPACE
31 
32 //! \addtogroup asmjit_core
33 //! \{
34 
35 // ============================================================================
36 // [asmjit::BaseFeatures]
37 // ============================================================================
38 
39 //! Base class that provides information about CPU features.
40 //!
41 //! Internally each feature is represented by a single bit in an embedded
42 //! bit-array, however, feature bits are defined by an architecture specific
43 //! implementations, like \ref x86::Features.
44 class BaseFeatures {
45 public:
46   typedef Support::BitWord BitWord;
47   typedef Support::BitVectorIterator<BitWord> Iterator;
48 
49   enum : uint32_t {
50     kMaxFeatures = 256,
51     kNumBitWords = kMaxFeatures / Support::kBitWordSizeInBits
52   };
53 
54   BitWord _bits[kNumBitWords];
55 
56   //! \name Construction & Destruction
57   //! \{
58 
BaseFeatures()59   inline BaseFeatures() noexcept { reset(); }
60   inline BaseFeatures(const BaseFeatures& other) noexcept = default;
BaseFeatures(Globals::NoInit_)61   inline explicit BaseFeatures(Globals::NoInit_) noexcept {}
62 
reset()63   inline void reset() noexcept {
64     for (size_t i = 0; i < kNumBitWords; i++)
65       _bits[i] = 0;
66   }
67 
68   //! \}
69 
70   //! \name Overloaded Operators
71   //! \{
72 
73   inline BaseFeatures& operator=(const BaseFeatures& other) noexcept = default;
74 
75   inline bool operator==(const BaseFeatures& other) noexcept { return  eq(other); }
76   inline bool operator!=(const BaseFeatures& other) noexcept { return !eq(other); }
77 
78   //! \}
79 
80   //! \name Cast
81   //! \{
82 
83   //! Casts this base class into a derived type `T`.
84   template<typename T>
as()85   inline T& as() noexcept { return static_cast<T&>(*this); }
86 
87   //! Casts this base class into a derived type `T` (const).
88   template<typename T>
as()89   inline const T& as() const noexcept { return static_cast<const T&>(*this); }
90 
91   //! \}
92 
93   //! \name Accessors
94   //! \{
95 
empty()96   inline bool empty() const noexcept {
97     for (uint32_t i = 0; i < kNumBitWords; i++)
98       if (_bits[i])
99         return false;
100     return true;
101   }
102 
103   //! Returns all features as array of bitwords (see \ref Support::BitWord).
bits()104   inline BitWord* bits() noexcept { return _bits; }
105   //! Returns all features as array of bitwords (const).
bits()106   inline const BitWord* bits() const noexcept { return _bits; }
107 
108   //! Returns the number of BitWords returned by \ref bits().
bitWordCount()109   inline size_t bitWordCount() const noexcept { return kNumBitWords; }
110 
111   //! Returns \ref Support::BitVectorIterator, that can be used to iterate
112   //! all features efficiently
iterator()113   inline Iterator iterator() const noexcept {
114     return Iterator(_bits, kNumBitWords);
115   }
116 
117   //! Tests whether the feature `featureId` is present.
has(uint32_t featureId)118   inline bool has(uint32_t featureId) const noexcept {
119     ASMJIT_ASSERT(featureId < kMaxFeatures);
120 
121     uint32_t idx = featureId / Support::kBitWordSizeInBits;
122     uint32_t bit = featureId % Support::kBitWordSizeInBits;
123 
124     return bool((_bits[idx] >> bit) & 0x1);
125   }
126 
127   //! Tests whether all features as defined by `other` are present.
hasAll(const BaseFeatures & other)128   inline bool hasAll(const BaseFeatures& other) const noexcept {
129     for (uint32_t i = 0; i < kNumBitWords; i++)
130       if ((_bits[i] & other._bits[i]) != other._bits[i])
131         return false;
132     return true;
133   }
134 
135   //! \}
136 
137   //! \name Utilities
138   //! \{
139 
140   //! Adds the given CPU `featureId` to the list of features.
add(uint32_t featureId)141   inline void add(uint32_t featureId) noexcept {
142     ASMJIT_ASSERT(featureId < kMaxFeatures);
143 
144     uint32_t idx = featureId / Support::kBitWordSizeInBits;
145     uint32_t bit = featureId % Support::kBitWordSizeInBits;
146 
147     _bits[idx] |= BitWord(1) << bit;
148   }
149 
150   template<typename... Args>
add(uint32_t featureId,Args...otherIds)151   inline void add(uint32_t featureId, Args... otherIds) noexcept {
152     add(featureId);
153     add(otherIds...);
154   }
155 
156   //! Removes the given CPU `featureId` from the list of features.
remove(uint32_t featureId)157   inline void remove(uint32_t featureId) noexcept {
158     ASMJIT_ASSERT(featureId < kMaxFeatures);
159 
160     uint32_t idx = featureId / Support::kBitWordSizeInBits;
161     uint32_t bit = featureId % Support::kBitWordSizeInBits;
162 
163     _bits[idx] &= ~(BitWord(1) << bit);
164   }
165 
166   template<typename... Args>
remove(uint32_t featureId,Args...otherIds)167   inline void remove(uint32_t featureId, Args... otherIds) noexcept {
168     remove(featureId);
169     remove(otherIds...);
170   }
171 
eq(const BaseFeatures & other)172   inline bool eq(const BaseFeatures& other) const noexcept {
173     for (size_t i = 0; i < kNumBitWords; i++)
174       if (_bits[i] != other._bits[i])
175         return false;
176     return true;
177   }
178 
179   //! \}
180 };
181 
182 //! \}
183 
184 ASMJIT_END_NAMESPACE
185 
186 #endif // ASMJIT_CORE_FEATURES_H_INCLUDED
187