1b1994897Sopenharmony_ci/** 2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License. 5b1994897Sopenharmony_ci * You may obtain a copy of the License at 6b1994897Sopenharmony_ci * 7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1994897Sopenharmony_ci * 9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and 13b1994897Sopenharmony_ci * limitations under the License. 14b1994897Sopenharmony_ci */ 15b1994897Sopenharmony_ci 16b1994897Sopenharmony_ci#ifndef LIBPANDABASE_UTILS_REGMASK_H 17b1994897Sopenharmony_ci#define LIBPANDABASE_UTILS_REGMASK_H 18b1994897Sopenharmony_ci 19b1994897Sopenharmony_ci#include <array> 20b1994897Sopenharmony_ci#include "utils/bit_utils.h" 21b1994897Sopenharmony_ci#include "utils/type_helpers.h" 22b1994897Sopenharmony_ci 23b1994897Sopenharmony_cinamespace panda { 24b1994897Sopenharmony_ci 25b1994897Sopenharmony_citemplate <typename T, size_t N> 26b1994897Sopenharmony_cistatic constexpr size_t MakeMask(const std::array<T, N> &indexes) 27b1994897Sopenharmony_ci{ 28b1994897Sopenharmony_ci size_t res = 0; 29b1994897Sopenharmony_ci for (size_t i : indexes) { 30b1994897Sopenharmony_ci res |= (1UL << i); 31b1994897Sopenharmony_ci } 32b1994897Sopenharmony_ci return res; 33b1994897Sopenharmony_ci} 34b1994897Sopenharmony_ci 35b1994897Sopenharmony_citemplate <typename... Indexes> 36b1994897Sopenharmony_cistatic constexpr size_t MakeMask(Indexes... indexes) 37b1994897Sopenharmony_ci{ 38b1994897Sopenharmony_ci return ((1UL << helpers::ToUnsigned(indexes)) | ...); 39b1994897Sopenharmony_ci} 40b1994897Sopenharmony_ci 41b1994897Sopenharmony_citemplate <typename... Indexes> 42b1994897Sopenharmony_cistatic constexpr size_t MakeMaskByExcluding(size_t width, Indexes... indexes) 43b1994897Sopenharmony_ci{ 44b1994897Sopenharmony_ci size_t res = (1ULL << width) - 1; 45b1994897Sopenharmony_ci size_t exclude = ((1ULL << helpers::ToUnsigned(indexes)) | ...); 46b1994897Sopenharmony_ci return res & ~exclude; 47b1994897Sopenharmony_ci} 48b1994897Sopenharmony_ci 49b1994897Sopenharmony_ci/** 50b1994897Sopenharmony_ci * Base struct for registers mask, template-parametrized by number of registers. 51b1994897Sopenharmony_ci * Currently we don't support registers number greater than 32. 52b1994897Sopenharmony_ci * Previously, Regmask class just inherited std::bitset, but std::bitset has poor constexpr support, that was the main 53b1994897Sopenharmony_ci * reason to implement own RegMask class. 54b1994897Sopenharmony_ci * Regmask has interface, similar to std::bitset. 55b1994897Sopenharmony_ci */ 56b1994897Sopenharmony_citemplate <size_t N> 57b1994897Sopenharmony_ciclass RegMaskImpl { 58b1994897Sopenharmony_cipublic: 59b1994897Sopenharmony_ci // We don't support architectures with CPU registers number, greater than 32. 60b1994897Sopenharmony_ci static_assert(N <= sizeof(uint32_t) * BITS_PER_BYTE); 61b1994897Sopenharmony_ci 62b1994897Sopenharmony_ci using ValueType = uint32_t; 63b1994897Sopenharmony_ci using Self = RegMaskImpl<N>; 64b1994897Sopenharmony_ci 65b1994897Sopenharmony_ci constexpr RegMaskImpl() = default; 66b1994897Sopenharmony_ci 67b1994897Sopenharmony_ci // NOLINTNEXTLINE(google-explicit-constructor) 68b1994897Sopenharmony_ci constexpr RegMaskImpl(ValueType v) : value_(v) {} 69b1994897Sopenharmony_ci 70b1994897Sopenharmony_ci constexpr ValueType GetValue() const 71b1994897Sopenharmony_ci { 72b1994897Sopenharmony_ci return value_; 73b1994897Sopenharmony_ci } 74b1994897Sopenharmony_ci 75b1994897Sopenharmony_ci static constexpr size_t Size() 76b1994897Sopenharmony_ci { 77b1994897Sopenharmony_ci return N; 78b1994897Sopenharmony_ci } 79b1994897Sopenharmony_ci 80b1994897Sopenharmony_ci constexpr bool Any() const 81b1994897Sopenharmony_ci { 82b1994897Sopenharmony_ci return value_ != 0; 83b1994897Sopenharmony_ci } 84b1994897Sopenharmony_ci 85b1994897Sopenharmony_ci constexpr bool None() const 86b1994897Sopenharmony_ci { 87b1994897Sopenharmony_ci return value_ == 0; 88b1994897Sopenharmony_ci } 89b1994897Sopenharmony_ci 90b1994897Sopenharmony_ci constexpr bool Test(size_t bit) const 91b1994897Sopenharmony_ci { 92b1994897Sopenharmony_ci ASSERT(bit < Size()); 93b1994897Sopenharmony_ci return ((value_ >> static_cast<ValueType>(bit)) & 1U) != 0; 94b1994897Sopenharmony_ci } 95b1994897Sopenharmony_ci 96b1994897Sopenharmony_ci constexpr void Set() 97b1994897Sopenharmony_ci { 98b1994897Sopenharmony_ci value_ = ~static_cast<ValueType>(0U); 99b1994897Sopenharmony_ci } 100b1994897Sopenharmony_ci constexpr void Reset() 101b1994897Sopenharmony_ci { 102b1994897Sopenharmony_ci value_ = 0; 103b1994897Sopenharmony_ci } 104b1994897Sopenharmony_ci 105b1994897Sopenharmony_ci constexpr void Set(size_t bit) 106b1994897Sopenharmony_ci { 107b1994897Sopenharmony_ci ASSERT(bit < Size()); 108b1994897Sopenharmony_ci value_ |= (1U << bit); 109b1994897Sopenharmony_ci } 110b1994897Sopenharmony_ci 111b1994897Sopenharmony_ci constexpr void Set(size_t bit, bool value) 112b1994897Sopenharmony_ci { 113b1994897Sopenharmony_ci ASSERT(bit < Size()); 114b1994897Sopenharmony_ci if (value) { 115b1994897Sopenharmony_ci Set(bit); 116b1994897Sopenharmony_ci } else { 117b1994897Sopenharmony_ci Reset(bit); 118b1994897Sopenharmony_ci } 119b1994897Sopenharmony_ci } 120b1994897Sopenharmony_ci 121b1994897Sopenharmony_ci constexpr void Reset(size_t bit) 122b1994897Sopenharmony_ci { 123b1994897Sopenharmony_ci ASSERT(bit < Size()); 124b1994897Sopenharmony_ci value_ &= ~(1U << bit); 125b1994897Sopenharmony_ci } 126b1994897Sopenharmony_ci 127b1994897Sopenharmony_ci constexpr size_t Count() const 128b1994897Sopenharmony_ci { 129b1994897Sopenharmony_ci return Popcount(GetValue()); 130b1994897Sopenharmony_ci } 131b1994897Sopenharmony_ci 132b1994897Sopenharmony_ci constexpr bool CountIsEven() const 133b1994897Sopenharmony_ci { 134b1994897Sopenharmony_ci return (Count() & 1U) == 0; 135b1994897Sopenharmony_ci } 136b1994897Sopenharmony_ci 137b1994897Sopenharmony_ci // Get number of registers from tail to the given register, counting only set bits. 138b1994897Sopenharmony_ci // Given `reg` is not counted even if it is set. 139b1994897Sopenharmony_ci constexpr size_t GetDistanceFromTail(size_t reg) const 140b1994897Sopenharmony_ci { 141b1994897Sopenharmony_ci ASSERT(reg < Size()); 142b1994897Sopenharmony_ci uint32_t val = GetValue() & ((1U << reg) - 1); 143b1994897Sopenharmony_ci return Popcount(val); 144b1994897Sopenharmony_ci } 145b1994897Sopenharmony_ci 146b1994897Sopenharmony_ci // Get number of registers from head to the given register, counting only set bits. 147b1994897Sopenharmony_ci // Given `reg` is not counted even if it is set. 148b1994897Sopenharmony_ci constexpr size_t GetDistanceFromHead(size_t reg) const 149b1994897Sopenharmony_ci { 150b1994897Sopenharmony_ci if (reg < (Size() - 1)) { 151b1994897Sopenharmony_ci uint32_t val = GetValue() & ~((1U << (reg + 1)) - 1); 152b1994897Sopenharmony_ci return Popcount(val); 153b1994897Sopenharmony_ci } 154b1994897Sopenharmony_ci if (reg == Size() - 1) { 155b1994897Sopenharmony_ci return 0; 156b1994897Sopenharmony_ci } 157b1994897Sopenharmony_ci // reg > (Size() - 1), something goes wrong... 158b1994897Sopenharmony_ci UNREACHABLE(); 159b1994897Sopenharmony_ci return 0; 160b1994897Sopenharmony_ci } 161b1994897Sopenharmony_ci 162b1994897Sopenharmony_ci constexpr uint32_t GetMinRegister() const 163b1994897Sopenharmony_ci { 164b1994897Sopenharmony_ci ASSERT(Any()); 165b1994897Sopenharmony_ci return panda::Ctz(GetValue()); 166b1994897Sopenharmony_ci } 167b1994897Sopenharmony_ci 168b1994897Sopenharmony_ci constexpr uint32_t GetMaxRegister() const 169b1994897Sopenharmony_ci { 170b1994897Sopenharmony_ci ASSERT(Any()); 171b1994897Sopenharmony_ci return (sizeof(decltype(GetValue())) * BITS_PER_BYTE) - 1 - panda::Clz(GetValue()); 172b1994897Sopenharmony_ci } 173b1994897Sopenharmony_ci 174b1994897Sopenharmony_ci constexpr Self operator~() const 175b1994897Sopenharmony_ci { 176b1994897Sopenharmony_ci return Self(~GetValue()); 177b1994897Sopenharmony_ci } 178b1994897Sopenharmony_ci 179b1994897Sopenharmony_ci constexpr Self operator&(Self other) const 180b1994897Sopenharmony_ci { 181b1994897Sopenharmony_ci return Self(GetValue() & other.GetValue()); 182b1994897Sopenharmony_ci } 183b1994897Sopenharmony_ci 184b1994897Sopenharmony_ci constexpr Self operator|(Self other) const 185b1994897Sopenharmony_ci { 186b1994897Sopenharmony_ci return Self(GetValue() | other.GetValue()); 187b1994897Sopenharmony_ci } 188b1994897Sopenharmony_ci 189b1994897Sopenharmony_ci constexpr Self operator^(Self other) const 190b1994897Sopenharmony_ci { 191b1994897Sopenharmony_ci return Self(GetValue() ^ other.GetValue()); 192b1994897Sopenharmony_ci } 193b1994897Sopenharmony_ci 194b1994897Sopenharmony_ci constexpr Self operator&=(Self other) 195b1994897Sopenharmony_ci { 196b1994897Sopenharmony_ci value_ &= other.GetValue(); 197b1994897Sopenharmony_ci return *this; 198b1994897Sopenharmony_ci } 199b1994897Sopenharmony_ci 200b1994897Sopenharmony_ci constexpr Self operator|=(Self other) 201b1994897Sopenharmony_ci { 202b1994897Sopenharmony_ci value_ |= other.GetValue(); 203b1994897Sopenharmony_ci return *this; 204b1994897Sopenharmony_ci } 205b1994897Sopenharmony_ci 206b1994897Sopenharmony_ci constexpr Self operator^=(Self other) 207b1994897Sopenharmony_ci { 208b1994897Sopenharmony_ci value_ ^= other.GetValue(); 209b1994897Sopenharmony_ci return *this; 210b1994897Sopenharmony_ci } 211b1994897Sopenharmony_ci constexpr bool operator[](size_t bit) const 212b1994897Sopenharmony_ci { 213b1994897Sopenharmony_ci return Test(bit); 214b1994897Sopenharmony_ci } 215b1994897Sopenharmony_ci constexpr bool operator==(Self other) const 216b1994897Sopenharmony_ci { 217b1994897Sopenharmony_ci return value_ == other.value_; 218b1994897Sopenharmony_ci } 219b1994897Sopenharmony_ci 220b1994897Sopenharmony_ci constexpr bool operator!=(Self other) const 221b1994897Sopenharmony_ci { 222b1994897Sopenharmony_ci return !(*this == other); 223b1994897Sopenharmony_ci } 224b1994897Sopenharmony_ci 225b1994897Sopenharmony_ci constexpr ValueType to_ulong() const 226b1994897Sopenharmony_ci { 227b1994897Sopenharmony_ci return GetValue(); 228b1994897Sopenharmony_ci } 229b1994897Sopenharmony_ci 230b1994897Sopenharmony_ci void Dump(std::ostream &out = std::cerr) const 231b1994897Sopenharmony_ci { 232b1994897Sopenharmony_ci out << "Regmask[" << N << "]: "; 233b1994897Sopenharmony_ci for (size_t i = 0; i < N; i++) { 234b1994897Sopenharmony_ci if (Test(i)) { 235b1994897Sopenharmony_ci out << i << " "; 236b1994897Sopenharmony_ci } 237b1994897Sopenharmony_ci } 238b1994897Sopenharmony_ci } 239b1994897Sopenharmony_ci 240b1994897Sopenharmony_ci // The following methods are for compatibility with `std::bitset`, since we used `std::bitset` before. 241b1994897Sopenharmony_ci // Don't use these method in a new code. 242b1994897Sopenharmony_ci constexpr bool any() const 243b1994897Sopenharmony_ci { 244b1994897Sopenharmony_ci return Any(); 245b1994897Sopenharmony_ci } 246b1994897Sopenharmony_ci constexpr bool none() const 247b1994897Sopenharmony_ci { 248b1994897Sopenharmony_ci return None(); 249b1994897Sopenharmony_ci } 250b1994897Sopenharmony_ci constexpr bool test(size_t bit) const 251b1994897Sopenharmony_ci { 252b1994897Sopenharmony_ci return Test(bit); 253b1994897Sopenharmony_ci } 254b1994897Sopenharmony_ci constexpr void set(size_t bit) 255b1994897Sopenharmony_ci { 256b1994897Sopenharmony_ci Set(bit); 257b1994897Sopenharmony_ci } 258b1994897Sopenharmony_ci constexpr void set(size_t bit, bool value) 259b1994897Sopenharmony_ci { 260b1994897Sopenharmony_ci Set(bit, value); 261b1994897Sopenharmony_ci } 262b1994897Sopenharmony_ci constexpr Self set() 263b1994897Sopenharmony_ci { 264b1994897Sopenharmony_ci Set(); 265b1994897Sopenharmony_ci return *this; 266b1994897Sopenharmony_ci } 267b1994897Sopenharmony_ci constexpr Self reset() 268b1994897Sopenharmony_ci { 269b1994897Sopenharmony_ci Reset(); 270b1994897Sopenharmony_ci return *this; 271b1994897Sopenharmony_ci } 272b1994897Sopenharmony_ci constexpr void reset(size_t bit) 273b1994897Sopenharmony_ci { 274b1994897Sopenharmony_ci Reset(bit); 275b1994897Sopenharmony_ci } 276b1994897Sopenharmony_ci constexpr size_t count() const 277b1994897Sopenharmony_ci { 278b1994897Sopenharmony_ci return Count(); 279b1994897Sopenharmony_ci } 280b1994897Sopenharmony_ci constexpr size_t size() const 281b1994897Sopenharmony_ci { 282b1994897Sopenharmony_ci return Size(); 283b1994897Sopenharmony_ci } 284b1994897Sopenharmony_ci 285b1994897Sopenharmony_ciprivate: 286b1994897Sopenharmony_ci ValueType value_ {0}; 287b1994897Sopenharmony_ci}; 288b1994897Sopenharmony_ci 289b1994897Sopenharmony_cistatic constexpr uint8_t REGISTERS_NUM = 32; 290b1994897Sopenharmony_cistatic constexpr uint8_t VREGISTERS_NUM = 32; 291b1994897Sopenharmony_ci 292b1994897Sopenharmony_ciusing RegMask = RegMaskImpl<REGISTERS_NUM>; 293b1994897Sopenharmony_ciusing VRegMask = RegMaskImpl<VREGISTERS_NUM>; 294b1994897Sopenharmony_ci 295b1994897Sopenharmony_ciinline std::ostream &operator<<(std::ostream &stream, const RegMask &mask) 296b1994897Sopenharmony_ci{ 297b1994897Sopenharmony_ci mask.Dump(stream); 298b1994897Sopenharmony_ci return stream; 299b1994897Sopenharmony_ci} 300b1994897Sopenharmony_ci 301b1994897Sopenharmony_ci} // namespace panda 302b1994897Sopenharmony_ci 303b1994897Sopenharmony_ci#endif // LIBPANDABASE_UTILS_REGMASK_H 304