1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBARTBASE_BASE_BIT_FIELD_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_LIBARTBASE_BASE_BIT_FIELD_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h> 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker #include "globals.h" 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker namespace art { 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker static constexpr uintptr_t kUintPtrTOne = 1U; 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker // BitField is a template for encoding and decoding a bit field inside 29*795d594fSAndroid Build Coastguard Worker // an unsigned machine word. 30*795d594fSAndroid Build Coastguard Worker template<typename T, size_t kPosition, size_t kSize> 31*795d594fSAndroid Build Coastguard Worker class BitField { 32*795d594fSAndroid Build Coastguard Worker public: 33*795d594fSAndroid Build Coastguard Worker using value_type = T; 34*795d594fSAndroid Build Coastguard Worker static constexpr size_t position = kPosition; 35*795d594fSAndroid Build Coastguard Worker static constexpr size_t size = kSize; 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker static_assert(position < sizeof(uintptr_t) * kBitsPerByte, "Invalid position."); 38*795d594fSAndroid Build Coastguard Worker static_assert(size != 0u, "Invalid size."); 39*795d594fSAndroid Build Coastguard Worker static_assert(size <= sizeof(uintptr_t) * kBitsPerByte, "Invalid size."); 40*795d594fSAndroid Build Coastguard Worker static_assert(size + position <= sizeof(uintptr_t) * kBitsPerByte, "Invalid position + size."); 41*795d594fSAndroid Build Coastguard Worker 42*795d594fSAndroid Build Coastguard Worker // Tells whether the provided value fits into the bit field. IsValid(T value)43*795d594fSAndroid Build Coastguard Worker static constexpr bool IsValid(T value) { 44*795d594fSAndroid Build Coastguard Worker return (static_cast<uintptr_t>(value) & ~((kUintPtrTOne << size) - 1)) == 0; 45*795d594fSAndroid Build Coastguard Worker } 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker // Returns a uword mask of the bit field. Mask()48*795d594fSAndroid Build Coastguard Worker static constexpr uintptr_t Mask() { 49*795d594fSAndroid Build Coastguard Worker return (kUintPtrTOne << size) - 1; 50*795d594fSAndroid Build Coastguard Worker } 51*795d594fSAndroid Build Coastguard Worker 52*795d594fSAndroid Build Coastguard Worker // Returns a uword mask of the bit field which can be applied directly to 53*795d594fSAndroid Build Coastguard Worker // the raw unshifted bits. MaskInPlace()54*795d594fSAndroid Build Coastguard Worker static constexpr uintptr_t MaskInPlace() { 55*795d594fSAndroid Build Coastguard Worker return ((kUintPtrTOne << size) - 1) << position; 56*795d594fSAndroid Build Coastguard Worker } 57*795d594fSAndroid Build Coastguard Worker 58*795d594fSAndroid Build Coastguard Worker // Returns the shift count needed to right-shift the bit field to 59*795d594fSAndroid Build Coastguard Worker // the least-significant bits. Shift()60*795d594fSAndroid Build Coastguard Worker static constexpr int Shift() { 61*795d594fSAndroid Build Coastguard Worker return position; 62*795d594fSAndroid Build Coastguard Worker } 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker // Returns the size of the bit field. BitSize()65*795d594fSAndroid Build Coastguard Worker static constexpr int BitSize() { 66*795d594fSAndroid Build Coastguard Worker return size; 67*795d594fSAndroid Build Coastguard Worker } 68*795d594fSAndroid Build Coastguard Worker 69*795d594fSAndroid Build Coastguard Worker // Returns a uword with the bit field value encoded. Encode(T value)70*795d594fSAndroid Build Coastguard Worker static constexpr uintptr_t Encode(T value) { 71*795d594fSAndroid Build Coastguard Worker DCHECK(IsValid(value)); 72*795d594fSAndroid Build Coastguard Worker return static_cast<uintptr_t>(value) << position; 73*795d594fSAndroid Build Coastguard Worker } 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker // Extracts the bit field from the value. Decode(uintptr_t value)76*795d594fSAndroid Build Coastguard Worker static constexpr T Decode(uintptr_t value) { 77*795d594fSAndroid Build Coastguard Worker return static_cast<T>((value >> position) & ((kUintPtrTOne << size) - 1)); 78*795d594fSAndroid Build Coastguard Worker } 79*795d594fSAndroid Build Coastguard Worker 80*795d594fSAndroid Build Coastguard Worker // Returns a uword with the bit field value encoded based on the 81*795d594fSAndroid Build Coastguard Worker // original value. Only the bits corresponding to this bit field 82*795d594fSAndroid Build Coastguard Worker // will be changed. Update(T value,uintptr_t original)83*795d594fSAndroid Build Coastguard Worker static constexpr uintptr_t Update(T value, uintptr_t original) { 84*795d594fSAndroid Build Coastguard Worker DCHECK(IsValid(value)); 85*795d594fSAndroid Build Coastguard Worker return (static_cast<uintptr_t>(value) << position) | 86*795d594fSAndroid Build Coastguard Worker (~MaskInPlace() & original); 87*795d594fSAndroid Build Coastguard Worker } 88*795d594fSAndroid Build Coastguard Worker }; 89*795d594fSAndroid Build Coastguard Worker 90*795d594fSAndroid Build Coastguard Worker } // namespace art 91*795d594fSAndroid Build Coastguard Worker 92*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBARTBASE_BASE_BIT_FIELD_H_ 93