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