bitfield.hh revision 4257
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>
364257Sgblack@eecs.umich.edu//#include "base/misc.hh"
372SN/A
382SN/A/**
392SN/A * Generate a 64-bit mask of 'nbits' 1s, right justified.
402SN/A */
412SN/Ainline uint64_t
422SN/Amask(int nbits)
432SN/A{
442SN/A    return (nbits == 64) ? (uint64_t)-1LL : (1ULL << nbits) - 1;
452SN/A}
462SN/A
472SN/A
484070Ssaidi@eecs.umich.edu
492SN/A/**
502SN/A * Extract the bitfield from position 'first' to 'last' (inclusive)
512SN/A * from 'val' and right justify it.  MSB is numbered 63, LSB is 0.
522SN/A */
532SN/Atemplate <class T>
542SN/Ainline
552SN/AT
562SN/Abits(T val, int first, int last)
572SN/A{
582SN/A    int nbits = first - last + 1;
592SN/A    return (val >> last) & mask(nbits);
602SN/A}
612SN/A
622SN/A/**
633814Ssaidi@eecs.umich.edu * Mask off the given bits in place like bits() but without shifting.
643814Ssaidi@eecs.umich.edu * msb = 63, lsb = 0
653814Ssaidi@eecs.umich.edu */
663814Ssaidi@eecs.umich.edutemplate <class T>
673814Ssaidi@eecs.umich.eduinline
683814Ssaidi@eecs.umich.eduT
693814Ssaidi@eecs.umich.edumbits(T val, int first, int last)
703814Ssaidi@eecs.umich.edu{
713814Ssaidi@eecs.umich.edu    return val & (mask(first+1) & ~mask(last));
723814Ssaidi@eecs.umich.edu}
733814Ssaidi@eecs.umich.edu
744070Ssaidi@eecs.umich.eduinline uint64_t
754070Ssaidi@eecs.umich.edumask(int first, int last)
764070Ssaidi@eecs.umich.edu{
774070Ssaidi@eecs.umich.edu    return mbits((uint64_t)-1LL, first, last);
784070Ssaidi@eecs.umich.edu}
794070Ssaidi@eecs.umich.edu
803814Ssaidi@eecs.umich.edu/**
812SN/A * Sign-extend an N-bit value to 64 bits.
822SN/A */
832SN/Atemplate <int N>
842SN/Ainline
852SN/Aint64_t
862SN/Asext(uint64_t val)
872SN/A{
882SN/A    int sign_bit = bits(val, N-1, N-1);
892SN/A    return sign_bit ? (val | ~mask(N)) : val;
902SN/A}
912SN/A
923422Sgblack@eecs.umich.edu/**
933422Sgblack@eecs.umich.edu * Return val with bits first to last set to bit_val
943422Sgblack@eecs.umich.edu */
953422Sgblack@eecs.umich.edutemplate <class T, class B>
963422Sgblack@eecs.umich.eduinline
973422Sgblack@eecs.umich.eduT
983422Sgblack@eecs.umich.eduinsertBits(T val, int first, int last, B bit_val)
993422Sgblack@eecs.umich.edu{
1003422Sgblack@eecs.umich.edu    T bmask = mask(first - last + 1) << last;
1013422Sgblack@eecs.umich.edu    return ((bit_val << last) & bmask) | (val & ~bmask);
1023422Sgblack@eecs.umich.edu}
1033422Sgblack@eecs.umich.edu
1043422Sgblack@eecs.umich.edu/**
1053422Sgblack@eecs.umich.edu * A convenience function to replace bits first to last of val with bit_val
1063422Sgblack@eecs.umich.edu * in place.
1073422Sgblack@eecs.umich.edu */
1083422Sgblack@eecs.umich.edutemplate <class T, class B>
1093422Sgblack@eecs.umich.eduinline
1103422Sgblack@eecs.umich.eduvoid
1113422Sgblack@eecs.umich.edureplaceBits(T& val, int first, int last, B bit_val)
1123422Sgblack@eecs.umich.edu{
1133422Sgblack@eecs.umich.edu    val = insertBits(val, first, last, bit_val);
1143422Sgblack@eecs.umich.edu}
1153422Sgblack@eecs.umich.edu
1164103Ssaidi@eecs.umich.edu/**
1174103Ssaidi@eecs.umich.edu * Returns the bit position of the MSB that is set in the input
1184103Ssaidi@eecs.umich.edu */
1194103Ssaidi@eecs.umich.eduinline
1204103Ssaidi@eecs.umich.eduint
1214103Ssaidi@eecs.umich.edufindMsbSet(uint64_t val) {
1224103Ssaidi@eecs.umich.edu    int msb = 0;
1234103Ssaidi@eecs.umich.edu    if (!val)
1244103Ssaidi@eecs.umich.edu        return 0;
1254244Ssaidi@eecs.umich.edu    if (bits(val, 63,32)) { msb += 32; val >>= 32; }
1264244Ssaidi@eecs.umich.edu    if (bits(val, 31,16)) { msb += 16; val >>= 16; }
1274244Ssaidi@eecs.umich.edu    if (bits(val, 15,8))  { msb += 8;  val >>= 8;  }
1284244Ssaidi@eecs.umich.edu    if (bits(val, 7,4))   { msb += 4;  val >>= 4;  }
1294244Ssaidi@eecs.umich.edu    if (bits(val, 3,2))   { msb += 2;  val >>= 2;  }
1304244Ssaidi@eecs.umich.edu    if (bits(val, 1,1))   { msb += 1; }
1314103Ssaidi@eecs.umich.edu    return msb;
1324103Ssaidi@eecs.umich.edu}
1334103Ssaidi@eecs.umich.edu
1344257Sgblack@eecs.umich.edutemplate<class Data, int first, int last=first>
1354257Sgblack@eecs.umich.educlass BitfieldBase
1364257Sgblack@eecs.umich.edu{
1374257Sgblack@eecs.umich.edu  protected:
1384257Sgblack@eecs.umich.edu    uint8_t __data[sizeof(Data)];
1394103Ssaidi@eecs.umich.edu
1404257Sgblack@eecs.umich.edu    //These are defined here so it can be specialized for Data, but can be
1414257Sgblack@eecs.umich.edu    //hidden by RO and WO variants.
1424257Sgblack@eecs.umich.edu    inline uint64_t getBits(int _first, int _last)
1434257Sgblack@eecs.umich.edu    {
1444257Sgblack@eecs.umich.edu        //build up the right bits from the byte array "data"
1454257Sgblack@eecs.umich.edu        //panic("Not yet implemented.\n");
1464257Sgblack@eecs.umich.edu        return 0;
1474257Sgblack@eecs.umich.edu    }
1484257Sgblack@eecs.umich.edu
1494257Sgblack@eecs.umich.edu    inline void setBits(int _first, int _last, uint64_t val)
1504257Sgblack@eecs.umich.edu    {
1514257Sgblack@eecs.umich.edu        //Set the right bits from the byte array "data"
1524257Sgblack@eecs.umich.edu        //panic("Not yet implemented.\n");
1534257Sgblack@eecs.umich.edu    }
1544257Sgblack@eecs.umich.edu};
1554257Sgblack@eecs.umich.edu
1564257Sgblack@eecs.umich.edutemplate<class Data, int first, int last=first>
1574257Sgblack@eecs.umich.educlass BitfieldNativeBase
1584257Sgblack@eecs.umich.edu{
1594257Sgblack@eecs.umich.edu  protected:
1604257Sgblack@eecs.umich.edu    Data __data;
1614257Sgblack@eecs.umich.edu
1624257Sgblack@eecs.umich.edu    inline uint64_t getBits(int _first, int _last)
1634257Sgblack@eecs.umich.edu    {
1644257Sgblack@eecs.umich.edu        return bits(__data, first, last);
1654257Sgblack@eecs.umich.edu    }
1664257Sgblack@eecs.umich.edu
1674257Sgblack@eecs.umich.edu    inline void setBits(int _first, int _last, uint64_t val)
1684257Sgblack@eecs.umich.edu    {
1694257Sgblack@eecs.umich.edu        replaceBits(__data, first, last, val);
1704257Sgblack@eecs.umich.edu    }
1714257Sgblack@eecs.umich.edu};
1724257Sgblack@eecs.umich.edu
1734257Sgblack@eecs.umich.edutemplate <int first>
1744257Sgblack@eecs.umich.educlass BitfieldBase<uint64_t, first, first> :
1754257Sgblack@eecs.umich.edu        public BitfieldNativeBase<uint64_t, first, first>
1764257Sgblack@eecs.umich.edu{};
1774257Sgblack@eecs.umich.edu
1784257Sgblack@eecs.umich.edutemplate <int first, int last>
1794257Sgblack@eecs.umich.educlass BitfieldBase<uint64_t, first, last> :
1804257Sgblack@eecs.umich.edu        public BitfieldNativeBase<uint64_t, first, last>
1814257Sgblack@eecs.umich.edu{};
1824257Sgblack@eecs.umich.edu
1834257Sgblack@eecs.umich.edutemplate <int first>
1844257Sgblack@eecs.umich.educlass BitfieldBase<uint32_t, first, first> :
1854257Sgblack@eecs.umich.edu        public BitfieldNativeBase<uint32_t, first, first>
1864257Sgblack@eecs.umich.edu{};
1874257Sgblack@eecs.umich.edu
1884257Sgblack@eecs.umich.edutemplate <int first, int last>
1894257Sgblack@eecs.umich.educlass BitfieldBase<uint32_t, first, last> :
1904257Sgblack@eecs.umich.edu        public BitfieldNativeBase<uint32_t, first, last>
1914257Sgblack@eecs.umich.edu{};
1924257Sgblack@eecs.umich.edu
1934257Sgblack@eecs.umich.edutemplate <int first>
1944257Sgblack@eecs.umich.educlass BitfieldBase<uint16_t, first, first> :
1954257Sgblack@eecs.umich.edu        public BitfieldNativeBase<uint16_t, first, first>
1964257Sgblack@eecs.umich.edu{};
1974257Sgblack@eecs.umich.edu
1984257Sgblack@eecs.umich.edutemplate <int first, int last>
1994257Sgblack@eecs.umich.educlass BitfieldBase<uint16_t, first, last> :
2004257Sgblack@eecs.umich.edu        public BitfieldNativeBase<uint16_t, first, last>
2014257Sgblack@eecs.umich.edu{};
2024257Sgblack@eecs.umich.edu
2034257Sgblack@eecs.umich.edutemplate <int first>
2044257Sgblack@eecs.umich.educlass BitfieldBase<uint8_t, first, first> :
2054257Sgblack@eecs.umich.edu        public BitfieldNativeBase<uint8_t, first, first>
2064257Sgblack@eecs.umich.edu{};
2074257Sgblack@eecs.umich.edu
2084257Sgblack@eecs.umich.edutemplate <int first, int last>
2094257Sgblack@eecs.umich.educlass BitfieldBase<uint8_t, first, last> :
2104257Sgblack@eecs.umich.edu        public BitfieldNativeBase<uint8_t, first, last>
2114257Sgblack@eecs.umich.edu{};
2124257Sgblack@eecs.umich.edu
2134257Sgblack@eecs.umich.edutemplate<class Data, int first, int last=first>
2144257Sgblack@eecs.umich.educlass _BitfieldRO : public BitfieldBase<Data, first, last>
2154257Sgblack@eecs.umich.edu{
2164257Sgblack@eecs.umich.edu  public:
2174257Sgblack@eecs.umich.edu    operator const Data & ()
2184257Sgblack@eecs.umich.edu    {
2194257Sgblack@eecs.umich.edu        return this->getBits(first, last);
2204257Sgblack@eecs.umich.edu    }
2214257Sgblack@eecs.umich.edu};
2224257Sgblack@eecs.umich.edu
2234257Sgblack@eecs.umich.edutemplate<class Data, int first, int last=first>
2244257Sgblack@eecs.umich.educlass _BitfieldWO : public BitfieldBase<Data, first, last>
2254257Sgblack@eecs.umich.edu{
2264257Sgblack@eecs.umich.edu  public:
2274257Sgblack@eecs.umich.edu    const Data & operator = (const Data & _data)
2284257Sgblack@eecs.umich.edu    {
2294257Sgblack@eecs.umich.edu        this->setBits(first, last, _data);
2304257Sgblack@eecs.umich.edu        return *this;
2314257Sgblack@eecs.umich.edu    }
2324257Sgblack@eecs.umich.edu};
2334257Sgblack@eecs.umich.edu
2344257Sgblack@eecs.umich.edutemplate<class Data, int first, int last=first>
2354257Sgblack@eecs.umich.educlass _BitfieldRW : public BitfieldBase<Data, first, last>
2364257Sgblack@eecs.umich.edu{
2374257Sgblack@eecs.umich.edu  public:
2384257Sgblack@eecs.umich.edu    operator const Data ()
2394257Sgblack@eecs.umich.edu    {
2404257Sgblack@eecs.umich.edu        return this->getBits(first, last);
2414257Sgblack@eecs.umich.edu    }
2424257Sgblack@eecs.umich.edu
2434257Sgblack@eecs.umich.edu    const Data operator = (const Data & _data)
2444257Sgblack@eecs.umich.edu    {
2454257Sgblack@eecs.umich.edu        this->setBits(first, last, _data);
2464257Sgblack@eecs.umich.edu        return *this;
2474257Sgblack@eecs.umich.edu    }
2484257Sgblack@eecs.umich.edu};
2494257Sgblack@eecs.umich.edu
2504257Sgblack@eecs.umich.edutemplate <class Type, class Base>
2514257Sgblack@eecs.umich.educlass BitUnionOperators : public Base
2524257Sgblack@eecs.umich.edu{
2534257Sgblack@eecs.umich.edu  public:
2544257Sgblack@eecs.umich.edu    operator const Type ()
2554257Sgblack@eecs.umich.edu    {
2564257Sgblack@eecs.umich.edu        return Base::__data;
2574257Sgblack@eecs.umich.edu    }
2584257Sgblack@eecs.umich.edu
2594257Sgblack@eecs.umich.edu    const Type operator = (const Type & _data)
2604257Sgblack@eecs.umich.edu    {
2614257Sgblack@eecs.umich.edu        Base::__data = _data;
2624257Sgblack@eecs.umich.edu    }
2634257Sgblack@eecs.umich.edu
2644257Sgblack@eecs.umich.edu    bool operator < (const Base & base)
2654257Sgblack@eecs.umich.edu    {
2664257Sgblack@eecs.umich.edu        return Base::__data < base.__data;
2674257Sgblack@eecs.umich.edu    }
2684257Sgblack@eecs.umich.edu
2694257Sgblack@eecs.umich.edu    bool operator == (const Base & base)
2704257Sgblack@eecs.umich.edu    {
2714257Sgblack@eecs.umich.edu        return Base::__data == base.__data;
2724257Sgblack@eecs.umich.edu    }
2734257Sgblack@eecs.umich.edu};
2744257Sgblack@eecs.umich.edu
2754257Sgblack@eecs.umich.edu#define __BitUnion(type, name) \
2764257Sgblack@eecs.umich.edu    class __##name { \
2774257Sgblack@eecs.umich.edu      public: \
2784257Sgblack@eecs.umich.edu        typedef type __DataType; \
2794257Sgblack@eecs.umich.edu        union { \
2804257Sgblack@eecs.umich.edu            type __data;\
2814257Sgblack@eecs.umich.edu
2824257Sgblack@eecs.umich.edu#define EndBitUnion(name) \
2834257Sgblack@eecs.umich.edu        }; \
2844257Sgblack@eecs.umich.edu    }; \
2854257Sgblack@eecs.umich.edu    typedef BitUnionOperators<__##name::__DataType, __##name> name;
2864257Sgblack@eecs.umich.edu
2874257Sgblack@eecs.umich.edu#define __SubBitUnion(type, name) \
2884257Sgblack@eecs.umich.edu        union { \
2894257Sgblack@eecs.umich.edu            type __data; \
2904257Sgblack@eecs.umich.edu            inline operator const __DataType () \
2914257Sgblack@eecs.umich.edu            { return __data; } \
2924257Sgblack@eecs.umich.edu            \
2934257Sgblack@eecs.umich.edu            inline const __DataType operator = (const __DataType & _data) \
2944257Sgblack@eecs.umich.edu            { __data = _data; }
2954257Sgblack@eecs.umich.edu
2964257Sgblack@eecs.umich.edu#define EndSubBitUnion(name) } name;
2974257Sgblack@eecs.umich.edu
2984257Sgblack@eecs.umich.edu//Regular read/write bitfields
2994257Sgblack@eecs.umich.edu#define BitfieldRW(first, last) _BitfieldRW<__DataType, first, last>
3004257Sgblack@eecs.umich.edu#define SubBitUnionRW(name, first, last) \
3014257Sgblack@eecs.umich.edu        __SubBitUnion(BitfieldRW(first, last), name)
3024257Sgblack@eecs.umich.edu#define Bitfield(first, last) BitfieldRW(first, last)
3034257Sgblack@eecs.umich.edu#define SubBitUnion(name, first, last) SubBitUnionRW(name, first, last)
3044257Sgblack@eecs.umich.edu
3054257Sgblack@eecs.umich.edu//Read only bitfields
3064257Sgblack@eecs.umich.edu#define BitfieldRO(first, last) _BitfieldRO<__DataType, first, last>
3074257Sgblack@eecs.umich.edu#define SubBitUnionRO(name, first, last) \
3084257Sgblack@eecs.umich.edu        __SubBitUnion(BitfieldRO(first, last), name)
3094257Sgblack@eecs.umich.edu
3104257Sgblack@eecs.umich.edu//Write only bitfields
3114257Sgblack@eecs.umich.edu#define BitfieldWO(first, last) _BitfieldWO<__DataType, first, last>
3124257Sgblack@eecs.umich.edu#define SubBitUnionWO(name, first, last) \
3134257Sgblack@eecs.umich.edu        __SubBitUnion(BitfieldWO(first, last), name)
3144257Sgblack@eecs.umich.edu
3154257Sgblack@eecs.umich.edu#define BitUnion(type, name) __BitUnion(type, name)
3164257Sgblack@eecs.umich.edu
3174257Sgblack@eecs.umich.edu#define BitUnion64(name) __BitUnion(uint64_t, name)
3184257Sgblack@eecs.umich.edu#define BitUnion32(name) __BitUnion(uint32_t, name)
3194257Sgblack@eecs.umich.edu#define BitUnion16(name) __BitUnion(uint16_t, name)
3204257Sgblack@eecs.umich.edu#define BitUnion8(name) __BitUnion(uint8_t, name)
3214103Ssaidi@eecs.umich.edu
3221112SN/A#endif // __BASE_BITFIELD_HH__
323