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 
33 template<typename T, unsigned LSB, unsigned MSB>
34 class Bitfield
35 {
36 private:
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");
40 
44  template<unsigned BITS> struct Best_type
45  {
46  template< typename TY > struct Cmp { enum { value = (BITS <= sizeof(TY)*8) }; };
47  typedef cxx::type_list<
48  unsigned char,
49  unsigned short,
50  unsigned int,
51  unsigned long,
52  unsigned long long
53  > Unsigned_types;
54  typedef typename cxx::find_type<Unsigned_types, Cmp>::type Type;
55  };
56 
57 public:
58  enum
59  {
60  Bits = MSB + 1 - LSB,
61  Lsb = LSB,
62  Msb = MSB,
63  };
64 
65  enum Masks : T
66  {
68  Low_mask = ((T)~0ULL) >> (sizeof(T)*8 - Bits),
71  };
72 
78  typedef typename Best_type<Bits>::Type Bits_type;
79 
86  typedef typename Best_type<Bits + Lsb>::Type Shift_type;
87 
88 private:
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");
94 
95 public:
100  static Bits_type get(Shift_type val)
101  { return (val >> Lsb) & Low_mask; }
102 
110  static T get_unshifted(Shift_type val)
111  { return val & Mask; }
112 
120  static T set_dirty(T dest, Shift_type val)
121  {
122  //assert (!(val & ~Low_mask));
123  return (dest & ~Mask) | (val << Lsb);
124  }
125 
135  static T set_unshifted_dirty(T dest, Shift_type val)
136  {
137  //assert (!(val & ~Mask));
138  return (dest & ~Mask) | val;
139  }
140 
146  static T set(T dest, Bits_type val)
147  { return set_dirty(dest, val & Low_mask); }
148 
155  static T set_unshifted(T dest, Shift_type val)
156  { return set_unshifted_dirty(dest, val & Mask); }
157 
164  static T val_dirty(Shift_type val) { return val << Lsb; }
165 
170  static T val(Bits_type val) { return val_dirty(val & Low_mask); }
171 
177  static T val_unshifted(Shift_type val) { return val & Mask; }
178 
180  template< typename TT >
182  {
183  private:
184  TT v;
185 
186  public:
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); }
190 
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); }
195  };
196 
198  template< typename TT >
199  class Value : public Value_base<TT>
200  {
201  public:
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; }
205  };
206 
208  template< typename TT >
209  class Value_unshifted : public Value_base<TT>
210  {
211  public:
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; }
215  };
216 
218  typedef Value<T&> Ref;
221 
226 };
227 
228 #define CXX_BITFIELD_MEMBER(LSB, MSB, name, data_member) \
229  \
230  \
231  typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
232  \
233  typename name ## _bfm_t::Val name() const { return data_member; } \
234  \
235  typename name ## _bfm_t::Ref name() { return data_member; } \
236 
238 #define CXX_BITFIELD_MEMBER_RO(LSB, MSB, name, data_member) \
239  \
240  \
241  typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
242  \
243  typename name ## _bfm_t::Val name() const { return data_member; } \
244 
246 #define CXX_BITFIELD_MEMBER_UNSHIFTED(LSB, MSB, name, data_member) \
247  \
248  \
249  typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
250  \
251  typename name ## _bfm_t::Val_unshifted name() const { return data_member; } \
252  \
253  typename name ## _bfm_t::Ref_unshifted name() { return data_member; } \
254 
256 #define CXX_BITFIELD_MEMBER_UNSHIFTED_RO(LSB, MSB, name, data_member) \
257  \
258  \
259  typedef cxx::Bitfield<decltype(data_member), LSB, MSB> name ## _bfm_t; \
260  \
261  typename name ## _bfm_t::Val_unshifted name() const { return data_member; } \
262 
263 }
Our C++ library.
Definition: arith:22
Mask value to get Bits bits.
Definition: bitfield:68
static T set_unshifted(T dest, Shift_type val)
Set the bits corresponding to val.
Definition: bitfield:155
static T val_dirty(Shift_type val)
Get the shifted bits for val.
Definition: bitfield:164
static T set_dirty(T dest, Shift_type val)
Set the bits corresponding to val.
Definition: bitfield:120
index of the LSB
Definition: bitfield:61
Value< T const > Val
Value type to access the bits inside a raw bit field.
Definition: bitfield:220
static T val_unshifted(Shift_type val)
Get the shifted bits for val.
Definition: bitfield:177
Best_type< Bits+Lsb >::Type Shift_type
Type to hold at least Bits + Lsb bits.
Definition: bitfield:86
Value_unshifted< T & > Ref_unshifted
Reference type to access the bits inside a raw bit field (in place).
Definition: bitfield:223
static T set_unshifted_dirty(T dest, Shift_type val)
Set the bits corresponding to val.
Definition: bitfield:135
static T set(T dest, Bits_type val)
Set the bits corresponding to val.
Definition: bitfield:146
Value< T & > Ref
Reference type to access the bits inside a raw bit field.
Definition: bitfield:218
Internal helper type.
Definition: bitfield:181
Internal helper type.
Definition: bitfield:209
Mask value to the bits out of a T.
Definition: bitfield:70
static Bits_type get(Shift_type val)
Get the bits out of val.
Definition: bitfield:100
Internal helper type.
Definition: bitfield:199
static T get_unshifted(Shift_type val)
Get the bits in place out of val.
Definition: bitfield:110
Value_unshifted< T const > Val_unshifted
Value type to access the bits inside a raw bit field (in place).
Definition: bitfield:225
static T val(Bits_type val)
Get the shifted bits for val.
Definition: bitfield:170
Definition for a member (part) of a bit field.
Definition: bitfield:34
index of the MSB
Definition: bitfield:62
Best_type< Bits >::Type Bits_type
Type to hold at least Bits bits.
Definition: bitfield:78
Number of bits.
Definition: bitfield:60