L4Re – L4 Runtime Environment
bitfield
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>,
4  * economic rights: Technische Universität Dresden (Germany)
5  *
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.
9  *
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.
18  */
19 
20 #pragma once
21 
22 #include "type_list"
23 
25 namespace cxx {
26 
34 template<typename T, unsigned LSB, unsigned MSB>
35 class Bitfield
36 {
37 private:
38  static_assert(MSB >= LSB, "boundary mismatch in bit-field definition");
39  static_assert(MSB < sizeof(T) * 8, "MSB outside of bit-field type");
40  static_assert(LSB < sizeof(T) * 8, "LSB outside of bit-field type");
41 
47  template<unsigned BITS> struct Best_type
48  {
49  template< typename TY > struct Cmp { enum { value = (BITS <= sizeof(TY)*8) }; };
50  typedef cxx::type_list<
51  unsigned char,
52  unsigned short,
53  unsigned int,
54  unsigned long,
55  unsigned long long
56  > Unsigned_types;
57  typedef typename cxx::find_type<Unsigned_types, Cmp>::type Type;
58  };
59 
60 public:
61  enum
62  {
63  Bits = MSB + 1 - LSB,
64  Lsb = LSB,
65  Msb = MSB,
66  };
67 
68  enum Masks : T
69  {
71  Low_mask = ((T)~0ULL) >> (sizeof(T)*8 - Bits),
74  };
75 
82  typedef typename Best_type<Bits>::Type Bits_type;
83 
90  typedef typename Best_type<Bits + Lsb>::Type Shift_type;
91 
92 private:
93  static_assert(sizeof(Bits_type)*8 >= Bits, "error finding the type to store the bits");
94  static_assert(sizeof(Shift_type)*8 >= Bits + Lsb, "error finding the type to keep the shifted bits");
95  static_assert(sizeof(Bits_type) <= sizeof(T), "size mismatch for Bits_type");
96  static_assert(sizeof(Shift_type) <= sizeof(T), "size mismatch for Shift_type");
97  static_assert(sizeof(Bits_type) <= sizeof(Shift_type), "size mismacht for Shift_type and Bits_type");
98 
99 public:
108  { return (val >> Lsb) & Low_mask; }
109 
121  { return val & Mask; }
122 
135  static T set_dirty(T dest, Shift_type val)
136  {
137  //assert (!(val & ~Low_mask));
138  return (dest & ~Mask) | (val << Lsb);
139  }
140 
156  {
157  //assert (!(val & ~Mask));
158  return (dest & ~Mask) | val;
159  }
160 
169  static T set(T dest, Bits_type val)
170  { return set_dirty(dest, val & Low_mask); }
171 
181  static T set_unshifted(T dest, Shift_type val)
182  { return set_unshifted_dirty(dest, val & Mask); }
183 
195  static T val_dirty(Shift_type val) { return val << Lsb; }
196 
204  static T val(Bits_type val) { return val_dirty(val & Low_mask); }
205 
214  static T val_unshifted(Shift_type val) { return val & Mask; }
215 
217  template< typename TT >
219  {
220  private:
221  TT v;
222 
223  public:
224  Value_base(TT t) : v(t) {}
225  Bits_type get() const { return Bitfield::get(v); }
226  T get_unshifted() const { return Bitfield::get_unshifted(v); }
227 
228  void set(Bits_type val) { v = Bitfield::set(v, val); }
229  void set_dirty(Bits_type val) { v = Bitfield::set_dirty(v, val); }
230  void set_unshifted(Shift_type val) { v = Bitfield::set_unshifted(v, val); }
231  void set_unshifted_dirty(Shift_type val) { v = Bitfield::set_unshifted_dirty(v, val); }
232  };
233 
235  template< typename TT >
236  class Value : public Value_base<TT>
237  {
238  public:
239  Value(TT t) : Value_base<TT>(t) {}
240  operator Bits_type () const { return this->get(); }
241  Value &operator = (Bits_type val) { this->set(val); return *this; }
242  Value &operator = (Value const &o) { this->set(o.get()); return *this; }
243  };
244 
246  template< typename TT >
247  class Value_unshifted : public Value_base<TT>
248  {
249  public:
250  Value_unshifted(TT t) : Value_base<TT>(t) {}
251  operator Shift_type () const { return this->get_unshifted(); }
252  Value_unshifted &operator = (Shift_type val) { this->set_unshifted(val); return *this; }
253  Value_unshifted &operator = (Value_unshifted const &o)
254  {
255  this->set_unshifted(o.get_unshifted());
256  return *this;
257  }
258  };
259 
261  typedef Value<T&> Ref;
264 
269 };
270 
271 #define CXX_BITFIELD_MEMBER(LSB, MSB, name, data_member) \
272  \
273  \
274  typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
275  \
276  typename name ## _bfm_t::Val name() const { return data_member; } \
277  \
278  typename name ## _bfm_t::Ref name() { return data_member; } \
279 
281 #define CXX_BITFIELD_MEMBER_RO(LSB, MSB, name, data_member) \
282  \
283  \
284  typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
285  \
286  typename name ## _bfm_t::Val name() const { return data_member; } \
287 
289 #define CXX_BITFIELD_MEMBER_UNSHIFTED(LSB, MSB, name, data_member) \
290  \
291  \
292  typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
293  \
294  typename name ## _bfm_t::Val_unshifted name() const { return data_member; } \
295  \
296  typename name ## _bfm_t::Ref_unshifted name() { return data_member; } \
297 
299 #define CXX_BITFIELD_MEMBER_UNSHIFTED_RO(LSB, MSB, name, data_member) \
300  \
301  \
302  typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
303  \
304  typename name ## _bfm_t::Val_unshifted name() const { return data_member; } \
305 
306 }
Internal helper type.
Definition: bitfield:219
Internal helper type.
Definition: bitfield:248
Internal helper type.
Definition: bitfield:237
Definition for a member (part) of a bit field.
Definition: bitfield:36
static T set(T dest, Bits_type val)
Set the bits corresponding to val.
Definition: bitfield:169
Value_unshifted< T const > Val_unshifted
Value type to access the bits inside a raw bit field (in place).
Definition: bitfield:268
static T val(Bits_type val)
Get the shifted bits for val.
Definition: bitfield:204
static Bits_type get(Shift_type val)
Get the bits out of val.
Definition: bitfield:107
Value_unshifted< T & > Ref_unshifted
Reference type to access the bits inside a raw bit field (in place).
Definition: bitfield:266
static T set_dirty(T dest, Shift_type val)
Set the bits corresponding to val.
Definition: bitfield:135
static T val_dirty(Shift_type val)
Get the shifted bits for val.
Definition: bitfield:195
@ Low_mask
Mask value to get Bits bits.
Definition: bitfield:71
@ Mask
Mask value to the bits out of a T.
Definition: bitfield:73
Value< T const > Val
Value type to access the bits inside a raw bit field.
Definition: bitfield:263
static T val_unshifted(Shift_type val)
Get the shifted bits for val.
Definition: bitfield:214
Value< T & > Ref
Reference type to access the bits inside a raw bit field.
Definition: bitfield:261
Best_type< Bits >::Type Bits_type
Type to hold at least Bits bits.
Definition: bitfield:82
static T set_unshifted_dirty(T dest, Shift_type val)
Set the bits corresponding to val.
Definition: bitfield:155
Best_type< Bits+Lsb >::Type Shift_type
Type to hold at least Bits + Lsb bits.
Definition: bitfield:90
static T set_unshifted(T dest, Shift_type val)
Set the bits corresponding to val.
Definition: bitfield:181
static T get_unshifted(Shift_type val)
Get the bits in place out of val.
Definition: bitfield:120
@ Msb
index of the MSB
Definition: bitfield:65
@ Bits
Number of bits.
Definition: bitfield:63
@ Lsb
index of the LSB
Definition: bitfield:64
Our C++ library.
Definition: arith:22