3 * (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>,
4 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
10 * As a special exception, you may use this file as part of a free software
11 * library without restriction. Specifically, if other files instantiate
12 * templates or use macros or inline functions from this file, or you compile
13 * this file and link it with other files to produce an executable, this
14 * file does not by itself cause the resulting executable to be covered by
15 * the GNU General Public License. This exception does not however
16 * invalidate any other reasons why the executable file might be covered by
17 * the GNU General Public License.
24 /** \brief Our C++ library. */
27 /** \brief Definition for a member (part) of a bit field.
29 * \param T the underlying type of the bit field.
30 * \param LSB the least significant bit of our bits.
31 * \param MSB the mos significant bit if our bits.
33 template<typename T, unsigned LSB, unsigned MSB>
37 static_assert(MSB >= LSB, "boundary mismatch in bit-field definition");
38 static_assert(MSB < sizeof(T) * 8, "MSB outside of bit-field type");
39 static_assert(LSB < sizeof(T) * 8, "LSB outside of bit-field type");
41 /** \brief Get the best unsigned type for \a bits.
42 * \param BITS number of bits to cover
44 template<unsigned BITS> struct Best_type
46 template< typename TY > struct Cmp { enum { value = (BITS <= sizeof(TY)*8) }; };
47 typedef cxx::type_list<
54 typedef typename cxx::find_type<Unsigned_types, Cmp>::type Type;
60 Bits = MSB + 1 - LSB, ///< Number of bits
61 Lsb = LSB, ///< index of the LSB
62 Msb = MSB, ///< index of the MSB
67 /** Mask value to get #Bits bits. */
68 Low_mask = ((T)~0ULL) >> (sizeof(T)*8 - Bits),
69 /** Mask value to the bits out of a \a T. */
70 Mask = Low_mask << Lsb,
73 /** \brief Type to hold at least #Bits bits.
75 * This type can handle all values that can be stored in this part of the bit
78 typedef typename Best_type<Bits>::Type Bits_type;
80 /** \brief Type to hold at least #Bits + #Lsb bits.
82 * This type can handle all values that can be stored in this part of the bit
83 * field when they are at the target location (#Lsb bits shifted to the
86 typedef typename Best_type<Bits + Lsb>::Type Shift_type;
89 static_assert(sizeof(Bits_type)*8 >= Bits, "error finding the type to store the bits");
90 static_assert(sizeof(Shift_type)*8 >= Bits + Lsb, "error finding the type to keep the shifted bits");
91 static_assert(sizeof(Bits_type) <= sizeof(T), "size mismatch for Bits_type");
92 static_assert(sizeof(Shift_type) <= sizeof(T), "size mismatch for Shift_type");
93 static_assert(sizeof(Bits_type) <= sizeof(Shift_type), "size mismacht for Shift_type and Bits_type");
96 /** \brief Get the bits out of \a val.
97 * \param val the raw value of the whole bit field.
98 * \return the bits form #Lsb to #Msb shifted to the right.
100 static Bits_type get(Shift_type val)
101 { return (val >> Lsb) & Low_mask; }
103 /** \brief Get the bits in place out of \a val.
104 * \param val the raw value of the whole bit field.
105 * \return the bits from #Lsb to #Msb (unshifted).
107 * This means other bits are masked out, however the result is not shifted to
110 static T get_unshifted(Shift_type val)
111 { return val & Mask; }
113 /** \brief Set the bits corresponding to \a val.
114 * \param dest the current value of the whole bit field.
115 * \param val the value to set into the bits.
116 * \return the new value of the whole bit field.
117 * \pre \a val must contain not more than bits than #Bits.
118 * \note This function does not mask \a val to the right number of bits.
120 static T set_dirty(T dest, Shift_type val)
122 //assert (!(val & ~Low_mask));
123 return (dest & ~Mask) | (val << Lsb);
126 /** \brief Set the bits corresponding to \a val.
127 * \param dest the current value of the whole bit field.
128 * \param val the value shifted #Lsb bits to the left that shall be set into
130 * \return the new value of the whole bit field.
131 * \pre \a val must contain not more than bits than #Bits shifted #Lsb bits
133 * \note This function does not mask \a val to the right number of bits.
135 static T set_unshifted_dirty(T dest, Shift_type val)
137 //assert (!(val & ~Mask));
138 return (dest & ~Mask) | val;
141 /** \brief Set the bits corresponding to \a val.
142 * \param dest the current value of the whole bit field.
143 * \param val the value to set into the bits.
144 * \return the new value of the whole bit field.
146 static T set(T dest, Bits_type val)
147 { return set_dirty(dest, val & Low_mask); }
149 /** \brief Set the bits corresponding to \a val.
150 * \param dest the current value of the whole bit field.
151 * \param val the value shifted #Lsb bits to the left that shall be set into
153 * \return the new value of the whole bit field.
155 static T set_unshifted(T dest, Shift_type val)
156 { return set_unshifted_dirty(dest, val & Mask); }
158 /** \brief Get the shifted bits for \a val.
159 * \param val the value to set into the bits.
160 * \return the raw bit field value containing.
161 * \pre \a val must contain not more than bits than #Bits.
162 * \note This function does not mask \a val to the right number of bits.
164 static T val_dirty(Shift_type val) { return val << Lsb; }
166 /** \brief Get the shifted bits for \a val.
167 * \param val the value to set into the bits.
168 * \return the raw bit field value containing.
170 static T val(Bits_type val) { return val_dirty(val & Low_mask); }
172 /** \brief Get the shifted bits for \a val.
173 * \param val the value shifted #Lsb bits to the left that shall be set into
175 * \return the raw bit field value containing.
177 static T val_unshifted(Shift_type val) { return val & Mask; }
179 /** Internal helper type */
180 template< typename TT >
187 Value_base(TT t) : v(t) {}
188 Bits_type get() const { return Bitfield::get(v); }
189 T get_unshifted() const { return Bitfield::get_unshifted(v); }
191 void set(Bits_type val) { v = Bitfield::set(v, val); }
192 void set_dirty(Bits_type val) { v = Bitfield::set_dirty(v, val); }
193 void set_unshifted(Shift_type val) { v = Bitfield::set_unshifted(v, val); }
194 void set_unshifted_dirty(Shift_type val) { v = Bitfield::set_unshifted_dirty(v, val); }
197 /** Internal helper type */
198 template< typename TT >
199 class Value : public Value_base<TT>
202 Value(TT t) : Value_base<TT>(t) {}
203 operator Bits_type () const { return this->get(); }
204 Value &operator = (Bits_type val) { this->set(val); return *this; }
207 /** Internal helper type */
208 template< typename TT >
209 class Value_unshifted : public Value_base<TT>
212 Value_unshifted(TT t) : Value_base<TT>(t) {}
213 operator Shift_type () const { return this->get_unshifted(); }
214 Value_unshifted &operator = (Shift_type val) { this->set_unshifted(val); return *this; }
217 /** Reference type to access the bits inside a raw bit field. */
218 typedef Value<T&> Ref;
219 /** Value type to access the bits inside a raw bit field. */
220 typedef Value<T const> Val;
222 /** Reference type to access the bits inside a raw bit field (in place). */
223 typedef Value_unshifted<T&> Ref_unshifted;
224 /** Value type to access the bits inside a raw bit field (in place). */
225 typedef Value_unshifted<T const> Val_unshifted;
228 #define CXX_BITFIELD_MEMBER(LSB, MSB, name, data_member) \
230 /** \brief Type to access the \a name bits (LSB to MSB) of \a data_member. */ \
231 typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
232 /** \brief Get the \a name bits (LSB to MSB) of \a data_member. */ \
233 typename name ## _bfm_t::Val name() const { return data_member; } \
234 /** \brief Get a reference to the \a name bits (LSB to MSB) of \a data_member. */ \
235 typename name ## _bfm_t::Ref name() { return data_member; } \
238 #define CXX_BITFIELD_MEMBER_RO(LSB, MSB, name, data_member) \
240 /** \brief Type to access the \a name bits (LSB to MSB) of \a data_member. */ \
241 typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
242 /** \brief Get the \a name bits (LSB to MSB) of \a data_member. */ \
243 typename name ## _bfm_t::Val name() const { return data_member; } \
246 #define CXX_BITFIELD_MEMBER_UNSHIFTED(LSB, MSB, name, data_member) \
248 /** \brief Type to access the \a name bits (LSB to MSB) of \a data_member. */ \
249 typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
250 /** \brief Get the \a name bits (LSB to MSB) of \a data_member. */ \
251 typename name ## _bfm_t::Val_unshifted name() const { return data_member; } \
252 /** \brief Get a reference to the \a name bits (LSB to MSB) of \a data_member. */ \
253 typename name ## _bfm_t::Ref_unshifted name() { return data_member; } \
256 #define CXX_BITFIELD_MEMBER_UNSHIFTED_RO(LSB, MSB, name, data_member) \
258 /** \brief Type to access the \a name bits (LSB to MSB) of \a data_member. */ \
259 typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
260 /** \brief Get the \a name bits (LSB to MSB) of \a data_member. */ \
261 typename name ## _bfm_t::Val_unshifted name() const { return data_member; } \