bitfield.hh revision 4274
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/**
623814Ssaidi@eecs.umich.edu * Mask off the given bits in place like bits() but without shifting.
633814Ssaidi@eecs.umich.edu * msb = 63, lsb = 0
643814Ssaidi@eecs.umich.edu */
653814Ssaidi@eecs.umich.edutemplate <class T>
663814Ssaidi@eecs.umich.eduinline
673814Ssaidi@eecs.umich.eduT
683814Ssaidi@eecs.umich.edumbits(T val, int first, int last)
693814Ssaidi@eecs.umich.edu{
703814Ssaidi@eecs.umich.edu    return val & (mask(first+1) & ~mask(last));
713814Ssaidi@eecs.umich.edu}
723814Ssaidi@eecs.umich.edu
734070Ssaidi@eecs.umich.eduinline uint64_t
744070Ssaidi@eecs.umich.edumask(int first, int last)
754070Ssaidi@eecs.umich.edu{
764070Ssaidi@eecs.umich.edu    return mbits((uint64_t)-1LL, first, last);
774070Ssaidi@eecs.umich.edu}
784070Ssaidi@eecs.umich.edu
793814Ssaidi@eecs.umich.edu/**
802SN/A * Sign-extend an N-bit value to 64 bits.
812SN/A */
822SN/Atemplate <int N>
832SN/Ainline
842SN/Aint64_t
852SN/Asext(uint64_t val)
862SN/A{
872SN/A    int sign_bit = bits(val, N-1, N-1);
882SN/A    return sign_bit ? (val | ~mask(N)) : val;
892SN/A}
902SN/A
913422Sgblack@eecs.umich.edu/**
923422Sgblack@eecs.umich.edu * Return val with bits first to last set to bit_val
933422Sgblack@eecs.umich.edu */
943422Sgblack@eecs.umich.edutemplate <class T, class B>
953422Sgblack@eecs.umich.eduinline
963422Sgblack@eecs.umich.eduT
973422Sgblack@eecs.umich.eduinsertBits(T val, int first, int last, B bit_val)
983422Sgblack@eecs.umich.edu{
993422Sgblack@eecs.umich.edu    T bmask = mask(first - last + 1) << last;
1003422Sgblack@eecs.umich.edu    return ((bit_val << last) & bmask) | (val & ~bmask);
1013422Sgblack@eecs.umich.edu}
1023422Sgblack@eecs.umich.edu
1033422Sgblack@eecs.umich.edu/**
1043422Sgblack@eecs.umich.edu * A convenience function to replace bits first to last of val with bit_val
1053422Sgblack@eecs.umich.edu * in place.
1063422Sgblack@eecs.umich.edu */
1073422Sgblack@eecs.umich.edutemplate <class T, class B>
1083422Sgblack@eecs.umich.eduinline
1093422Sgblack@eecs.umich.eduvoid
1103422Sgblack@eecs.umich.edureplaceBits(T& val, int first, int last, B bit_val)
1113422Sgblack@eecs.umich.edu{
1123422Sgblack@eecs.umich.edu    val = insertBits(val, first, last, bit_val);
1133422Sgblack@eecs.umich.edu}
1143422Sgblack@eecs.umich.edu
1154103Ssaidi@eecs.umich.edu/**
1164103Ssaidi@eecs.umich.edu * Returns the bit position of the MSB that is set in the input
1174103Ssaidi@eecs.umich.edu */
1184103Ssaidi@eecs.umich.eduinline
1194103Ssaidi@eecs.umich.eduint
1204103Ssaidi@eecs.umich.edufindMsbSet(uint64_t val) {
1214103Ssaidi@eecs.umich.edu    int msb = 0;
1224103Ssaidi@eecs.umich.edu    if (!val)
1234103Ssaidi@eecs.umich.edu        return 0;
1244244Ssaidi@eecs.umich.edu    if (bits(val, 63,32)) { msb += 32; val >>= 32; }
1254244Ssaidi@eecs.umich.edu    if (bits(val, 31,16)) { msb += 16; val >>= 16; }
1264244Ssaidi@eecs.umich.edu    if (bits(val, 15,8))  { msb += 8;  val >>= 8;  }
1274244Ssaidi@eecs.umich.edu    if (bits(val, 7,4))   { msb += 4;  val >>= 4;  }
1284244Ssaidi@eecs.umich.edu    if (bits(val, 3,2))   { msb += 2;  val >>= 2;  }
1294244Ssaidi@eecs.umich.edu    if (bits(val, 1,1))   { msb += 1; }
1304103Ssaidi@eecs.umich.edu    return msb;
1314103Ssaidi@eecs.umich.edu}
1324103Ssaidi@eecs.umich.edu
1334259Sgblack@eecs.umich.edu//	The following implements the BitUnion system of defining bitfields
1344262Sgblack@eecs.umich.edu//on top of an underlying class. This is done through the pervasive use of
1354259Sgblack@eecs.umich.edu//both named and unnamed unions which all contain the same actual storage.
1364259Sgblack@eecs.umich.edu//Since they're unioned with each other, all of these storage locations
1374259Sgblack@eecs.umich.edu//overlap. This allows all of the bitfields to manipulate the same data
1384262Sgblack@eecs.umich.edu//without having to have access to each other. More details are provided with the
1394259Sgblack@eecs.umich.edu//individual components.
1404259Sgblack@eecs.umich.edu
1414259Sgblack@eecs.umich.edu//This namespace is for classes which implement the backend of the BitUnion
1424262Sgblack@eecs.umich.edu//stuff. Don't use any of these directly, except for the Bitfield classes in
1434262Sgblack@eecs.umich.edu//the *BitfieldTypes class(es).
1444258Sgblack@eecs.umich.edunamespace BitfieldBackend
1454257Sgblack@eecs.umich.edu{
1464259Sgblack@eecs.umich.edu    //A base class for all bitfields. It instantiates the actual storage,
1474259Sgblack@eecs.umich.edu    //and provides getBits and setBits functions for manipulating it. The
1484259Sgblack@eecs.umich.edu    //Data template parameter is type of the underlying storage.
1494258Sgblack@eecs.umich.edu    template<class Data>
1504258Sgblack@eecs.umich.edu    class BitfieldBase
1514258Sgblack@eecs.umich.edu    {
1524258Sgblack@eecs.umich.edu      protected:
1534258Sgblack@eecs.umich.edu        Data __data;
1544103Ssaidi@eecs.umich.edu
1554259Sgblack@eecs.umich.edu        //This function returns a range of bits from the underlying storage.
1564259Sgblack@eecs.umich.edu        //It relies on the "bits" function above. It's the user's
1574259Sgblack@eecs.umich.edu        //responsibility to make sure that there is a properly overloaded
1584259Sgblack@eecs.umich.edu        //version of this function for whatever type they want to overlay.
1594258Sgblack@eecs.umich.edu        inline uint64_t
1604258Sgblack@eecs.umich.edu        getBits(int first, int last)
1614258Sgblack@eecs.umich.edu        {
1624258Sgblack@eecs.umich.edu            return bits(__data, first, last);
1634258Sgblack@eecs.umich.edu        }
1644258Sgblack@eecs.umich.edu
1654259Sgblack@eecs.umich.edu        //Similar to the above, but for settings bits with replaceBits.
1664258Sgblack@eecs.umich.edu        inline void
1674258Sgblack@eecs.umich.edu        setBits(int first, int last, uint64_t val)
1684258Sgblack@eecs.umich.edu        {
1694258Sgblack@eecs.umich.edu            replaceBits(__data, first, last, val);
1704258Sgblack@eecs.umich.edu        }
1714258Sgblack@eecs.umich.edu    };
1724258Sgblack@eecs.umich.edu
1734262Sgblack@eecs.umich.edu    //This class contains all the "regular" bitfield classes. It is inherited
1744262Sgblack@eecs.umich.edu    //by all BitUnions which give them access to those types.
1754262Sgblack@eecs.umich.edu    template<class Type>
1764262Sgblack@eecs.umich.edu    class RegularBitfieldTypes
1774257Sgblack@eecs.umich.edu    {
1784262Sgblack@eecs.umich.edu      protected:
1794262Sgblack@eecs.umich.edu        //This class implements ordinary bitfields, that is a span of bits
1804262Sgblack@eecs.umich.edu        //who's msb is "first", and who's lsb is "last".
1814262Sgblack@eecs.umich.edu        template<int first, int last=first>
1824262Sgblack@eecs.umich.edu        class Bitfield : public BitfieldBase<Type>
1834262Sgblack@eecs.umich.edu        {
1844262Sgblack@eecs.umich.edu          public:
1854274Sgblack@eecs.umich.edu            operator uint64_t () const
1864262Sgblack@eecs.umich.edu            {
1874262Sgblack@eecs.umich.edu                return this->getBits(first, last);
1884262Sgblack@eecs.umich.edu            }
1894261Sgblack@eecs.umich.edu
1904274Sgblack@eecs.umich.edu            uint64_t
1914274Sgblack@eecs.umich.edu            operator=(const uint64_t _data)
1924262Sgblack@eecs.umich.edu            {
1934262Sgblack@eecs.umich.edu                this->setBits(first, last, _data);
1944262Sgblack@eecs.umich.edu                return _data;
1954262Sgblack@eecs.umich.edu            }
1964262Sgblack@eecs.umich.edu        };
1974262Sgblack@eecs.umich.edu
1984262Sgblack@eecs.umich.edu        //A class which specializes the above so that it can only be read
1994262Sgblack@eecs.umich.edu        //from. This is accomplished explicitly making sure the assignment
2004262Sgblack@eecs.umich.edu        //operator is blocked. The conversion operator is carried through
2014262Sgblack@eecs.umich.edu        //inheritance. This will unfortunately need to be copied into each
2024262Sgblack@eecs.umich.edu        //bitfield type due to limitations with how templates work
2034262Sgblack@eecs.umich.edu        template<int first, int last=first>
2044262Sgblack@eecs.umich.edu        class BitfieldRO : public Bitfield<first, last>
2054258Sgblack@eecs.umich.edu        {
2064262Sgblack@eecs.umich.edu          private:
2074274Sgblack@eecs.umich.edu            uint64_t
2084274Sgblack@eecs.umich.edu            operator=(const uint64_t _data);
2094262Sgblack@eecs.umich.edu        };
2104262Sgblack@eecs.umich.edu
2114262Sgblack@eecs.umich.edu        //Similar to the above, but only allows writing.
2124262Sgblack@eecs.umich.edu        template<int first, int last=first>
2134262Sgblack@eecs.umich.edu        class BitfieldWO : public Bitfield<first, last>
2144262Sgblack@eecs.umich.edu        {
2154262Sgblack@eecs.umich.edu          private:
2164274Sgblack@eecs.umich.edu            operator uint64_t () const;
2174262Sgblack@eecs.umich.edu
2184262Sgblack@eecs.umich.edu          public:
2194274Sgblack@eecs.umich.edu            using Bitfield<first, last>::operator=;
2204274Sgblack@eecs.umich.edu        };
2214274Sgblack@eecs.umich.edu    };
2224274Sgblack@eecs.umich.edu
2234274Sgblack@eecs.umich.edu    //This class contains all the "regular" bitfield classes. It is inherited
2244274Sgblack@eecs.umich.edu    //by all BitUnions which give them access to those types.
2254274Sgblack@eecs.umich.edu    template<class Type>
2264274Sgblack@eecs.umich.edu    class SignedBitfieldTypes
2274274Sgblack@eecs.umich.edu    {
2284274Sgblack@eecs.umich.edu      protected:
2294274Sgblack@eecs.umich.edu        //This class implements ordinary bitfields, that is a span of bits
2304274Sgblack@eecs.umich.edu        //who's msb is "first", and who's lsb is "last".
2314274Sgblack@eecs.umich.edu        template<int first, int last=first>
2324274Sgblack@eecs.umich.edu        class SignedBitfield : public BitfieldBase<Type>
2334274Sgblack@eecs.umich.edu        {
2344274Sgblack@eecs.umich.edu          public:
2354274Sgblack@eecs.umich.edu            operator int64_t () const
2364262Sgblack@eecs.umich.edu            {
2374274Sgblack@eecs.umich.edu                return sext<first - last + 1>(this->getBits(first, last));
2384274Sgblack@eecs.umich.edu            }
2394274Sgblack@eecs.umich.edu
2404274Sgblack@eecs.umich.edu            int64_t
2414274Sgblack@eecs.umich.edu            operator=(const int64_t _data)
2424274Sgblack@eecs.umich.edu            {
2434274Sgblack@eecs.umich.edu                this->setBits(first, last, _data);
2444274Sgblack@eecs.umich.edu                return _data;
2454274Sgblack@eecs.umich.edu            }
2464274Sgblack@eecs.umich.edu        };
2474274Sgblack@eecs.umich.edu
2484274Sgblack@eecs.umich.edu        //A class which specializes the above so that it can only be read
2494274Sgblack@eecs.umich.edu        //from. This is accomplished explicitly making sure the assignment
2504274Sgblack@eecs.umich.edu        //operator is blocked. The conversion operator is carried through
2514274Sgblack@eecs.umich.edu        //inheritance. This will unfortunately need to be copied into each
2524274Sgblack@eecs.umich.edu        //bitfield type due to limitations with how templates work
2534274Sgblack@eecs.umich.edu        template<int first, int last=first>
2544274Sgblack@eecs.umich.edu        class SignedBitfieldRO : public SignedBitfield<first, last>
2554274Sgblack@eecs.umich.edu        {
2564274Sgblack@eecs.umich.edu          private:
2574274Sgblack@eecs.umich.edu            int64_t
2584274Sgblack@eecs.umich.edu            operator=(const int64_t _data);
2594274Sgblack@eecs.umich.edu        };
2604274Sgblack@eecs.umich.edu
2614274Sgblack@eecs.umich.edu        //Similar to the above, but only allows writing.
2624274Sgblack@eecs.umich.edu        template<int first, int last=first>
2634274Sgblack@eecs.umich.edu        class SignedBitfieldWO : public SignedBitfield<first, last>
2644274Sgblack@eecs.umich.edu        {
2654274Sgblack@eecs.umich.edu          private:
2664274Sgblack@eecs.umich.edu            operator int64_t () const;
2674274Sgblack@eecs.umich.edu
2684274Sgblack@eecs.umich.edu          public:
2694274Sgblack@eecs.umich.edu            int64_t operator=(const int64_t _data)
2704274Sgblack@eecs.umich.edu            {
2714274Sgblack@eecs.umich.edu                *((SignedBitfield<first, last> *)this) = _data;
2724262Sgblack@eecs.umich.edu                return _data;
2734262Sgblack@eecs.umich.edu            }
2744262Sgblack@eecs.umich.edu        };
2754258Sgblack@eecs.umich.edu    };
2764257Sgblack@eecs.umich.edu
2774262Sgblack@eecs.umich.edu    template<class Type>
2784274Sgblack@eecs.umich.edu    class BitfieldTypes : public RegularBitfieldTypes<Type>,
2794274Sgblack@eecs.umich.edu                          public SignedBitfieldTypes<Type>
2804262Sgblack@eecs.umich.edu    {};
2814258Sgblack@eecs.umich.edu
2824259Sgblack@eecs.umich.edu    //When a BitUnion is set up, an underlying class is created which holds
2834259Sgblack@eecs.umich.edu    //the actual union. This class then inherits from it, and provids the
2844259Sgblack@eecs.umich.edu    //implementations for various operators. Setting things up this way
2854259Sgblack@eecs.umich.edu    //prevents having to redefine these functions in every different BitUnion
2864259Sgblack@eecs.umich.edu    //type. More operators could be implemented in the future, as the need
2874259Sgblack@eecs.umich.edu    //arises.
2884258Sgblack@eecs.umich.edu    template <class Type, class Base>
2894258Sgblack@eecs.umich.edu    class BitUnionOperators : public Base
2904257Sgblack@eecs.umich.edu    {
2914258Sgblack@eecs.umich.edu      public:
2924274Sgblack@eecs.umich.edu        operator Type () const
2934258Sgblack@eecs.umich.edu        {
2944258Sgblack@eecs.umich.edu            return Base::__data;
2954258Sgblack@eecs.umich.edu        }
2964257Sgblack@eecs.umich.edu
2974274Sgblack@eecs.umich.edu        Type
2984260Sgblack@eecs.umich.edu        operator=(const Type & _data)
2994258Sgblack@eecs.umich.edu        {
3004258Sgblack@eecs.umich.edu            Base::__data = _data;
3014274Sgblack@eecs.umich.edu            return _data;
3024258Sgblack@eecs.umich.edu        }
3034257Sgblack@eecs.umich.edu
3044258Sgblack@eecs.umich.edu        bool
3054274Sgblack@eecs.umich.edu        operator<(const Base & base) const
3064258Sgblack@eecs.umich.edu        {
3074258Sgblack@eecs.umich.edu            return Base::__data < base.__data;
3084258Sgblack@eecs.umich.edu        }
3094257Sgblack@eecs.umich.edu
3104258Sgblack@eecs.umich.edu        bool
3114274Sgblack@eecs.umich.edu        operator==(const Base & base) const
3124258Sgblack@eecs.umich.edu        {
3134258Sgblack@eecs.umich.edu            return Base::__data == base.__data;
3144258Sgblack@eecs.umich.edu        }
3154258Sgblack@eecs.umich.edu    };
3164258Sgblack@eecs.umich.edu}
3174257Sgblack@eecs.umich.edu
3184259Sgblack@eecs.umich.edu//This macro is a backend for other macros that specialize it slightly.
3194259Sgblack@eecs.umich.edu//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
3204259Sgblack@eecs.umich.edu//sticks the class which has the actual union in it, which
3214259Sgblack@eecs.umich.edu//BitfieldOperators above inherits from. Putting these classes in a special
3224259Sgblack@eecs.umich.edu//namespace ensures that there will be no collisions with other names as long
3234259Sgblack@eecs.umich.edu//as the BitUnion names themselves are all distinct and nothing else uses
3244259Sgblack@eecs.umich.edu//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
3254259Sgblack@eecs.umich.edu//creates a typedef of the "type" parameter called __DataType. This allows
3264259Sgblack@eecs.umich.edu//the type to propagate outside of the macro itself in a controlled way.
3274259Sgblack@eecs.umich.edu//Finally, the base storage is defined which BitfieldOperators will refer to
3284259Sgblack@eecs.umich.edu//in the operators it defines. This macro is intended to be followed by
3294259Sgblack@eecs.umich.edu//bitfield definitions which will end up inside it's union. As explained
3304259Sgblack@eecs.umich.edu//above, these is overlayed the __data member in its entirety by each of the
3314259Sgblack@eecs.umich.edu//bitfields which are defined in the union, creating shared storage with no
3324259Sgblack@eecs.umich.edu//overhead.
3334257Sgblack@eecs.umich.edu#define __BitUnion(type, name) \
3344258Sgblack@eecs.umich.edu    namespace BitfieldUnderlyingClasses \
3354258Sgblack@eecs.umich.edu    { \
3364258Sgblack@eecs.umich.edu        class name; \
3374258Sgblack@eecs.umich.edu    } \
3384262Sgblack@eecs.umich.edu    class BitfieldUnderlyingClasses::name : \
3394262Sgblack@eecs.umich.edu        public BitfieldBackend::BitfieldTypes<type> \
3404262Sgblack@eecs.umich.edu    { \
3414257Sgblack@eecs.umich.edu      public: \
3424257Sgblack@eecs.umich.edu        typedef type __DataType; \
3434257Sgblack@eecs.umich.edu        union { \
3444257Sgblack@eecs.umich.edu            type __data;\
3454257Sgblack@eecs.umich.edu
3464259Sgblack@eecs.umich.edu//This closes off the class and union started by the above macro. It is
3474259Sgblack@eecs.umich.edu//followed by a typedef which makes "name" refer to a BitfieldOperator
3484259Sgblack@eecs.umich.edu//class inheriting from the class and union just defined, which completes
3494259Sgblack@eecs.umich.edu//building up the type for the user.
3504257Sgblack@eecs.umich.edu#define EndBitUnion(name) \
3514257Sgblack@eecs.umich.edu        }; \
3524257Sgblack@eecs.umich.edu    }; \
3534258Sgblack@eecs.umich.edu    typedef BitfieldBackend::BitUnionOperators< \
3544258Sgblack@eecs.umich.edu        BitfieldUnderlyingClasses::name::__DataType, \
3554258Sgblack@eecs.umich.edu        BitfieldUnderlyingClasses::name> name;
3564257Sgblack@eecs.umich.edu
3574259Sgblack@eecs.umich.edu//This sets up a bitfield which has other bitfields nested inside of it. The
3584259Sgblack@eecs.umich.edu//__data member functions like the "underlying storage" of the top level
3594259Sgblack@eecs.umich.edu//BitUnion. Like everything else, it overlays with the top level storage, so
3604259Sgblack@eecs.umich.edu//making it a regular bitfield type makes the entire thing function as a
3614262Sgblack@eecs.umich.edu//regular bitfield when referred to by itself.
3624262Sgblack@eecs.umich.edu#define __SubBitUnion(fieldType, first, last, name) \
3634262Sgblack@eecs.umich.edu    class : public BitfieldBackend::BitfieldTypes<__DataType> \
3644262Sgblack@eecs.umich.edu    { \
3654262Sgblack@eecs.umich.edu      public: \
3664257Sgblack@eecs.umich.edu        union { \
3674262Sgblack@eecs.umich.edu            fieldType<first, last> __data;
3684257Sgblack@eecs.umich.edu
3694259Sgblack@eecs.umich.edu//This closes off the union created above and gives it a name. Unlike the top
3704259Sgblack@eecs.umich.edu//level BitUnion, we're interested in creating an object instead of a type.
3714262Sgblack@eecs.umich.edu//The operators are defined in the macro itself instead of a class for
3724262Sgblack@eecs.umich.edu//technical reasons. If someone determines a way to move them to one, please
3734262Sgblack@eecs.umich.edu//do so.
3744262Sgblack@eecs.umich.edu#define EndSubBitUnion(name) \
3754262Sgblack@eecs.umich.edu        }; \
3764262Sgblack@eecs.umich.edu        inline operator const __DataType () \
3774262Sgblack@eecs.umich.edu        { return __data; } \
3784262Sgblack@eecs.umich.edu        \
3794262Sgblack@eecs.umich.edu        inline const __DataType operator = (const __DataType & _data) \
3804262Sgblack@eecs.umich.edu        { __data = _data; } \
3814262Sgblack@eecs.umich.edu    } name;
3824258Sgblack@eecs.umich.edu
3834258Sgblack@eecs.umich.edu//Regular bitfields
3844262Sgblack@eecs.umich.edu//These define macros for read/write regular bitfield based subbitfields.
3854258Sgblack@eecs.umich.edu#define SubBitUnion(name, first, last) \
3864262Sgblack@eecs.umich.edu    __SubBitUnion(Bitfield, first, last, name)
3874257Sgblack@eecs.umich.edu
3884274Sgblack@eecs.umich.edu//Regular bitfields
3894274Sgblack@eecs.umich.edu//These define macros for read/write regular bitfield based subbitfields.
3904274Sgblack@eecs.umich.edu#define SignedSubBitUnion(name, first, last) \
3914274Sgblack@eecs.umich.edu    __SubBitUnion(SignedBitfield, first, last, name)
3924274Sgblack@eecs.umich.edu
3934259Sgblack@eecs.umich.edu//Use this to define an arbitrary type overlayed with bitfields.
3944257Sgblack@eecs.umich.edu#define BitUnion(type, name) __BitUnion(type, name)
3954257Sgblack@eecs.umich.edu
3964259Sgblack@eecs.umich.edu//Use this to define conveniently sized values overlayed with bitfields.
3974257Sgblack@eecs.umich.edu#define BitUnion64(name) __BitUnion(uint64_t, name)
3984257Sgblack@eecs.umich.edu#define BitUnion32(name) __BitUnion(uint32_t, name)
3994257Sgblack@eecs.umich.edu#define BitUnion16(name) __BitUnion(uint16_t, name)
4004257Sgblack@eecs.umich.edu#define BitUnion8(name) __BitUnion(uint8_t, name)
4014103Ssaidi@eecs.umich.edu
4021112SN/A#endif // __BASE_BITFIELD_HH__
403