bitunion.hh revision 11294:a368064a2ab5
17753SWilliam.Wang@arm.com/* 29394Sandreas.hansson@arm.com * Copyright (c) 2007-2008 The Regents of The University of Michigan 37753SWilliam.Wang@arm.com * All rights reserved. 47753SWilliam.Wang@arm.com * 57753SWilliam.Wang@arm.com * Redistribution and use in source and binary forms, with or without 67753SWilliam.Wang@arm.com * modification, are permitted provided that the following conditions are 77753SWilliam.Wang@arm.com * met: redistributions of source code must retain the above copyright 87753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer; 97753SWilliam.Wang@arm.com * redistributions in binary form must reproduce the above copyright 107753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer in the 117753SWilliam.Wang@arm.com * documentation and/or other materials provided with the distribution; 127753SWilliam.Wang@arm.com * neither the name of the copyright holders nor the names of its 137753SWilliam.Wang@arm.com * contributors may be used to endorse or promote products derived from 147753SWilliam.Wang@arm.com * this software without specific prior written permission. 157753SWilliam.Wang@arm.com * 167753SWilliam.Wang@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177753SWilliam.Wang@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187753SWilliam.Wang@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197753SWilliam.Wang@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207753SWilliam.Wang@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217753SWilliam.Wang@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227753SWilliam.Wang@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237753SWilliam.Wang@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247753SWilliam.Wang@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257753SWilliam.Wang@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267753SWilliam.Wang@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277753SWilliam.Wang@arm.com * 287753SWilliam.Wang@arm.com * Authors: Gabe Black 297753SWilliam.Wang@arm.com */ 307753SWilliam.Wang@arm.com 317753SWilliam.Wang@arm.com#ifndef __BASE_BITUNION_HH__ 327753SWilliam.Wang@arm.com#define __BASE_BITUNION_HH__ 337753SWilliam.Wang@arm.com 347753SWilliam.Wang@arm.com#include "base/bitfield.hh" 357753SWilliam.Wang@arm.com#include "base/types.hh" 367753SWilliam.Wang@arm.com 377753SWilliam.Wang@arm.com// The following implements the BitUnion system of defining bitfields 387950SAli.Saidi@ARM.com//on top of an underlying class. This is done through the pervasive use of 397753SWilliam.Wang@arm.com//both named and unnamed unions which all contain the same actual storage. 407753SWilliam.Wang@arm.com//Since they're unioned with each other, all of these storage locations 419330Schander.sudanthi@arm.com//overlap. This allows all of the bitfields to manipulate the same data 427950SAli.Saidi@ARM.com//without having to have access to each other. More details are provided with 437950SAli.Saidi@ARM.com//the individual components. 447753SWilliam.Wang@arm.com 458245Snate@binkert.org//This namespace is for classes which implement the backend of the BitUnion 468245Snate@binkert.org//stuff. Don't use any of these directly, except for the Bitfield classes in 477753SWilliam.Wang@arm.com//the *BitfieldTypes class(es). 489525SAndreas.Sandberg@ARM.comnamespace BitfieldBackend 497753SWilliam.Wang@arm.com{ 507753SWilliam.Wang@arm.com //A base class for all bitfields. It instantiates the actual storage, 517753SWilliam.Wang@arm.com //and provides getBits and setBits functions for manipulating it. The 529525SAndreas.Sandberg@ARM.com //Data template parameter is type of the underlying storage. 537753SWilliam.Wang@arm.com template<class Data> 548737Skoansin.tan@gmail.com class BitfieldBase 558737Skoansin.tan@gmail.com { 568737Skoansin.tan@gmail.com protected: 578737Skoansin.tan@gmail.com Data __data; 587753SWilliam.Wang@arm.com 597753SWilliam.Wang@arm.com //This function returns a range of bits from the underlying storage. 607753SWilliam.Wang@arm.com //It relies on the "bits" function above. It's the user's 617753SWilliam.Wang@arm.com //responsibility to make sure that there is a properly overloaded 627950SAli.Saidi@ARM.com //version of this function for whatever type they want to overlay. 637753SWilliam.Wang@arm.com inline uint64_t 647753SWilliam.Wang@arm.com getBits(int first, int last) const 659157Sandreas.hansson@arm.com { 669530SChris.Emmons@arm.com return bits(__data, first, last); 679530SChris.Emmons@arm.com } 687950SAli.Saidi@ARM.com 697753SWilliam.Wang@arm.com //Similar to the above, but for settings bits with replaceBits. 709395SAndreas.Sandberg@ARM.com inline void 719395SAndreas.Sandberg@ARM.com setBits(int first, int last, uint64_t val) 729939Sdam.sunwoo@arm.com { 737753SWilliam.Wang@arm.com replaceBits(__data, first, last, val); 747753SWilliam.Wang@arm.com } 757753SWilliam.Wang@arm.com }; 768737Skoansin.tan@gmail.com 777950SAli.Saidi@ARM.com //This class contains all the "regular" bitfield classes. It is inherited 787753SWilliam.Wang@arm.com //by all BitUnions which give them access to those types. 797753SWilliam.Wang@arm.com template<class Type> 808737Skoansin.tan@gmail.com class RegularBitfieldTypes 817950SAli.Saidi@ARM.com { 829395SAndreas.Sandberg@ARM.com protected: 839395SAndreas.Sandberg@ARM.com //This class implements ordinary bitfields, that is a span of bits 849395SAndreas.Sandberg@ARM.com //who's msb is "first", and who's lsb is "last". 859330Schander.sudanthi@arm.com template<int first, int last=first> 869330Schander.sudanthi@arm.com class Bitfield : public BitfieldBase<Type> 877753SWilliam.Wang@arm.com { 887753SWilliam.Wang@arm.com static_assert(first >= last, 899086Sandreas.hansson@arm.com "Bitfield ranges must be specified as <msb, lsb>"); 909086Sandreas.hansson@arm.com 919086Sandreas.hansson@arm.com public: 929086Sandreas.hansson@arm.com operator uint64_t () const 939086Sandreas.hansson@arm.com { 947753SWilliam.Wang@arm.com return this->getBits(first, last); 957753SWilliam.Wang@arm.com } 967753SWilliam.Wang@arm.com 977753SWilliam.Wang@arm.com uint64_t 987753SWilliam.Wang@arm.com operator=(const uint64_t _data) 997753SWilliam.Wang@arm.com { 1007753SWilliam.Wang@arm.com this->setBits(first, last, _data); 1017753SWilliam.Wang@arm.com return _data; 1027753SWilliam.Wang@arm.com } 1037950SAli.Saidi@ARM.com 1047950SAli.Saidi@ARM.com uint64_t 1057753SWilliam.Wang@arm.com operator=(Bitfield<first, last> const & other) 1067950SAli.Saidi@ARM.com { 1077950SAli.Saidi@ARM.com return *this = (uint64_t)other; 1087753SWilliam.Wang@arm.com } 1097950SAli.Saidi@ARM.com }; 1107753SWilliam.Wang@arm.com 1117950SAli.Saidi@ARM.com //A class which specializes the above so that it can only be read 1127950SAli.Saidi@ARM.com //from. This is accomplished explicitly making sure the assignment 1137950SAli.Saidi@ARM.com //operator is blocked. The conversion operator is carried through 1147950SAli.Saidi@ARM.com //inheritance. This will unfortunately need to be copied into each 1157950SAli.Saidi@ARM.com //bitfield type due to limitations with how templates work 1167950SAli.Saidi@ARM.com template<int first, int last=first> 1177950SAli.Saidi@ARM.com class BitfieldRO : public Bitfield<first, last> 1187950SAli.Saidi@ARM.com { 1197950SAli.Saidi@ARM.com private: 1207950SAli.Saidi@ARM.com uint64_t 1217950SAli.Saidi@ARM.com operator=(const uint64_t _data); 1227950SAli.Saidi@ARM.com 1237950SAli.Saidi@ARM.com uint64_t 1247950SAli.Saidi@ARM.com operator=(const Bitfield<first, last>& other); 1257950SAli.Saidi@ARM.com }; 1267950SAli.Saidi@ARM.com 1277950SAli.Saidi@ARM.com //Similar to the above, but only allows writing. 1287950SAli.Saidi@ARM.com template<int first, int last=first> 1297950SAli.Saidi@ARM.com class BitfieldWO : public Bitfield<first, last> 1307950SAli.Saidi@ARM.com { 1317950SAli.Saidi@ARM.com private: 1327950SAli.Saidi@ARM.com operator uint64_t () const; 1337950SAli.Saidi@ARM.com 1347950SAli.Saidi@ARM.com public: 1357950SAli.Saidi@ARM.com using Bitfield<first, last>::operator=; 1367950SAli.Saidi@ARM.com }; 1377950SAli.Saidi@ARM.com }; 1387950SAli.Saidi@ARM.com 1397950SAli.Saidi@ARM.com //This class contains all the "regular" bitfield classes. It is inherited 1407950SAli.Saidi@ARM.com //by all BitUnions which give them access to those types. 1417950SAli.Saidi@ARM.com template<class Type> 1427950SAli.Saidi@ARM.com class SignedBitfieldTypes 1437950SAli.Saidi@ARM.com { 1447950SAli.Saidi@ARM.com protected: 1457950SAli.Saidi@ARM.com //This class implements ordinary bitfields, that is a span of bits 1467950SAli.Saidi@ARM.com //who's msb is "first", and who's lsb is "last". 1477950SAli.Saidi@ARM.com template<int first, int last=first> 1487950SAli.Saidi@ARM.com class SignedBitfield : public BitfieldBase<Type> 1497950SAli.Saidi@ARM.com { 1507950SAli.Saidi@ARM.com public: 1517950SAli.Saidi@ARM.com operator int64_t () const 1527950SAli.Saidi@ARM.com { 1537950SAli.Saidi@ARM.com return sext<first - last + 1>(this->getBits(first, last)); 1547950SAli.Saidi@ARM.com } 1557950SAli.Saidi@ARM.com 1567950SAli.Saidi@ARM.com int64_t 1577950SAli.Saidi@ARM.com operator=(const int64_t _data) 1587950SAli.Saidi@ARM.com { 1597950SAli.Saidi@ARM.com this->setBits(first, last, _data); 1607950SAli.Saidi@ARM.com return _data; 1617950SAli.Saidi@ARM.com } 1627950SAli.Saidi@ARM.com 1637950SAli.Saidi@ARM.com int64_t 1647950SAli.Saidi@ARM.com operator=(SignedBitfield<first, last> const & other) 1657950SAli.Saidi@ARM.com { 1667950SAli.Saidi@ARM.com return *this = (int64_t)other; 1677950SAli.Saidi@ARM.com } 1687950SAli.Saidi@ARM.com }; 1697950SAli.Saidi@ARM.com 1707950SAli.Saidi@ARM.com //A class which specializes the above so that it can only be read 1717950SAli.Saidi@ARM.com //from. This is accomplished explicitly making sure the assignment 1727950SAli.Saidi@ARM.com //operator is blocked. The conversion operator is carried through 1737950SAli.Saidi@ARM.com //inheritance. This will unfortunately need to be copied into each 1747950SAli.Saidi@ARM.com //bitfield type due to limitations with how templates work 1757950SAli.Saidi@ARM.com template<int first, int last=first> 1767950SAli.Saidi@ARM.com class SignedBitfieldRO : public SignedBitfield<first, last> 1777950SAli.Saidi@ARM.com { 1787950SAli.Saidi@ARM.com private: 1797950SAli.Saidi@ARM.com int64_t 1807950SAli.Saidi@ARM.com operator=(const int64_t _data); 1817950SAli.Saidi@ARM.com 1829806Sstever@gmail.com int64_t 1837950SAli.Saidi@ARM.com operator=(const SignedBitfield<first, last>& other); 1847950SAli.Saidi@ARM.com }; 1857753SWilliam.Wang@arm.com 1867950SAli.Saidi@ARM.com //Similar to the above, but only allows writing. 1877950SAli.Saidi@ARM.com template<int first, int last=first> 1887950SAli.Saidi@ARM.com class SignedBitfieldWO : public SignedBitfield<first, last> 1897950SAli.Saidi@ARM.com { 1907950SAli.Saidi@ARM.com private: 1917753SWilliam.Wang@arm.com operator int64_t () const; 1927950SAli.Saidi@ARM.com 1937950SAli.Saidi@ARM.com public: 1947950SAli.Saidi@ARM.com using SignedBitfield<first, last>::operator=; 1957950SAli.Saidi@ARM.com }; 1967950SAli.Saidi@ARM.com }; 1977753SWilliam.Wang@arm.com 1987950SAli.Saidi@ARM.com template<class Type> 1997950SAli.Saidi@ARM.com class BitfieldTypes : public RegularBitfieldTypes<Type>, 2007950SAli.Saidi@ARM.com public SignedBitfieldTypes<Type> 2017753SWilliam.Wang@arm.com {}; 2027753SWilliam.Wang@arm.com 2037753SWilliam.Wang@arm.com //When a BitUnion is set up, an underlying class is created which holds 2047753SWilliam.Wang@arm.com //the actual union. This class then inherits from it, and provids the 2057753SWilliam.Wang@arm.com //implementations for various operators. Setting things up this way 2067753SWilliam.Wang@arm.com //prevents having to redefine these functions in every different BitUnion 2077753SWilliam.Wang@arm.com //type. More operators could be implemented in the future, as the need 2087753SWilliam.Wang@arm.com //arises. 2097753SWilliam.Wang@arm.com template <class Type, class Base> 2107753SWilliam.Wang@arm.com class BitUnionOperators : public Base 2117753SWilliam.Wang@arm.com { 2127753SWilliam.Wang@arm.com public: 2137753SWilliam.Wang@arm.com BitUnionOperators(Type const & _data) 2147753SWilliam.Wang@arm.com { 2157753SWilliam.Wang@arm.com Base::__data = _data; 2167753SWilliam.Wang@arm.com } 2177753SWilliam.Wang@arm.com 2187753SWilliam.Wang@arm.com BitUnionOperators() {} 2197753SWilliam.Wang@arm.com 2207753SWilliam.Wang@arm.com operator const Type () const 2217753SWilliam.Wang@arm.com { 2227753SWilliam.Wang@arm.com return Base::__data; 2237753SWilliam.Wang@arm.com } 2247753SWilliam.Wang@arm.com 2257753SWilliam.Wang@arm.com Type 2267753SWilliam.Wang@arm.com operator=(Type const & _data) 2277753SWilliam.Wang@arm.com { 2287753SWilliam.Wang@arm.com Base::__data = _data; 2297753SWilliam.Wang@arm.com return _data; 2307753SWilliam.Wang@arm.com } 2317753SWilliam.Wang@arm.com 2327753SWilliam.Wang@arm.com Type 2337753SWilliam.Wang@arm.com operator=(BitUnionOperators const & other) 2347753SWilliam.Wang@arm.com { 2357753SWilliam.Wang@arm.com Base::__data = other; 2367753SWilliam.Wang@arm.com return Base::__data; 2377753SWilliam.Wang@arm.com } 2387753SWilliam.Wang@arm.com 2397753SWilliam.Wang@arm.com bool 2407753SWilliam.Wang@arm.com operator<(Base const & base) const 2417753SWilliam.Wang@arm.com { 2427753SWilliam.Wang@arm.com return Base::__data < base.__data; 2437753SWilliam.Wang@arm.com } 2447753SWilliam.Wang@arm.com 2457753SWilliam.Wang@arm.com bool 2467753SWilliam.Wang@arm.com operator==(Base const & base) const 2477753SWilliam.Wang@arm.com { 2487950SAli.Saidi@ARM.com return Base::__data == base.__data; 2497950SAli.Saidi@ARM.com } 2507753SWilliam.Wang@arm.com }; 2517950SAli.Saidi@ARM.com} 2527753SWilliam.Wang@arm.com 2537950SAli.Saidi@ARM.com//This macro is a backend for other macros that specialize it slightly. 2547950SAli.Saidi@ARM.com//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and 2557753SWilliam.Wang@arm.com//sticks the class which has the actual union in it, which 2567950SAli.Saidi@ARM.com//BitfieldOperators above inherits from. Putting these classes in a special 2577950SAli.Saidi@ARM.com//namespace ensures that there will be no collisions with other names as long 2587950SAli.Saidi@ARM.com//as the BitUnion names themselves are all distinct and nothing else uses 2597950SAli.Saidi@ARM.com//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself 2607950SAli.Saidi@ARM.com//creates a typedef of the "type" parameter called __DataType. This allows 2617950SAli.Saidi@ARM.com//the type to propagate outside of the macro itself in a controlled way. 2627950SAli.Saidi@ARM.com//Finally, the base storage is defined which BitfieldOperators will refer to 2637950SAli.Saidi@ARM.com//in the operators it defines. This macro is intended to be followed by 2647950SAli.Saidi@ARM.com//bitfield definitions which will end up inside it's union. As explained 2657950SAli.Saidi@ARM.com//above, these is overlayed the __data member in its entirety by each of the 2667950SAli.Saidi@ARM.com//bitfields which are defined in the union, creating shared storage with no 2677950SAli.Saidi@ARM.com//overhead. 2687950SAli.Saidi@ARM.com#define __BitUnion(type, name) \ 2697950SAli.Saidi@ARM.com class BitfieldUnderlyingClasses##name : \ 2707950SAli.Saidi@ARM.com public BitfieldBackend::BitfieldTypes<type> \ 2717950SAli.Saidi@ARM.com { \ 2727950SAli.Saidi@ARM.com public: \ 2737950SAli.Saidi@ARM.com typedef type __DataType; \ 2747950SAli.Saidi@ARM.com union { \ 2757950SAli.Saidi@ARM.com type __data;\ 2767950SAli.Saidi@ARM.com 2777950SAli.Saidi@ARM.com//This closes off the class and union started by the above macro. It is 2788508SAli.Saidi@ARM.com//followed by a typedef which makes "name" refer to a BitfieldOperator 2797950SAli.Saidi@ARM.com//class inheriting from the class and union just defined, which completes 2807950SAli.Saidi@ARM.com//building up the type for the user. 2817950SAli.Saidi@ARM.com#define EndBitUnion(name) \ 2827950SAli.Saidi@ARM.com }; \ 2837950SAli.Saidi@ARM.com }; \ 2847950SAli.Saidi@ARM.com typedef BitfieldBackend::BitUnionOperators< \ 2857950SAli.Saidi@ARM.com BitfieldUnderlyingClasses##name::__DataType, \ 2867753SWilliam.Wang@arm.com BitfieldUnderlyingClasses##name> name; 2877950SAli.Saidi@ARM.com 2887950SAli.Saidi@ARM.com//This sets up a bitfield which has other bitfields nested inside of it. The 2897950SAli.Saidi@ARM.com//__data member functions like the "underlying storage" of the top level 2907950SAli.Saidi@ARM.com//BitUnion. Like everything else, it overlays with the top level storage, so 2917950SAli.Saidi@ARM.com//making it a regular bitfield type makes the entire thing function as a 2927950SAli.Saidi@ARM.com//regular bitfield when referred to by itself. 2937950SAli.Saidi@ARM.com#define __SubBitUnion(fieldType, first, last, name) \ 2947950SAli.Saidi@ARM.com class : public BitfieldBackend::BitfieldTypes<__DataType> \ 2957950SAli.Saidi@ARM.com { \ 2967950SAli.Saidi@ARM.com public: \ 2977950SAli.Saidi@ARM.com union { \ 2987950SAli.Saidi@ARM.com fieldType<first, last> __data; 2997950SAli.Saidi@ARM.com 3007950SAli.Saidi@ARM.com//This closes off the union created above and gives it a name. Unlike the top 3017950SAli.Saidi@ARM.com//level BitUnion, we're interested in creating an object instead of a type. 3027950SAli.Saidi@ARM.com//The operators are defined in the macro itself instead of a class for 3037950SAli.Saidi@ARM.com//technical reasons. If someone determines a way to move them to one, please 3047950SAli.Saidi@ARM.com//do so. 3057950SAli.Saidi@ARM.com#define EndSubBitUnion(name) \ 3067950SAli.Saidi@ARM.com }; \ 3077950SAli.Saidi@ARM.com inline operator __DataType () const \ 3087950SAli.Saidi@ARM.com { return __data; } \ 3097950SAli.Saidi@ARM.com \ 3107950SAli.Saidi@ARM.com inline __DataType operator = (const __DataType & _data) \ 3117950SAli.Saidi@ARM.com { return __data = _data;} \ 3127950SAli.Saidi@ARM.com } name; 3137950SAli.Saidi@ARM.com 3147950SAli.Saidi@ARM.com//Regular bitfields 3157950SAli.Saidi@ARM.com//These define macros for read/write regular bitfield based subbitfields. 3167950SAli.Saidi@ARM.com#define SubBitUnion(name, first, last) \ 3177950SAli.Saidi@ARM.com __SubBitUnion(Bitfield, first, last, name) 3187950SAli.Saidi@ARM.com 3197950SAli.Saidi@ARM.com//Regular bitfields 3207950SAli.Saidi@ARM.com//These define macros for read/write regular bitfield based subbitfields. 3217950SAli.Saidi@ARM.com#define SignedSubBitUnion(name, first, last) \ 3227950SAli.Saidi@ARM.com __SubBitUnion(SignedBitfield, first, last, name) 3237950SAli.Saidi@ARM.com 3247950SAli.Saidi@ARM.com//Use this to define an arbitrary type overlayed with bitfields. 3257950SAli.Saidi@ARM.com#define BitUnion(type, name) __BitUnion(type, name) 3267950SAli.Saidi@ARM.com 3277950SAli.Saidi@ARM.com//Use this to define conveniently sized values overlayed with bitfields. 3287950SAli.Saidi@ARM.com#define BitUnion64(name) __BitUnion(uint64_t, name) 3297950SAli.Saidi@ARM.com#define BitUnion32(name) __BitUnion(uint32_t, name) 3307950SAli.Saidi@ARM.com#define BitUnion16(name) __BitUnion(uint16_t, name) 3317950SAli.Saidi@ARM.com#define BitUnion8(name) __BitUnion(uint8_t, name) 3327950SAli.Saidi@ARM.com 3337950SAli.Saidi@ARM.com#endif // __BASE_BITUNION_HH__ 3347950SAli.Saidi@ARM.com