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