bitfield.hh revision 4661
12SN/A/*
21762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt
292665Ssaidi@eecs.umich.edu *          Nathan Binkert
302SN/A */
312SN/A
321112SN/A#ifndef __BASE_BITFIELD_HH__
331112SN/A#define __BASE_BITFIELD_HH__
342SN/A
353386Sgblack@eecs.umich.edu#include <inttypes.h>
362SN/A
372SN/A/**
382SN/A * Generate a 64-bit mask of 'nbits' 1s, right justified.
392SN/A */
402SN/Ainline uint64_t
412SN/Amask(int nbits)
422SN/A{
432SN/A    return (nbits == 64) ? (uint64_t)-1LL : (1ULL << nbits) - 1;
442SN/A}
452SN/A
462SN/A
474070Ssaidi@eecs.umich.edu
482SN/A/**
492SN/A * Extract the bitfield from position 'first' to 'last' (inclusive)
502SN/A * from 'val' and right justify it.  MSB is numbered 63, LSB is 0.
512SN/A */
522SN/Atemplate <class T>
532SN/Ainline
542SN/AT
552SN/Abits(T val, int first, int last)
562SN/A{
572SN/A    int nbits = first - last + 1;
582SN/A    return (val >> last) & mask(nbits);
592SN/A}
602SN/A
612SN/A/**
624661Sksewell@umich.edu * Extract the bit from this position from 'val' and right justify it.
634661Sksewell@umich.edu */
644661Sksewell@umich.edutemplate <class T>
654661Sksewell@umich.eduinline
664661Sksewell@umich.eduT
674661Sksewell@umich.edubits(T val, int bit)
684661Sksewell@umich.edu{
694661Sksewell@umich.edu    return bits(val, bit, bit);
704661Sksewell@umich.edu}
714661Sksewell@umich.edu
724661Sksewell@umich.edu/**
733814Ssaidi@eecs.umich.edu * Mask off the given bits in place like bits() but without shifting.
743814Ssaidi@eecs.umich.edu * msb = 63, lsb = 0
753814Ssaidi@eecs.umich.edu */
763814Ssaidi@eecs.umich.edutemplate <class T>
773814Ssaidi@eecs.umich.eduinline
783814Ssaidi@eecs.umich.eduT
793814Ssaidi@eecs.umich.edumbits(T val, int first, int last)
803814Ssaidi@eecs.umich.edu{
813814Ssaidi@eecs.umich.edu    return val & (mask(first+1) & ~mask(last));
823814Ssaidi@eecs.umich.edu}
833814Ssaidi@eecs.umich.edu
844070Ssaidi@eecs.umich.eduinline uint64_t
854070Ssaidi@eecs.umich.edumask(int first, int last)
864070Ssaidi@eecs.umich.edu{
874070Ssaidi@eecs.umich.edu    return mbits((uint64_t)-1LL, first, last);
884070Ssaidi@eecs.umich.edu}
894070Ssaidi@eecs.umich.edu
903814Ssaidi@eecs.umich.edu/**
912SN/A * Sign-extend an N-bit value to 64 bits.
922SN/A */
932SN/Atemplate <int N>
942SN/Ainline
952SN/Aint64_t
962SN/Asext(uint64_t val)
972SN/A{
982SN/A    int sign_bit = bits(val, N-1, N-1);
992SN/A    return sign_bit ? (val | ~mask(N)) : val;
1002SN/A}
1012SN/A
1023422Sgblack@eecs.umich.edu/**
1033422Sgblack@eecs.umich.edu * Return val with bits first to last set to bit_val
1043422Sgblack@eecs.umich.edu */
1053422Sgblack@eecs.umich.edutemplate <class T, class B>
1063422Sgblack@eecs.umich.eduinline
1073422Sgblack@eecs.umich.eduT
1083422Sgblack@eecs.umich.eduinsertBits(T val, int first, int last, B bit_val)
1093422Sgblack@eecs.umich.edu{
1104425Ssaidi@eecs.umich.edu    T t_bit_val = bit_val;
1113422Sgblack@eecs.umich.edu    T bmask = mask(first - last + 1) << last;
1124425Ssaidi@eecs.umich.edu    return ((t_bit_val << last) & bmask) | (val & ~bmask);
1133422Sgblack@eecs.umich.edu}
1143422Sgblack@eecs.umich.edu
1153422Sgblack@eecs.umich.edu/**
1164661Sksewell@umich.edu * Overloaded for access to only one bit in value
1174661Sksewell@umich.edu */
1184661Sksewell@umich.edutemplate <class T, class B>
1194661Sksewell@umich.eduinline
1204661Sksewell@umich.eduT
1214661Sksewell@umich.eduinsertBits(T val, int bit, B bit_val)
1224661Sksewell@umich.edu{
1234661Sksewell@umich.edu    return insertBits(val, bit, bit, bit_val);
1244661Sksewell@umich.edu}
1254661Sksewell@umich.edu
1264661Sksewell@umich.edu/**
1273422Sgblack@eecs.umich.edu * A convenience function to replace bits first to last of val with bit_val
1283422Sgblack@eecs.umich.edu * in place.
1293422Sgblack@eecs.umich.edu */
1303422Sgblack@eecs.umich.edutemplate <class T, class B>
1313422Sgblack@eecs.umich.eduinline
1323422Sgblack@eecs.umich.eduvoid
1333422Sgblack@eecs.umich.edureplaceBits(T& val, int first, int last, B bit_val)
1343422Sgblack@eecs.umich.edu{
1353422Sgblack@eecs.umich.edu    val = insertBits(val, first, last, bit_val);
1363422Sgblack@eecs.umich.edu}
1373422Sgblack@eecs.umich.edu
1384661Sksewell@umich.edu/** Overloaded function to allow to access only 1 bit*/
1394661Sksewell@umich.edutemplate <class T, class B>
1404661Sksewell@umich.eduinline
1414661Sksewell@umich.eduvoid
1424661Sksewell@umich.edureplaceBits(T& val, int bit, B bit_val)
1434661Sksewell@umich.edu{
1444661Sksewell@umich.edu    val = insertBits(val, bit, bit, bit_val);
1454661Sksewell@umich.edu}
1464103Ssaidi@eecs.umich.edu/**
1474103Ssaidi@eecs.umich.edu * Returns the bit position of the MSB that is set in the input
1484103Ssaidi@eecs.umich.edu */
1494103Ssaidi@eecs.umich.eduinline
1504103Ssaidi@eecs.umich.eduint
1514103Ssaidi@eecs.umich.edufindMsbSet(uint64_t val) {
1524103Ssaidi@eecs.umich.edu    int msb = 0;
1534103Ssaidi@eecs.umich.edu    if (!val)
1544103Ssaidi@eecs.umich.edu        return 0;
1554244Ssaidi@eecs.umich.edu    if (bits(val, 63,32)) { msb += 32; val >>= 32; }
1564244Ssaidi@eecs.umich.edu    if (bits(val, 31,16)) { msb += 16; val >>= 16; }
1574244Ssaidi@eecs.umich.edu    if (bits(val, 15,8))  { msb += 8;  val >>= 8;  }
1584244Ssaidi@eecs.umich.edu    if (bits(val, 7,4))   { msb += 4;  val >>= 4;  }
1594244Ssaidi@eecs.umich.edu    if (bits(val, 3,2))   { msb += 2;  val >>= 2;  }
1604244Ssaidi@eecs.umich.edu    if (bits(val, 1,1))   { msb += 1; }
1614103Ssaidi@eecs.umich.edu    return msb;
1624103Ssaidi@eecs.umich.edu}
1634103Ssaidi@eecs.umich.edu
1644259Sgblack@eecs.umich.edu//	The following implements the BitUnion system of defining bitfields
1654262Sgblack@eecs.umich.edu//on top of an underlying class. This is done through the pervasive use of
1664259Sgblack@eecs.umich.edu//both named and unnamed unions which all contain the same actual storage.
1674259Sgblack@eecs.umich.edu//Since they're unioned with each other, all of these storage locations
1684259Sgblack@eecs.umich.edu//overlap. This allows all of the bitfields to manipulate the same data
1694262Sgblack@eecs.umich.edu//without having to have access to each other. More details are provided with the
1704259Sgblack@eecs.umich.edu//individual components.
1714259Sgblack@eecs.umich.edu
1724259Sgblack@eecs.umich.edu//This namespace is for classes which implement the backend of the BitUnion
1734262Sgblack@eecs.umich.edu//stuff. Don't use any of these directly, except for the Bitfield classes in
1744262Sgblack@eecs.umich.edu//the *BitfieldTypes class(es).
1754258Sgblack@eecs.umich.edunamespace BitfieldBackend
1764257Sgblack@eecs.umich.edu{
1774259Sgblack@eecs.umich.edu    //A base class for all bitfields. It instantiates the actual storage,
1784259Sgblack@eecs.umich.edu    //and provides getBits and setBits functions for manipulating it. The
1794259Sgblack@eecs.umich.edu    //Data template parameter is type of the underlying storage.
1804258Sgblack@eecs.umich.edu    template<class Data>
1814258Sgblack@eecs.umich.edu    class BitfieldBase
1824258Sgblack@eecs.umich.edu    {
1834258Sgblack@eecs.umich.edu      protected:
1844258Sgblack@eecs.umich.edu        Data __data;
1854103Ssaidi@eecs.umich.edu
1864259Sgblack@eecs.umich.edu        //This function returns a range of bits from the underlying storage.
1874259Sgblack@eecs.umich.edu        //It relies on the "bits" function above. It's the user's
1884259Sgblack@eecs.umich.edu        //responsibility to make sure that there is a properly overloaded
1894259Sgblack@eecs.umich.edu        //version of this function for whatever type they want to overlay.
1904258Sgblack@eecs.umich.edu        inline uint64_t
1914275Sgblack@eecs.umich.edu        getBits(int first, int last) const
1924258Sgblack@eecs.umich.edu        {
1934258Sgblack@eecs.umich.edu            return bits(__data, first, last);
1944258Sgblack@eecs.umich.edu        }
1954258Sgblack@eecs.umich.edu
1964259Sgblack@eecs.umich.edu        //Similar to the above, but for settings bits with replaceBits.
1974258Sgblack@eecs.umich.edu        inline void
1984258Sgblack@eecs.umich.edu        setBits(int first, int last, uint64_t val)
1994258Sgblack@eecs.umich.edu        {
2004258Sgblack@eecs.umich.edu            replaceBits(__data, first, last, val);
2014258Sgblack@eecs.umich.edu        }
2024258Sgblack@eecs.umich.edu    };
2034258Sgblack@eecs.umich.edu
2044262Sgblack@eecs.umich.edu    //This class contains all the "regular" bitfield classes. It is inherited
2054262Sgblack@eecs.umich.edu    //by all BitUnions which give them access to those types.
2064262Sgblack@eecs.umich.edu    template<class Type>
2074262Sgblack@eecs.umich.edu    class RegularBitfieldTypes
2084257Sgblack@eecs.umich.edu    {
2094262Sgblack@eecs.umich.edu      protected:
2104262Sgblack@eecs.umich.edu        //This class implements ordinary bitfields, that is a span of bits
2114262Sgblack@eecs.umich.edu        //who's msb is "first", and who's lsb is "last".
2124262Sgblack@eecs.umich.edu        template<int first, int last=first>
2134262Sgblack@eecs.umich.edu        class Bitfield : public BitfieldBase<Type>
2144262Sgblack@eecs.umich.edu        {
2154262Sgblack@eecs.umich.edu          public:
2164274Sgblack@eecs.umich.edu            operator uint64_t () const
2174262Sgblack@eecs.umich.edu            {
2184262Sgblack@eecs.umich.edu                return this->getBits(first, last);
2194262Sgblack@eecs.umich.edu            }
2204261Sgblack@eecs.umich.edu
2214274Sgblack@eecs.umich.edu            uint64_t
2224274Sgblack@eecs.umich.edu            operator=(const uint64_t _data)
2234262Sgblack@eecs.umich.edu            {
2244262Sgblack@eecs.umich.edu                this->setBits(first, last, _data);
2254262Sgblack@eecs.umich.edu                return _data;
2264262Sgblack@eecs.umich.edu            }
2274262Sgblack@eecs.umich.edu        };
2284262Sgblack@eecs.umich.edu
2294262Sgblack@eecs.umich.edu        //A class which specializes the above so that it can only be read
2304262Sgblack@eecs.umich.edu        //from. This is accomplished explicitly making sure the assignment
2314262Sgblack@eecs.umich.edu        //operator is blocked. The conversion operator is carried through
2324262Sgblack@eecs.umich.edu        //inheritance. This will unfortunately need to be copied into each
2334262Sgblack@eecs.umich.edu        //bitfield type due to limitations with how templates work
2344262Sgblack@eecs.umich.edu        template<int first, int last=first>
2354262Sgblack@eecs.umich.edu        class BitfieldRO : public Bitfield<first, last>
2364258Sgblack@eecs.umich.edu        {
2374262Sgblack@eecs.umich.edu          private:
2384274Sgblack@eecs.umich.edu            uint64_t
2394274Sgblack@eecs.umich.edu            operator=(const uint64_t _data);
2404262Sgblack@eecs.umich.edu        };
2414262Sgblack@eecs.umich.edu
2424262Sgblack@eecs.umich.edu        //Similar to the above, but only allows writing.
2434262Sgblack@eecs.umich.edu        template<int first, int last=first>
2444262Sgblack@eecs.umich.edu        class BitfieldWO : public Bitfield<first, last>
2454262Sgblack@eecs.umich.edu        {
2464262Sgblack@eecs.umich.edu          private:
2474274Sgblack@eecs.umich.edu            operator uint64_t () const;
2484262Sgblack@eecs.umich.edu
2494262Sgblack@eecs.umich.edu          public:
2504274Sgblack@eecs.umich.edu            using Bitfield<first, last>::operator=;
2514274Sgblack@eecs.umich.edu        };
2524274Sgblack@eecs.umich.edu    };
2534274Sgblack@eecs.umich.edu
2544274Sgblack@eecs.umich.edu    //This class contains all the "regular" bitfield classes. It is inherited
2554274Sgblack@eecs.umich.edu    //by all BitUnions which give them access to those types.
2564274Sgblack@eecs.umich.edu    template<class Type>
2574274Sgblack@eecs.umich.edu    class SignedBitfieldTypes
2584274Sgblack@eecs.umich.edu    {
2594274Sgblack@eecs.umich.edu      protected:
2604274Sgblack@eecs.umich.edu        //This class implements ordinary bitfields, that is a span of bits
2614274Sgblack@eecs.umich.edu        //who's msb is "first", and who's lsb is "last".
2624274Sgblack@eecs.umich.edu        template<int first, int last=first>
2634274Sgblack@eecs.umich.edu        class SignedBitfield : public BitfieldBase<Type>
2644274Sgblack@eecs.umich.edu        {
2654274Sgblack@eecs.umich.edu          public:
2664274Sgblack@eecs.umich.edu            operator int64_t () const
2674262Sgblack@eecs.umich.edu            {
2684274Sgblack@eecs.umich.edu                return sext<first - last + 1>(this->getBits(first, last));
2694274Sgblack@eecs.umich.edu            }
2704274Sgblack@eecs.umich.edu
2714274Sgblack@eecs.umich.edu            int64_t
2724274Sgblack@eecs.umich.edu            operator=(const int64_t _data)
2734274Sgblack@eecs.umich.edu            {
2744274Sgblack@eecs.umich.edu                this->setBits(first, last, _data);
2754274Sgblack@eecs.umich.edu                return _data;
2764274Sgblack@eecs.umich.edu            }
2774274Sgblack@eecs.umich.edu        };
2784274Sgblack@eecs.umich.edu
2794274Sgblack@eecs.umich.edu        //A class which specializes the above so that it can only be read
2804274Sgblack@eecs.umich.edu        //from. This is accomplished explicitly making sure the assignment
2814274Sgblack@eecs.umich.edu        //operator is blocked. The conversion operator is carried through
2824274Sgblack@eecs.umich.edu        //inheritance. This will unfortunately need to be copied into each
2834274Sgblack@eecs.umich.edu        //bitfield type due to limitations with how templates work
2844274Sgblack@eecs.umich.edu        template<int first, int last=first>
2854274Sgblack@eecs.umich.edu        class SignedBitfieldRO : public SignedBitfield<first, last>
2864274Sgblack@eecs.umich.edu        {
2874274Sgblack@eecs.umich.edu          private:
2884274Sgblack@eecs.umich.edu            int64_t
2894274Sgblack@eecs.umich.edu            operator=(const int64_t _data);
2904274Sgblack@eecs.umich.edu        };
2914274Sgblack@eecs.umich.edu
2924274Sgblack@eecs.umich.edu        //Similar to the above, but only allows writing.
2934274Sgblack@eecs.umich.edu        template<int first, int last=first>
2944274Sgblack@eecs.umich.edu        class SignedBitfieldWO : public SignedBitfield<first, last>
2954274Sgblack@eecs.umich.edu        {
2964274Sgblack@eecs.umich.edu          private:
2974274Sgblack@eecs.umich.edu            operator int64_t () const;
2984274Sgblack@eecs.umich.edu
2994274Sgblack@eecs.umich.edu          public:
3004274Sgblack@eecs.umich.edu            int64_t operator=(const int64_t _data)
3014274Sgblack@eecs.umich.edu            {
3024274Sgblack@eecs.umich.edu                *((SignedBitfield<first, last> *)this) = _data;
3034262Sgblack@eecs.umich.edu                return _data;
3044262Sgblack@eecs.umich.edu            }
3054262Sgblack@eecs.umich.edu        };
3064258Sgblack@eecs.umich.edu    };
3074257Sgblack@eecs.umich.edu
3084262Sgblack@eecs.umich.edu    template<class Type>
3094274Sgblack@eecs.umich.edu    class BitfieldTypes : public RegularBitfieldTypes<Type>,
3104274Sgblack@eecs.umich.edu                          public SignedBitfieldTypes<Type>
3114262Sgblack@eecs.umich.edu    {};
3124258Sgblack@eecs.umich.edu
3134259Sgblack@eecs.umich.edu    //When a BitUnion is set up, an underlying class is created which holds
3144259Sgblack@eecs.umich.edu    //the actual union. This class then inherits from it, and provids the
3154259Sgblack@eecs.umich.edu    //implementations for various operators. Setting things up this way
3164259Sgblack@eecs.umich.edu    //prevents having to redefine these functions in every different BitUnion
3174259Sgblack@eecs.umich.edu    //type. More operators could be implemented in the future, as the need
3184259Sgblack@eecs.umich.edu    //arises.
3194258Sgblack@eecs.umich.edu    template <class Type, class Base>
3204258Sgblack@eecs.umich.edu    class BitUnionOperators : public Base
3214257Sgblack@eecs.umich.edu    {
3224258Sgblack@eecs.umich.edu      public:
3234274Sgblack@eecs.umich.edu        operator Type () const
3244258Sgblack@eecs.umich.edu        {
3254258Sgblack@eecs.umich.edu            return Base::__data;
3264258Sgblack@eecs.umich.edu        }
3274257Sgblack@eecs.umich.edu
3284274Sgblack@eecs.umich.edu        Type
3294260Sgblack@eecs.umich.edu        operator=(const Type & _data)
3304258Sgblack@eecs.umich.edu        {
3314258Sgblack@eecs.umich.edu            Base::__data = _data;
3324274Sgblack@eecs.umich.edu            return _data;
3334258Sgblack@eecs.umich.edu        }
3344257Sgblack@eecs.umich.edu
3354258Sgblack@eecs.umich.edu        bool
3364274Sgblack@eecs.umich.edu        operator<(const Base & base) const
3374258Sgblack@eecs.umich.edu        {
3384258Sgblack@eecs.umich.edu            return Base::__data < base.__data;
3394258Sgblack@eecs.umich.edu        }
3404257Sgblack@eecs.umich.edu
3414258Sgblack@eecs.umich.edu        bool
3424274Sgblack@eecs.umich.edu        operator==(const Base & base) const
3434258Sgblack@eecs.umich.edu        {
3444258Sgblack@eecs.umich.edu            return Base::__data == base.__data;
3454258Sgblack@eecs.umich.edu        }
3464258Sgblack@eecs.umich.edu    };
3474258Sgblack@eecs.umich.edu}
3484257Sgblack@eecs.umich.edu
3494259Sgblack@eecs.umich.edu//This macro is a backend for other macros that specialize it slightly.
3504259Sgblack@eecs.umich.edu//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
3514259Sgblack@eecs.umich.edu//sticks the class which has the actual union in it, which
3524259Sgblack@eecs.umich.edu//BitfieldOperators above inherits from. Putting these classes in a special
3534259Sgblack@eecs.umich.edu//namespace ensures that there will be no collisions with other names as long
3544259Sgblack@eecs.umich.edu//as the BitUnion names themselves are all distinct and nothing else uses
3554259Sgblack@eecs.umich.edu//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
3564259Sgblack@eecs.umich.edu//creates a typedef of the "type" parameter called __DataType. This allows
3574259Sgblack@eecs.umich.edu//the type to propagate outside of the macro itself in a controlled way.
3584259Sgblack@eecs.umich.edu//Finally, the base storage is defined which BitfieldOperators will refer to
3594259Sgblack@eecs.umich.edu//in the operators it defines. This macro is intended to be followed by
3604259Sgblack@eecs.umich.edu//bitfield definitions which will end up inside it's union. As explained
3614259Sgblack@eecs.umich.edu//above, these is overlayed the __data member in its entirety by each of the
3624259Sgblack@eecs.umich.edu//bitfields which are defined in the union, creating shared storage with no
3634259Sgblack@eecs.umich.edu//overhead.
3644257Sgblack@eecs.umich.edu#define __BitUnion(type, name) \
3654258Sgblack@eecs.umich.edu    namespace BitfieldUnderlyingClasses \
3664258Sgblack@eecs.umich.edu    { \
3674258Sgblack@eecs.umich.edu        class name; \
3684258Sgblack@eecs.umich.edu    } \
3694262Sgblack@eecs.umich.edu    class BitfieldUnderlyingClasses::name : \
3704262Sgblack@eecs.umich.edu        public BitfieldBackend::BitfieldTypes<type> \
3714262Sgblack@eecs.umich.edu    { \
3724257Sgblack@eecs.umich.edu      public: \
3734257Sgblack@eecs.umich.edu        typedef type __DataType; \
3744257Sgblack@eecs.umich.edu        union { \
3754257Sgblack@eecs.umich.edu            type __data;\
3764257Sgblack@eecs.umich.edu
3774259Sgblack@eecs.umich.edu//This closes off the class and union started by the above macro. It is
3784259Sgblack@eecs.umich.edu//followed by a typedef which makes "name" refer to a BitfieldOperator
3794259Sgblack@eecs.umich.edu//class inheriting from the class and union just defined, which completes
3804259Sgblack@eecs.umich.edu//building up the type for the user.
3814257Sgblack@eecs.umich.edu#define EndBitUnion(name) \
3824257Sgblack@eecs.umich.edu        }; \
3834257Sgblack@eecs.umich.edu    }; \
3844258Sgblack@eecs.umich.edu    typedef BitfieldBackend::BitUnionOperators< \
3854258Sgblack@eecs.umich.edu        BitfieldUnderlyingClasses::name::__DataType, \
3864258Sgblack@eecs.umich.edu        BitfieldUnderlyingClasses::name> name;
3874257Sgblack@eecs.umich.edu
3884259Sgblack@eecs.umich.edu//This sets up a bitfield which has other bitfields nested inside of it. The
3894259Sgblack@eecs.umich.edu//__data member functions like the "underlying storage" of the top level
3904259Sgblack@eecs.umich.edu//BitUnion. Like everything else, it overlays with the top level storage, so
3914259Sgblack@eecs.umich.edu//making it a regular bitfield type makes the entire thing function as a
3924262Sgblack@eecs.umich.edu//regular bitfield when referred to by itself.
3934262Sgblack@eecs.umich.edu#define __SubBitUnion(fieldType, first, last, name) \
3944262Sgblack@eecs.umich.edu    class : public BitfieldBackend::BitfieldTypes<__DataType> \
3954262Sgblack@eecs.umich.edu    { \
3964262Sgblack@eecs.umich.edu      public: \
3974257Sgblack@eecs.umich.edu        union { \
3984262Sgblack@eecs.umich.edu            fieldType<first, last> __data;
3994257Sgblack@eecs.umich.edu
4004259Sgblack@eecs.umich.edu//This closes off the union created above and gives it a name. Unlike the top
4014259Sgblack@eecs.umich.edu//level BitUnion, we're interested in creating an object instead of a type.
4024262Sgblack@eecs.umich.edu//The operators are defined in the macro itself instead of a class for
4034262Sgblack@eecs.umich.edu//technical reasons. If someone determines a way to move them to one, please
4044262Sgblack@eecs.umich.edu//do so.
4054262Sgblack@eecs.umich.edu#define EndSubBitUnion(name) \
4064262Sgblack@eecs.umich.edu        }; \
4074262Sgblack@eecs.umich.edu        inline operator const __DataType () \
4084262Sgblack@eecs.umich.edu        { return __data; } \
4094262Sgblack@eecs.umich.edu        \
4104262Sgblack@eecs.umich.edu        inline const __DataType operator = (const __DataType & _data) \
4114262Sgblack@eecs.umich.edu        { __data = _data; } \
4124262Sgblack@eecs.umich.edu    } name;
4134258Sgblack@eecs.umich.edu
4144258Sgblack@eecs.umich.edu//Regular bitfields
4154262Sgblack@eecs.umich.edu//These define macros for read/write regular bitfield based subbitfields.
4164258Sgblack@eecs.umich.edu#define SubBitUnion(name, first, last) \
4174262Sgblack@eecs.umich.edu    __SubBitUnion(Bitfield, first, last, name)
4184257Sgblack@eecs.umich.edu
4194274Sgblack@eecs.umich.edu//Regular bitfields
4204274Sgblack@eecs.umich.edu//These define macros for read/write regular bitfield based subbitfields.
4214274Sgblack@eecs.umich.edu#define SignedSubBitUnion(name, first, last) \
4224274Sgblack@eecs.umich.edu    __SubBitUnion(SignedBitfield, first, last, name)
4234274Sgblack@eecs.umich.edu
4244259Sgblack@eecs.umich.edu//Use this to define an arbitrary type overlayed with bitfields.
4254257Sgblack@eecs.umich.edu#define BitUnion(type, name) __BitUnion(type, name)
4264257Sgblack@eecs.umich.edu
4274259Sgblack@eecs.umich.edu//Use this to define conveniently sized values overlayed with bitfields.
4284257Sgblack@eecs.umich.edu#define BitUnion64(name) __BitUnion(uint64_t, name)
4294257Sgblack@eecs.umich.edu#define BitUnion32(name) __BitUnion(uint32_t, name)
4304257Sgblack@eecs.umich.edu#define BitUnion16(name) __BitUnion(uint16_t, name)
4314257Sgblack@eecs.umich.edu#define BitUnion8(name) __BitUnion(uint8_t, name)
4324103Ssaidi@eecs.umich.edu
4331112SN/A#endif // __BASE_BITFIELD_HH__
434