bitfield.hh revision 4258
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
1334258Sgblack@eecs.umich.edunamespace BitfieldBackend
1344257Sgblack@eecs.umich.edu{
1354258Sgblack@eecs.umich.edu    template<class Data>
1364258Sgblack@eecs.umich.edu    class BitfieldBase
1374258Sgblack@eecs.umich.edu    {
1384258Sgblack@eecs.umich.edu      protected:
1394258Sgblack@eecs.umich.edu        Data __data;
1404103Ssaidi@eecs.umich.edu
1414258Sgblack@eecs.umich.edu        inline uint64_t
1424258Sgblack@eecs.umich.edu        getBits(int first, int last)
1434258Sgblack@eecs.umich.edu        {
1444258Sgblack@eecs.umich.edu            return bits(__data, first, last);
1454258Sgblack@eecs.umich.edu        }
1464258Sgblack@eecs.umich.edu
1474258Sgblack@eecs.umich.edu        inline void
1484258Sgblack@eecs.umich.edu        setBits(int first, int last, uint64_t val)
1494258Sgblack@eecs.umich.edu        {
1504258Sgblack@eecs.umich.edu            replaceBits(__data, first, last, val);
1514258Sgblack@eecs.umich.edu        }
1524258Sgblack@eecs.umich.edu    };
1534258Sgblack@eecs.umich.edu
1544258Sgblack@eecs.umich.edu    template<class Type, class Base>
1554258Sgblack@eecs.umich.edu    class _BitfieldRO : public Base
1564257Sgblack@eecs.umich.edu    {
1574258Sgblack@eecs.umich.edu      public:
1584258Sgblack@eecs.umich.edu        operator const Type ()
1594258Sgblack@eecs.umich.edu        {
1604258Sgblack@eecs.umich.edu            return *((Base *)this);
1614258Sgblack@eecs.umich.edu        }
1624258Sgblack@eecs.umich.edu    };
1634257Sgblack@eecs.umich.edu
1644258Sgblack@eecs.umich.edu    template<class Type, class Base>
1654258Sgblack@eecs.umich.edu    class _BitfieldWO : public Base
1664257Sgblack@eecs.umich.edu    {
1674258Sgblack@eecs.umich.edu      public:
1684258Sgblack@eecs.umich.edu        const Type operator = (const Type & _data)
1694258Sgblack@eecs.umich.edu        {
1704258Sgblack@eecs.umich.edu            *((Base *)this) = _data;
1714258Sgblack@eecs.umich.edu            return _data;
1724258Sgblack@eecs.umich.edu        }
1734258Sgblack@eecs.umich.edu    };
1744257Sgblack@eecs.umich.edu
1754258Sgblack@eecs.umich.edu    template<class Data, int first, int last=first>
1764258Sgblack@eecs.umich.edu    class _Bitfield : public BitfieldBase<Data>
1774258Sgblack@eecs.umich.edu    {
1784258Sgblack@eecs.umich.edu      public:
1794258Sgblack@eecs.umich.edu        operator const Data ()
1804258Sgblack@eecs.umich.edu        {
1814258Sgblack@eecs.umich.edu            return this->getBits(first, last);
1824258Sgblack@eecs.umich.edu        }
1834257Sgblack@eecs.umich.edu
1844258Sgblack@eecs.umich.edu        const Data
1854258Sgblack@eecs.umich.edu        operator = (const Data & _data)
1864258Sgblack@eecs.umich.edu        {
1874258Sgblack@eecs.umich.edu            this->setBits(first, last, _data);
1884258Sgblack@eecs.umich.edu            return _data;
1894258Sgblack@eecs.umich.edu        }
1904258Sgblack@eecs.umich.edu    };
1914258Sgblack@eecs.umich.edu
1924258Sgblack@eecs.umich.edu    template <class Type, class Base>
1934258Sgblack@eecs.umich.edu    class BitUnionOperators : public Base
1944257Sgblack@eecs.umich.edu    {
1954258Sgblack@eecs.umich.edu      public:
1964258Sgblack@eecs.umich.edu        operator const Type ()
1974258Sgblack@eecs.umich.edu        {
1984258Sgblack@eecs.umich.edu            return Base::__data;
1994258Sgblack@eecs.umich.edu        }
2004257Sgblack@eecs.umich.edu
2014258Sgblack@eecs.umich.edu        const Type
2024258Sgblack@eecs.umich.edu        operator = (const Type & _data)
2034258Sgblack@eecs.umich.edu        {
2044258Sgblack@eecs.umich.edu            Base::__data = _data;
2054258Sgblack@eecs.umich.edu        }
2064257Sgblack@eecs.umich.edu
2074258Sgblack@eecs.umich.edu        bool
2084258Sgblack@eecs.umich.edu        operator < (const Base & base)
2094258Sgblack@eecs.umich.edu        {
2104258Sgblack@eecs.umich.edu            return Base::__data < base.__data;
2114258Sgblack@eecs.umich.edu        }
2124257Sgblack@eecs.umich.edu
2134258Sgblack@eecs.umich.edu        bool
2144258Sgblack@eecs.umich.edu        operator == (const Base & base)
2154258Sgblack@eecs.umich.edu        {
2164258Sgblack@eecs.umich.edu            return Base::__data == base.__data;
2174258Sgblack@eecs.umich.edu        }
2184258Sgblack@eecs.umich.edu    };
2194258Sgblack@eecs.umich.edu}
2204257Sgblack@eecs.umich.edu
2214257Sgblack@eecs.umich.edu#define __BitUnion(type, name) \
2224258Sgblack@eecs.umich.edu    namespace BitfieldUnderlyingClasses \
2234258Sgblack@eecs.umich.edu    { \
2244258Sgblack@eecs.umich.edu        class name; \
2254258Sgblack@eecs.umich.edu    } \
2264258Sgblack@eecs.umich.edu    class BitfieldUnderlyingClasses::name { \
2274257Sgblack@eecs.umich.edu      public: \
2284257Sgblack@eecs.umich.edu        typedef type __DataType; \
2294257Sgblack@eecs.umich.edu        union { \
2304257Sgblack@eecs.umich.edu            type __data;\
2314257Sgblack@eecs.umich.edu
2324257Sgblack@eecs.umich.edu#define EndBitUnion(name) \
2334257Sgblack@eecs.umich.edu        }; \
2344257Sgblack@eecs.umich.edu    }; \
2354258Sgblack@eecs.umich.edu    typedef BitfieldBackend::BitUnionOperators< \
2364258Sgblack@eecs.umich.edu        BitfieldUnderlyingClasses::name::__DataType, \
2374258Sgblack@eecs.umich.edu        BitfieldUnderlyingClasses::name> name;
2384257Sgblack@eecs.umich.edu
2394257Sgblack@eecs.umich.edu#define __SubBitUnion(type, name) \
2404257Sgblack@eecs.umich.edu        union { \
2414257Sgblack@eecs.umich.edu            type __data; \
2424257Sgblack@eecs.umich.edu            inline operator const __DataType () \
2434257Sgblack@eecs.umich.edu            { return __data; } \
2444257Sgblack@eecs.umich.edu            \
2454257Sgblack@eecs.umich.edu            inline const __DataType operator = (const __DataType & _data) \
2464257Sgblack@eecs.umich.edu            { __data = _data; }
2474257Sgblack@eecs.umich.edu
2484257Sgblack@eecs.umich.edu#define EndSubBitUnion(name) } name;
2494257Sgblack@eecs.umich.edu
2504258Sgblack@eecs.umich.edu//This is so we can send in parameters with commas
2514258Sgblack@eecs.umich.edu#define wrap(guts) guts
2524257Sgblack@eecs.umich.edu
2534257Sgblack@eecs.umich.edu//Read only bitfields
2544258Sgblack@eecs.umich.edu#define __BitfieldRO(base) \
2554258Sgblack@eecs.umich.edu    BitfieldBackend::_BitfieldRO<__DataType, base>
2564258Sgblack@eecs.umich.edu#define __SubBitUnionRO(name, base) \
2574258Sgblack@eecs.umich.edu    __SubBitUnion(wrap(_BitfieldRO<__DataType, base>), name)
2584257Sgblack@eecs.umich.edu
2594257Sgblack@eecs.umich.edu//Write only bitfields
2604258Sgblack@eecs.umich.edu#define __BitfieldWO(base) \
2614258Sgblack@eecs.umich.edu    BitfieldBackend::_BitfieldWO<__DataType, base>
2624258Sgblack@eecs.umich.edu#define __SubBitUnionWO(name, base) \
2634258Sgblack@eecs.umich.edu    __SubBitUnion(wrap(_BitfieldWO<__DataType, base>), name)
2644258Sgblack@eecs.umich.edu
2654258Sgblack@eecs.umich.edu//Regular bitfields
2664258Sgblack@eecs.umich.edu#define Bitfield(first, last) \
2674258Sgblack@eecs.umich.edu    BitfieldBackend::_Bitfield<__DataType, first, last>
2684258Sgblack@eecs.umich.edu#define SubBitUnion(name, first, last) \
2694258Sgblack@eecs.umich.edu    __SubBitUnion(Bitfield(first, last), name)
2704258Sgblack@eecs.umich.edu#define BitfieldRO(first, last) __BitfieldRO(Bitfield(first, last))
2714258Sgblack@eecs.umich.edu#define SubBitUnionRO(name, first, last) \
2724258Sgblack@eecs.umich.edu    __SubBitUnionRO(Bitfield(first, last), name)
2734258Sgblack@eecs.umich.edu#define BitfieldWO(first, last) __BitfieldWO(Bitfield(first, last))
2744257Sgblack@eecs.umich.edu#define SubBitUnionWO(name, first, last) \
2754258Sgblack@eecs.umich.edu    __SubBitUnionWO(Bitfield(first, last), name)
2764257Sgblack@eecs.umich.edu
2774257Sgblack@eecs.umich.edu#define BitUnion(type, name) __BitUnion(type, name)
2784257Sgblack@eecs.umich.edu
2794257Sgblack@eecs.umich.edu#define BitUnion64(name) __BitUnion(uint64_t, name)
2804257Sgblack@eecs.umich.edu#define BitUnion32(name) __BitUnion(uint32_t, name)
2814257Sgblack@eecs.umich.edu#define BitUnion16(name) __BitUnion(uint16_t, name)
2824257Sgblack@eecs.umich.edu#define BitUnion8(name) __BitUnion(uint8_t, name)
2834103Ssaidi@eecs.umich.edu
2841112SN/A#endif // __BASE_BITFIELD_HH__
285