bitfield.hh revision 4661:44458219add1
12810SN/A/* 212724Snikos.nikoleris@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 38856Sandreas.hansson@arm.com * All rights reserved. 48856Sandreas.hansson@arm.com * 58856Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68856Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78856Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98856Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118856Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128856Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138856Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 142810SN/A * this software without specific prior written permission. 152810SN/A * 162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272810SN/A * 282810SN/A * Authors: Steve Reinhardt 292810SN/A * Nathan Binkert 302810SN/A */ 312810SN/A 322810SN/A#ifndef __BASE_BITFIELD_HH__ 332810SN/A#define __BASE_BITFIELD_HH__ 342810SN/A 352810SN/A#include <inttypes.h> 362810SN/A 372810SN/A/** 382810SN/A * Generate a 64-bit mask of 'nbits' 1s, right justified. 392810SN/A */ 402810SN/Ainline uint64_t 4112724Snikos.nikoleris@arm.commask(int nbits) 422810SN/A{ 432810SN/A return (nbits == 64) ? (uint64_t)-1LL : (1ULL << nbits) - 1; 442810SN/A} 452810SN/A 462810SN/A 472810SN/A 482810SN/A/** 4911486Snikos.nikoleris@arm.com * Extract the bitfield from position 'first' to 'last' (inclusive) 5011486Snikos.nikoleris@arm.com * from 'val' and right justify it. MSB is numbered 63, LSB is 0. 5112724Snikos.nikoleris@arm.com */ 5212724Snikos.nikoleris@arm.comtemplate <class T> 538232Snate@binkert.orginline 5412724Snikos.nikoleris@arm.comT 5513222Sodanrc@yahoo.com.brbits(T val, int first, int last) 5612724Snikos.nikoleris@arm.com{ 5711486Snikos.nikoleris@arm.com int nbits = first - last + 1; 5812724Snikos.nikoleris@arm.com return (val >> last) & mask(nbits); 5912724Snikos.nikoleris@arm.com} 6012724Snikos.nikoleris@arm.com 6113352Snikos.nikoleris@arm.com/** 6212724Snikos.nikoleris@arm.com * Extract the bit from this position from 'val' and right justify it. 6312724Snikos.nikoleris@arm.com */ 6412724Snikos.nikoleris@arm.comtemplate <class T> 6512724Snikos.nikoleris@arm.cominline 662810SN/AT 672810SN/Abits(T val, int bit) 682810SN/A{ 698856Sandreas.hansson@arm.com return bits(val, bit, bit); 708856Sandreas.hansson@arm.com} 718856Sandreas.hansson@arm.com 7213564Snikos.nikoleris@arm.com/** 7313564Snikos.nikoleris@arm.com * Mask off the given bits in place like bits() but without shifting. 7412084Sspwilson2@wisc.edu * msb = 63, lsb = 0 7512084Sspwilson2@wisc.edu */ 768856Sandreas.hansson@arm.comtemplate <class T> 778856Sandreas.hansson@arm.cominline 784475SN/AT 7911053Sandreas.hansson@arm.commbits(T val, int first, int last) 805034SN/A{ 8112724Snikos.nikoleris@arm.com return val & (mask(first+1) & ~mask(last)); 8212724Snikos.nikoleris@arm.com} 8311377Sandreas.hansson@arm.com 8411377Sandreas.hansson@arm.cominline uint64_t 8512724Snikos.nikoleris@arm.commask(int first, int last) 8612724Snikos.nikoleris@arm.com{ 8713352Snikos.nikoleris@arm.com return mbits((uint64_t)-1LL, first, last); 8812724Snikos.nikoleris@arm.com} 8912724Snikos.nikoleris@arm.com 9012724Snikos.nikoleris@arm.com/** 9112724Snikos.nikoleris@arm.com * Sign-extend an N-bit value to 64 bits. 9212724Snikos.nikoleris@arm.com */ 9311053Sandreas.hansson@arm.comtemplate <int N> 9411722Ssophiane.senni@gmail.cominline 9511722Ssophiane.senni@gmail.comint64_t 9611722Ssophiane.senni@gmail.comsext(uint64_t val) 9711722Ssophiane.senni@gmail.com{ 989263Smrinmoy.ghosh@arm.com int sign_bit = bits(val, N-1, N-1); 9913418Sodanrc@yahoo.com.br return sign_bit ? (val | ~mask(N)) : val; 1005034SN/A} 10111331Sandreas.hansson@arm.com 10212724Snikos.nikoleris@arm.com/** 10310884Sandreas.hansson@arm.com * Return val with bits first to last set to bit_val 1044626SN/A */ 10510360Sandreas.hansson@arm.comtemplate <class T, class B> 10611484Snikos.nikoleris@arm.cominline 1075034SN/AT 1088883SAli.Saidi@ARM.cominsertBits(T val, int first, int last, B bit_val) 1098833Sdam.sunwoo@arm.com{ 1104458SN/A T t_bit_val = bit_val; 11111377Sandreas.hansson@arm.com T bmask = mask(first - last + 1) << last; 11211377Sandreas.hansson@arm.com return ((t_bit_val << last) & bmask) | (val & ~bmask); 11311377Sandreas.hansson@arm.com} 11411377Sandreas.hansson@arm.com 11511377Sandreas.hansson@arm.com/** 11611377Sandreas.hansson@arm.com * Overloaded for access to only one bit in value 11711331Sandreas.hansson@arm.com */ 11811331Sandreas.hansson@arm.comtemplate <class T, class B> 11912724Snikos.nikoleris@arm.cominline 12012843Srmk35@cl.cam.ac.ukT 12112724Snikos.nikoleris@arm.cominsertBits(T val, int bit, B bit_val) 12213419Sodanrc@yahoo.com.br{ 12312724Snikos.nikoleris@arm.com return insertBits(val, bit, bit, bit_val); 12412724Snikos.nikoleris@arm.com} 12512724Snikos.nikoleris@arm.com 12612724Snikos.nikoleris@arm.com/** 12712724Snikos.nikoleris@arm.com * A convenience function to replace bits first to last of val with bit_val 12812724Snikos.nikoleris@arm.com * in place. 12912724Snikos.nikoleris@arm.com */ 1302810SN/Atemplate <class T, class B> 1312810SN/Ainline 1323013SN/Avoid 1338856Sandreas.hansson@arm.comreplaceBits(T& val, int first, int last, B bit_val) 1342810SN/A{ 1353013SN/A val = insertBits(val, first, last, bit_val); 13610714Sandreas.hansson@arm.com} 1372810SN/A 1389614Srene.dejong@arm.com/** Overloaded function to allow to access only 1 bit*/ 1399614Srene.dejong@arm.comtemplate <class T, class B> 1409614Srene.dejong@arm.cominline 14110345SCurtis.Dunham@arm.comvoid 14210714Sandreas.hansson@arm.comreplaceBits(T& val, int bit, B bit_val) 14310345SCurtis.Dunham@arm.com{ 1449614Srene.dejong@arm.com val = insertBits(val, bit, bit, bit_val); 1452810SN/A} 1462810SN/A/** 1472810SN/A * Returns the bit position of the MSB that is set in the input 1488856Sandreas.hansson@arm.com */ 1492810SN/Ainline 1503013SN/Aint 15110714Sandreas.hansson@arm.comfindMsbSet(uint64_t val) { 1523013SN/A int msb = 0; 1538856Sandreas.hansson@arm.com if (!val) 15410714Sandreas.hansson@arm.com return 0; 1558922Swilliam.wang@arm.com if (bits(val, 63,32)) { msb += 32; val >>= 32; } 1562897SN/A if (bits(val, 31,16)) { msb += 16; val >>= 16; } 1572810SN/A if (bits(val, 15,8)) { msb += 8; val >>= 8; } 1582810SN/A if (bits(val, 7,4)) { msb += 4; val >>= 4; } 15910344Sandreas.hansson@arm.com if (bits(val, 3,2)) { msb += 2; val >>= 2; } 16010344Sandreas.hansson@arm.com if (bits(val, 1,1)) { msb += 1; } 16110344Sandreas.hansson@arm.com return msb; 16210714Sandreas.hansson@arm.com} 16310344Sandreas.hansson@arm.com 16410344Sandreas.hansson@arm.com// The following implements the BitUnion system of defining bitfields 16510344Sandreas.hansson@arm.com//on top of an underlying class. This is done through the pervasive use of 16610713Sandreas.hansson@arm.com//both named and unnamed unions which all contain the same actual storage. 16710344Sandreas.hansson@arm.com//Since they're unioned with each other, all of these storage locations 1682844SN/A//overlap. This allows all of the bitfields to manipulate the same data 16912730Sodanrc@yahoo.com.br//without having to have access to each other. More details are provided with the 17012730Sodanrc@yahoo.com.br//individual components. 17112730Sodanrc@yahoo.com.br 17212730Sodanrc@yahoo.com.br//This namespace is for classes which implement the backend of the BitUnion 17312730Sodanrc@yahoo.com.br//stuff. Don't use any of these directly, except for the Bitfield classes in 17412730Sodanrc@yahoo.com.br//the *BitfieldTypes class(es). 17512730Sodanrc@yahoo.com.brnamespace BitfieldBackend 17612730Sodanrc@yahoo.com.br{ 17712730Sodanrc@yahoo.com.br //A base class for all bitfields. It instantiates the actual storage, 17812730Sodanrc@yahoo.com.br //and provides getBits and setBits functions for manipulating it. The 1792810SN/A //Data template parameter is type of the underlying storage. 1802858SN/A template<class Data> 1812858SN/A class BitfieldBase 18212724Snikos.nikoleris@arm.com { 1838922Swilliam.wang@arm.com protected: 18412724Snikos.nikoleris@arm.com Data __data; 18512724Snikos.nikoleris@arm.com 1862858SN/A //This function returns a range of bits from the underlying storage. 1872858SN/A //It relies on the "bits" function above. It's the user's 1889294Sandreas.hansson@arm.com //responsibility to make sure that there is a properly overloaded 1899294Sandreas.hansson@arm.com //version of this function for whatever type they want to overlay. 1908922Swilliam.wang@arm.com inline uint64_t 1918922Swilliam.wang@arm.com getBits(int first, int last) const 19212724Snikos.nikoleris@arm.com { 1938922Swilliam.wang@arm.com return bits(__data, first, last); 1948922Swilliam.wang@arm.com } 1958922Swilliam.wang@arm.com 1968922Swilliam.wang@arm.com //Similar to the above, but for settings bits with replaceBits. 1978922Swilliam.wang@arm.com inline void 1989294Sandreas.hansson@arm.com setBits(int first, int last, uint64_t val) 1999294Sandreas.hansson@arm.com { 2008922Swilliam.wang@arm.com replaceBits(__data, first, last, val); 2018922Swilliam.wang@arm.com } 20212724Snikos.nikoleris@arm.com }; 2038922Swilliam.wang@arm.com 2048922Swilliam.wang@arm.com //This class contains all the "regular" bitfield classes. It is inherited 2058922Swilliam.wang@arm.com //by all BitUnions which give them access to those types. 2068922Swilliam.wang@arm.com template<class Type> 2074628SN/A class RegularBitfieldTypes 20810821Sandreas.hansson@arm.com { 20910821Sandreas.hansson@arm.com protected: 21010821Sandreas.hansson@arm.com //This class implements ordinary bitfields, that is a span of bits 21110821Sandreas.hansson@arm.com //who's msb is "first", and who's lsb is "last". 21210821Sandreas.hansson@arm.com template<int first, int last=first> 21310821Sandreas.hansson@arm.com class Bitfield : public BitfieldBase<Type> 21410821Sandreas.hansson@arm.com { 21510821Sandreas.hansson@arm.com public: 21610821Sandreas.hansson@arm.com operator uint64_t () const 21710821Sandreas.hansson@arm.com { 21810821Sandreas.hansson@arm.com return this->getBits(first, last); 2192858SN/A } 22012724Snikos.nikoleris@arm.com 22112724Snikos.nikoleris@arm.com uint64_t 22212724Snikos.nikoleris@arm.com operator=(const uint64_t _data) 22312724Snikos.nikoleris@arm.com { 22412724Snikos.nikoleris@arm.com this->setBits(first, last, _data); 22512724Snikos.nikoleris@arm.com return _data; 22612724Snikos.nikoleris@arm.com } 22712724Snikos.nikoleris@arm.com }; 22812724Snikos.nikoleris@arm.com 22912724Snikos.nikoleris@arm.com //A class which specializes the above so that it can only be read 23013418Sodanrc@yahoo.com.br //from. This is accomplished explicitly making sure the assignment 23113418Sodanrc@yahoo.com.br //operator is blocked. The conversion operator is carried through 23213564Snikos.nikoleris@arm.com //inheritance. This will unfortunately need to be copied into each 23312724Snikos.nikoleris@arm.com //bitfield type due to limitations with how templates work 23412724Snikos.nikoleris@arm.com template<int first, int last=first> 23512724Snikos.nikoleris@arm.com class BitfieldRO : public Bitfield<first, last> 23612724Snikos.nikoleris@arm.com { 23712724Snikos.nikoleris@arm.com private: 23812724Snikos.nikoleris@arm.com uint64_t 23912724Snikos.nikoleris@arm.com operator=(const uint64_t _data); 24012724Snikos.nikoleris@arm.com }; 24112724Snikos.nikoleris@arm.com 24212724Snikos.nikoleris@arm.com //Similar to the above, but only allows writing. 24312724Snikos.nikoleris@arm.com template<int first, int last=first> 24412724Snikos.nikoleris@arm.com class BitfieldWO : public Bitfield<first, last> 24512724Snikos.nikoleris@arm.com { 24612724Snikos.nikoleris@arm.com private: 24712724Snikos.nikoleris@arm.com operator uint64_t () const; 24812724Snikos.nikoleris@arm.com 24913352Snikos.nikoleris@arm.com public: 25013352Snikos.nikoleris@arm.com using Bitfield<first, last>::operator=; 25113352Snikos.nikoleris@arm.com }; 25213352Snikos.nikoleris@arm.com }; 25313352Snikos.nikoleris@arm.com 25413352Snikos.nikoleris@arm.com //This class contains all the "regular" bitfield classes. It is inherited 25512724Snikos.nikoleris@arm.com //by all BitUnions which give them access to those types. 25612724Snikos.nikoleris@arm.com template<class Type> 25712724Snikos.nikoleris@arm.com class SignedBitfieldTypes 25812724Snikos.nikoleris@arm.com { 25912724Snikos.nikoleris@arm.com protected: 26012724Snikos.nikoleris@arm.com //This class implements ordinary bitfields, that is a span of bits 26112724Snikos.nikoleris@arm.com //who's msb is "first", and who's lsb is "last". 26212724Snikos.nikoleris@arm.com template<int first, int last=first> 26312724Snikos.nikoleris@arm.com class SignedBitfield : public BitfieldBase<Type> 26412724Snikos.nikoleris@arm.com { 26512724Snikos.nikoleris@arm.com public: 26612724Snikos.nikoleris@arm.com operator int64_t () const 26712724Snikos.nikoleris@arm.com { 26812724Snikos.nikoleris@arm.com return sext<first - last + 1>(this->getBits(first, last)); 26912724Snikos.nikoleris@arm.com } 27012724Snikos.nikoleris@arm.com 27112724Snikos.nikoleris@arm.com int64_t 27212724Snikos.nikoleris@arm.com operator=(const int64_t _data) 27312724Snikos.nikoleris@arm.com { 27412724Snikos.nikoleris@arm.com this->setBits(first, last, _data); 27512724Snikos.nikoleris@arm.com return _data; 27612724Snikos.nikoleris@arm.com } 27712724Snikos.nikoleris@arm.com }; 27812724Snikos.nikoleris@arm.com 27912724Snikos.nikoleris@arm.com //A class which specializes the above so that it can only be read 28012724Snikos.nikoleris@arm.com //from. This is accomplished explicitly making sure the assignment 28112724Snikos.nikoleris@arm.com //operator is blocked. The conversion operator is carried through 28212724Snikos.nikoleris@arm.com //inheritance. This will unfortunately need to be copied into each 28312724Snikos.nikoleris@arm.com //bitfield type due to limitations with how templates work 28412724Snikos.nikoleris@arm.com template<int first, int last=first> 28512724Snikos.nikoleris@arm.com class SignedBitfieldRO : public SignedBitfield<first, last> 28612724Snikos.nikoleris@arm.com { 28712724Snikos.nikoleris@arm.com private: 28812724Snikos.nikoleris@arm.com int64_t 28912724Snikos.nikoleris@arm.com operator=(const int64_t _data); 29012724Snikos.nikoleris@arm.com }; 29112724Snikos.nikoleris@arm.com 29212724Snikos.nikoleris@arm.com //Similar to the above, but only allows writing. 29312724Snikos.nikoleris@arm.com template<int first, int last=first> 29412724Snikos.nikoleris@arm.com class SignedBitfieldWO : public SignedBitfield<first, last> 29512724Snikos.nikoleris@arm.com { 29612724Snikos.nikoleris@arm.com private: 29712724Snikos.nikoleris@arm.com operator int64_t () const; 29812724Snikos.nikoleris@arm.com 29912724Snikos.nikoleris@arm.com public: 30012724Snikos.nikoleris@arm.com int64_t operator=(const int64_t _data) 30112724Snikos.nikoleris@arm.com { 30212724Snikos.nikoleris@arm.com *((SignedBitfield<first, last> *)this) = _data; 30312724Snikos.nikoleris@arm.com return _data; 30412724Snikos.nikoleris@arm.com } 30512724Snikos.nikoleris@arm.com }; 30612724Snikos.nikoleris@arm.com }; 30712724Snikos.nikoleris@arm.com 30812724Snikos.nikoleris@arm.com template<class Type> 30912724Snikos.nikoleris@arm.com class BitfieldTypes : public RegularBitfieldTypes<Type>, 31012724Snikos.nikoleris@arm.com public SignedBitfieldTypes<Type> 31112724Snikos.nikoleris@arm.com {}; 31212724Snikos.nikoleris@arm.com 31312724Snikos.nikoleris@arm.com //When a BitUnion is set up, an underlying class is created which holds 31412724Snikos.nikoleris@arm.com //the actual union. This class then inherits from it, and provids the 31512724Snikos.nikoleris@arm.com //implementations for various operators. Setting things up this way 31612724Snikos.nikoleris@arm.com //prevents having to redefine these functions in every different BitUnion 31712724Snikos.nikoleris@arm.com //type. More operators could be implemented in the future, as the need 31812724Snikos.nikoleris@arm.com //arises. 31912724Snikos.nikoleris@arm.com template <class Type, class Base> 32012724Snikos.nikoleris@arm.com class BitUnionOperators : public Base 32112724Snikos.nikoleris@arm.com { 32212724Snikos.nikoleris@arm.com public: 32312724Snikos.nikoleris@arm.com operator Type () const 32412724Snikos.nikoleris@arm.com { 32512724Snikos.nikoleris@arm.com return Base::__data; 32612724Snikos.nikoleris@arm.com } 32712724Snikos.nikoleris@arm.com 32812724Snikos.nikoleris@arm.com Type 32912724Snikos.nikoleris@arm.com operator=(const Type & _data) 33012724Snikos.nikoleris@arm.com { 33112724Snikos.nikoleris@arm.com Base::__data = _data; 33212724Snikos.nikoleris@arm.com return _data; 33312724Snikos.nikoleris@arm.com } 33412724Snikos.nikoleris@arm.com 33512724Snikos.nikoleris@arm.com bool 33612724Snikos.nikoleris@arm.com operator<(const Base & base) const 33712724Snikos.nikoleris@arm.com { 33812724Snikos.nikoleris@arm.com return Base::__data < base.__data; 33912724Snikos.nikoleris@arm.com } 34012724Snikos.nikoleris@arm.com 34112724Snikos.nikoleris@arm.com bool 34212724Snikos.nikoleris@arm.com operator==(const Base & base) const 34312724Snikos.nikoleris@arm.com { 34412724Snikos.nikoleris@arm.com return Base::__data == base.__data; 34512724Snikos.nikoleris@arm.com } 34612724Snikos.nikoleris@arm.com }; 34713418Sodanrc@yahoo.com.br} 34812724Snikos.nikoleris@arm.com 34912724Snikos.nikoleris@arm.com//This macro is a backend for other macros that specialize it slightly. 35012724Snikos.nikoleris@arm.com//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and 35112724Snikos.nikoleris@arm.com//sticks the class which has the actual union in it, which 35212724Snikos.nikoleris@arm.com//BitfieldOperators above inherits from. Putting these classes in a special 35313418Sodanrc@yahoo.com.br//namespace ensures that there will be no collisions with other names as long 35412724Snikos.nikoleris@arm.com//as the BitUnion names themselves are all distinct and nothing else uses 35512724Snikos.nikoleris@arm.com//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself 35612724Snikos.nikoleris@arm.com//creates a typedef of the "type" parameter called __DataType. This allows 35712820Srmk35@cl.cam.ac.uk//the type to propagate outside of the macro itself in a controlled way. 35812724Snikos.nikoleris@arm.com//Finally, the base storage is defined which BitfieldOperators will refer to 35912724Snikos.nikoleris@arm.com//in the operators it defines. This macro is intended to be followed by 36012724Snikos.nikoleris@arm.com//bitfield definitions which will end up inside it's union. As explained 36112724Snikos.nikoleris@arm.com//above, these is overlayed the __data member in its entirety by each of the 36212724Snikos.nikoleris@arm.com//bitfields which are defined in the union, creating shared storage with no 36313418Sodanrc@yahoo.com.br//overhead. 36412724Snikos.nikoleris@arm.com#define __BitUnion(type, name) \ 36512724Snikos.nikoleris@arm.com namespace BitfieldUnderlyingClasses \ 36612724Snikos.nikoleris@arm.com { \ 36712724Snikos.nikoleris@arm.com class name; \ 36812724Snikos.nikoleris@arm.com } \ 36912724Snikos.nikoleris@arm.com class BitfieldUnderlyingClasses::name : \ 37012724Snikos.nikoleris@arm.com public BitfieldBackend::BitfieldTypes<type> \ 37113416Sjavier.bueno@metempsy.com { \ 37213416Sjavier.bueno@metempsy.com public: \ 37313416Sjavier.bueno@metempsy.com typedef type __DataType; \ 37412724Snikos.nikoleris@arm.com union { \ 37513416Sjavier.bueno@metempsy.com type __data;\ 37613416Sjavier.bueno@metempsy.com 37712724Snikos.nikoleris@arm.com//This closes off the class and union started by the above macro. It is 37812724Snikos.nikoleris@arm.com//followed by a typedef which makes "name" refer to a BitfieldOperator 37912724Snikos.nikoleris@arm.com//class inheriting from the class and union just defined, which completes 38012724Snikos.nikoleris@arm.com//building up the type for the user. 38112724Snikos.nikoleris@arm.com#define EndBitUnion(name) \ 38212724Snikos.nikoleris@arm.com }; \ 38313416Sjavier.bueno@metempsy.com }; \ 38412724Snikos.nikoleris@arm.com typedef BitfieldBackend::BitUnionOperators< \ 38512724Snikos.nikoleris@arm.com BitfieldUnderlyingClasses::name::__DataType, \ 38613416Sjavier.bueno@metempsy.com BitfieldUnderlyingClasses::name> name; 38713416Sjavier.bueno@metempsy.com 38813416Sjavier.bueno@metempsy.com//This sets up a bitfield which has other bitfields nested inside of it. The 38913416Sjavier.bueno@metempsy.com//__data member functions like the "underlying storage" of the top level 39013416Sjavier.bueno@metempsy.com//BitUnion. Like everything else, it overlays with the top level storage, so 39113416Sjavier.bueno@metempsy.com//making it a regular bitfield type makes the entire thing function as a 39212724Snikos.nikoleris@arm.com//regular bitfield when referred to by itself. 39312724Snikos.nikoleris@arm.com#define __SubBitUnion(fieldType, first, last, name) \ 39412724Snikos.nikoleris@arm.com class : public BitfieldBackend::BitfieldTypes<__DataType> \ 39512724Snikos.nikoleris@arm.com { \ 39612724Snikos.nikoleris@arm.com public: \ 39712724Snikos.nikoleris@arm.com union { \ 39812724Snikos.nikoleris@arm.com fieldType<first, last> __data; 39912724Snikos.nikoleris@arm.com 40012724Snikos.nikoleris@arm.com//This closes off the union created above and gives it a name. Unlike the top 40112724Snikos.nikoleris@arm.com//level BitUnion, we're interested in creating an object instead of a type. 40212724Snikos.nikoleris@arm.com//The operators are defined in the macro itself instead of a class for 40312724Snikos.nikoleris@arm.com//technical reasons. If someone determines a way to move them to one, please 40413564Snikos.nikoleris@arm.com//do so. 40512724Snikos.nikoleris@arm.com#define EndSubBitUnion(name) \ 40612724Snikos.nikoleris@arm.com }; \ 40712724Snikos.nikoleris@arm.com inline operator const __DataType () \ 40812724Snikos.nikoleris@arm.com { return __data; } \ 40912724Snikos.nikoleris@arm.com \ 41012724Snikos.nikoleris@arm.com inline const __DataType operator = (const __DataType & _data) \ 41112724Snikos.nikoleris@arm.com { __data = _data; } \ 41212724Snikos.nikoleris@arm.com } name; 41312724Snikos.nikoleris@arm.com 41412724Snikos.nikoleris@arm.com//Regular bitfields 41512724Snikos.nikoleris@arm.com//These define macros for read/write regular bitfield based subbitfields. 41612724Snikos.nikoleris@arm.com#define SubBitUnion(name, first, last) \ 41712724Snikos.nikoleris@arm.com __SubBitUnion(Bitfield, first, last, name) 41812724Snikos.nikoleris@arm.com 41912724Snikos.nikoleris@arm.com//Regular bitfields 42012724Snikos.nikoleris@arm.com//These define macros for read/write regular bitfield based subbitfields. 42112724Snikos.nikoleris@arm.com#define SignedSubBitUnion(name, first, last) \ 42212724Snikos.nikoleris@arm.com __SubBitUnion(SignedBitfield, first, last, name) 42312724Snikos.nikoleris@arm.com 42412724Snikos.nikoleris@arm.com//Use this to define an arbitrary type overlayed with bitfields. 42512724Snikos.nikoleris@arm.com#define BitUnion(type, name) __BitUnion(type, name) 42612724Snikos.nikoleris@arm.com 42712724Snikos.nikoleris@arm.com//Use this to define conveniently sized values overlayed with bitfields. 42812724Snikos.nikoleris@arm.com#define BitUnion64(name) __BitUnion(uint64_t, name) 42912724Snikos.nikoleris@arm.com#define BitUnion32(name) __BitUnion(uint32_t, name) 43012724Snikos.nikoleris@arm.com#define BitUnion16(name) __BitUnion(uint16_t, name) 43112724Snikos.nikoleris@arm.com#define BitUnion8(name) __BitUnion(uint8_t, name) 43212724Snikos.nikoleris@arm.com 43312724Snikos.nikoleris@arm.com#endif // __BASE_BITFIELD_HH__ 43412724Snikos.nikoleris@arm.com