lttng: tracer control and core structures
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / lttng / lib / bitfield.h
1 #ifndef _BABELTRACE_BITFIELD_H
2 #define _BABELTRACE_BITFIELD_H
3
4 /*
5  * BabelTrace
6  *
7  * Bitfields read/write functions.
8  *
9  * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  */
21
22 #include "../ltt-endian.h"
23
24 #ifndef CHAR_BIT
25 #define CHAR_BIT 8
26 #endif
27
28 /* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */
29 #define _bt_piecewise_rshift(_v, _shift)                                \
30 ({                                                                      \
31         typeof(_v) ___v = (_v);                                         \
32         typeof(_shift) ___shift = (_shift);                             \
33         unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1);  \
34         unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \
35                                                                         \
36         for (; sb; sb--)                                                \
37                 ___v >>= sizeof(___v) * CHAR_BIT - 1;                   \
38         ___v >>= final;                                                 \
39 })
40
41 #define _bt_piecewise_lshift(_v, _shift)                                \
42 ({                                                                      \
43         typeof(_v) ___v = (_v);                                         \
44         typeof(_shift) ___shift = (_shift);                             \
45         unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1);  \
46         unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \
47                                                                         \
48         for (; sb; sb--)                                                \
49                 ___v <<= sizeof(___v) * CHAR_BIT - 1;                   \
50         ___v <<= final;                                                 \
51 })
52
53 #define _bt_is_signed_type(type)        (((type)(-1)) < 0)
54
55 #define _bt_unsigned_cast(type, v)                                      \
56 ({                                                                      \
57         (sizeof(v) < sizeof(type)) ?                                    \
58                 ((type) (v)) & (~(~(type) 0 << (sizeof(v) * CHAR_BIT))) : \
59                 (type) (v);                                             \
60 })
61
62 /*
63  * bt_bitfield_write - write integer to a bitfield in native endianness
64  *
65  * Save integer to the bitfield, which starts at the "start" bit, has "len"
66  * bits.
67  * The inside of a bitfield is from high bits to low bits.
68  * Uses native endianness.
69  * For unsigned "v", pad MSB with 0 if bitfield is larger than v.
70  * For signed "v", sign-extend v if bitfield is larger than v.
71  *
72  * On little endian, bytes are placed from the less significant to the most
73  * significant. Also, consecutive bitfields are placed from lower bits to higher
74  * bits.
75  *
76  * On big endian, bytes are places from most significant to less significant.
77  * Also, consecutive bitfields are placed from higher to lower bits.
78  */
79
80 #define _bt_bitfield_write_le(_ptr, type, _start, _length, _v)          \
81 do {                                                                    \
82         typeof(_v) __v = (_v);                                          \
83         type *__ptr = (void *) (_ptr);                                  \
84         unsigned long __start = (_start), __length = (_length);         \
85         type mask, cmask;                                               \
86         unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */     \
87         unsigned long start_unit, end_unit, this_unit;                  \
88         unsigned long end, cshift; /* cshift is "complement shift" */   \
89                                                                         \
90         if (!__length)                                                  \
91                 break;                                                  \
92                                                                         \
93         end = __start + __length;                                       \
94         start_unit = __start / ts;                                      \
95         end_unit = (end + (ts - 1)) / ts;                               \
96                                                                         \
97         /* Trim v high bits */                                          \
98         if (__length < sizeof(__v) * CHAR_BIT)                          \
99                 __v &= ~((~(typeof(__v)) 0) << __length);               \
100                                                                         \
101         /* We can now append v with a simple "or", shift it piece-wise */ \
102         this_unit = start_unit;                                         \
103         if (start_unit == end_unit - 1) {                               \
104                 mask = ~((~(type) 0) << (__start % ts));                \
105                 if (end % ts)                                           \
106                         mask |= (~(type) 0) << (end % ts);              \
107                 cmask = (type) __v << (__start % ts);                   \
108                 cmask &= ~mask;                                         \
109                 __ptr[this_unit] &= mask;                               \
110                 __ptr[this_unit] |= cmask;                              \
111                 break;                                                  \
112         }                                                               \
113         if (__start % ts) {                                             \
114                 cshift = __start % ts;                                  \
115                 mask = ~((~(type) 0) << cshift);                        \
116                 cmask = (type) __v << cshift;                           \
117                 cmask &= ~mask;                                         \
118                 __ptr[this_unit] &= mask;                               \
119                 __ptr[this_unit] |= cmask;                              \
120                 __v = _bt_piecewise_rshift(__v, ts - cshift);           \
121                 __start += ts - cshift;                                 \
122                 this_unit++;                                            \
123         }                                                               \
124         for (; this_unit < end_unit - 1; this_unit++) {                 \
125                 __ptr[this_unit] = (type) __v;                          \
126                 __v = _bt_piecewise_rshift(__v, ts);                    \
127                 __start += ts;                                          \
128         }                                                               \
129         if (end % ts) {                                                 \
130                 mask = (~(type) 0) << (end % ts);                       \
131                 cmask = (type) __v;                                     \
132                 cmask &= ~mask;                                         \
133                 __ptr[this_unit] &= mask;                               \
134                 __ptr[this_unit] |= cmask;                              \
135         } else                                                          \
136                 __ptr[this_unit] = (type) __v;                          \
137 } while (0)
138
139 #define _bt_bitfield_write_be(_ptr, type, _start, _length, _v)          \
140 do {                                                                    \
141         typeof(_v) __v = (_v);                                          \
142         type *__ptr = (void *) (_ptr);                                  \
143         unsigned long __start = (_start), __length = (_length);         \
144         type mask, cmask;                                               \
145         unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */     \
146         unsigned long start_unit, end_unit, this_unit;                  \
147         unsigned long end, cshift; /* cshift is "complement shift" */   \
148                                                                         \
149         if (!__length)                                                  \
150                 break;                                                  \
151                                                                         \
152         end = __start + __length;                                       \
153         start_unit = __start / ts;                                      \
154         end_unit = (end + (ts - 1)) / ts;                               \
155                                                                         \
156         /* Trim v high bits */                                          \
157         if (__length < sizeof(__v) * CHAR_BIT)                          \
158                 __v &= ~((~(typeof(__v)) 0) << __length);               \
159                                                                         \
160         /* We can now append v with a simple "or", shift it piece-wise */ \
161         this_unit = end_unit - 1;                                       \
162         if (start_unit == end_unit - 1) {                               \
163                 mask = ~((~(type) 0) << ((ts - (end % ts)) % ts));      \
164                 if (__start % ts)                                       \
165                         mask |= (~((type) 0)) << (ts - (__start % ts)); \
166                 cmask = (type) __v << ((ts - (end % ts)) % ts);         \
167                 cmask &= ~mask;                                         \
168                 __ptr[this_unit] &= mask;                               \
169                 __ptr[this_unit] |= cmask;                              \
170                 break;                                                  \
171         }                                                               \
172         if (end % ts) {                                                 \
173                 cshift = end % ts;                                      \
174                 mask = ~((~(type) 0) << (ts - cshift));                 \
175                 cmask = (type) __v << (ts - cshift);                    \
176                 cmask &= ~mask;                                         \
177                 __ptr[this_unit] &= mask;                               \
178                 __ptr[this_unit] |= cmask;                              \
179                 __v = _bt_piecewise_rshift(__v, cshift);                \
180                 end -= cshift;                                          \
181                 this_unit--;                                            \
182         }                                                               \
183         for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
184                 __ptr[this_unit] = (type) __v;                          \
185                 __v = _bt_piecewise_rshift(__v, ts);                    \
186                 end -= ts;                                              \
187         }                                                               \
188         if (__start % ts) {                                             \
189                 mask = (~(type) 0) << (ts - (__start % ts));            \
190                 cmask = (type) __v;                                     \
191                 cmask &= ~mask;                                         \
192                 __ptr[this_unit] &= mask;                               \
193                 __ptr[this_unit] |= cmask;                              \
194         } else                                                          \
195                 __ptr[this_unit] = (type) __v;                          \
196 } while (0)
197
198 /*
199  * bt_bitfield_write - write integer to a bitfield in native endianness
200  * bt_bitfield_write_le - write integer to a bitfield in little endian
201  * bt_bitfield_write_be - write integer to a bitfield in big endian
202  */
203
204 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
205
206 #define bt_bitfield_write(ptr, type, _start, _length, _v)               \
207         _bt_bitfield_write_le(ptr, type, _start, _length, _v)
208
209 #define bt_bitfield_write_le(ptr, type, _start, _length, _v)            \
210         _bt_bitfield_write_le(ptr, type, _start, _length, _v)
211         
212 #define bt_bitfield_write_be(ptr, type, _start, _length, _v)            \
213         _bt_bitfield_write_be(ptr, unsigned char, _start, _length, _v)
214
215 #elif (__BYTE_ORDER == __BIG_ENDIAN)
216
217 #define bt_bitfield_write(ptr, type, _start, _length, _v)               \
218         _bt_bitfield_write_be(ptr, type, _start, _length, _v)
219
220 #define bt_bitfield_write_le(ptr, type, _start, _length, _v)            \
221         _bt_bitfield_write_le(ptr, unsigned char, _start, _length, _v)
222         
223 #define bt_bitfield_write_be(ptr, type, _start, _length, _v)            \
224         _bt_bitfield_write_be(ptr, type, _start, _length, _v)
225
226 #else /* (BYTE_ORDER == PDP_ENDIAN) */
227
228 #error "Byte order not supported"
229
230 #endif
231
232 #define _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)        \
233 do {                                                                    \
234         typeof(*(_vptr)) *__vptr = (_vptr);                             \
235         typeof(*__vptr) __v;                                            \
236         type *__ptr = (void *) (_ptr);                                  \
237         unsigned long __start = (_start), __length = (_length);         \
238         type mask, cmask;                                               \
239         unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */     \
240         unsigned long start_unit, end_unit, this_unit;                  \
241         unsigned long end, cshift; /* cshift is "complement shift" */   \
242                                                                         \
243         if (!__length) {                                                \
244                 *__vptr = 0;                                            \
245                 break;                                                  \
246         }                                                               \
247                                                                         \
248         end = __start + __length;                                       \
249         start_unit = __start / ts;                                      \
250         end_unit = (end + (ts - 1)) / ts;                               \
251                                                                         \
252         this_unit = end_unit - 1;                                       \
253         if (_bt_is_signed_type(typeof(__v))                             \
254             && (__ptr[this_unit] & ((type) 1 << ((end % ts ? : ts) - 1)))) \
255                 __v = ~(typeof(__v)) 0;                                 \
256         else                                                            \
257                 __v = 0;                                                \
258         if (start_unit == end_unit - 1) {                               \
259                 cmask = __ptr[this_unit];                               \
260                 cmask >>= (__start % ts);                               \
261                 if ((end - __start) % ts) {                             \
262                         mask = ~((~(type) 0) << (end - __start));       \
263                         cmask &= mask;                                  \
264                 }                                                       \
265                 __v = _bt_piecewise_lshift(__v, end - __start);         \
266                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
267                 *__vptr = __v;                                          \
268                 break;                                                  \
269         }                                                               \
270         if (end % ts) {                                                 \
271                 cshift = end % ts;                                      \
272                 mask = ~((~(type) 0) << cshift);                        \
273                 cmask = __ptr[this_unit];                               \
274                 cmask &= mask;                                          \
275                 __v = _bt_piecewise_lshift(__v, cshift);                \
276                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
277                 end -= cshift;                                          \
278                 this_unit--;                                            \
279         }                                                               \
280         for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
281                 __v = _bt_piecewise_lshift(__v, ts);                    \
282                 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
283                 end -= ts;                                              \
284         }                                                               \
285         if (__start % ts) {                                             \
286                 mask = ~((~(type) 0) << (ts - (__start % ts)));         \
287                 cmask = __ptr[this_unit];                               \
288                 cmask >>= (__start % ts);                               \
289                 cmask &= mask;                                          \
290                 __v = _bt_piecewise_lshift(__v, ts - (__start % ts));   \
291                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
292         } else {                                                        \
293                 __v = _bt_piecewise_lshift(__v, ts);                    \
294                 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
295         }                                                               \
296         *__vptr = __v;                                                  \
297 } while (0)
298
299 #define _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)        \
300 do {                                                                    \
301         typeof(*(_vptr)) *__vptr = (_vptr);                             \
302         typeof(*__vptr) __v;                                            \
303         type *__ptr = (void *) (_ptr);                                  \
304         unsigned long __start = (_start), __length = (_length);         \
305         type mask, cmask;                                               \
306         unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */     \
307         unsigned long start_unit, end_unit, this_unit;                  \
308         unsigned long end, cshift; /* cshift is "complement shift" */   \
309                                                                         \
310         if (!__length) {                                                \
311                 *__vptr = 0;                                            \
312                 break;                                                  \
313         }                                                               \
314                                                                         \
315         end = __start + __length;                                       \
316         start_unit = __start / ts;                                      \
317         end_unit = (end + (ts - 1)) / ts;                               \
318                                                                         \
319         this_unit = start_unit;                                         \
320         if (_bt_is_signed_type(typeof(__v))                             \
321             && (__ptr[this_unit] & ((type) 1 << (ts - (__start % ts) - 1)))) \
322                 __v = ~(typeof(__v)) 0;                                 \
323         else                                                            \
324                 __v = 0;                                                \
325         if (start_unit == end_unit - 1) {                               \
326                 cmask = __ptr[this_unit];                               \
327                 cmask >>= (ts - (end % ts)) % ts;                       \
328                 if ((end - __start) % ts) {                             \
329                         mask = ~((~(type) 0) << (end - __start));       \
330                         cmask &= mask;                                  \
331                 }                                                       \
332                 __v = _bt_piecewise_lshift(__v, end - __start);         \
333                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
334                 *__vptr = __v;                                          \
335                 break;                                                  \
336         }                                                               \
337         if (__start % ts) {                                             \
338                 cshift = __start % ts;                                  \
339                 mask = ~((~(type) 0) << (ts - cshift));                 \
340                 cmask = __ptr[this_unit];                               \
341                 cmask &= mask;                                          \
342                 __v = _bt_piecewise_lshift(__v, ts - cshift);           \
343                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
344                 __start += ts - cshift;                                 \
345                 this_unit++;                                            \
346         }                                                               \
347         for (; this_unit < end_unit - 1; this_unit++) {                 \
348                 __v = _bt_piecewise_lshift(__v, ts);                    \
349                 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
350                 __start += ts;                                          \
351         }                                                               \
352         if (end % ts) {                                                 \
353                 mask = ~((~(type) 0) << (end % ts));                    \
354                 cmask = __ptr[this_unit];                               \
355                 cmask >>= ts - (end % ts);                              \
356                 cmask &= mask;                                          \
357                 __v = _bt_piecewise_lshift(__v, end % ts);              \
358                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
359         } else {                                                        \
360                 __v = _bt_piecewise_lshift(__v, ts);                    \
361                 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
362         }                                                               \
363         *__vptr = __v;                                                  \
364 } while (0)
365
366 /*
367  * bt_bitfield_read - read integer from a bitfield in native endianness
368  * bt_bitfield_read_le - read integer from a bitfield in little endian
369  * bt_bitfield_read_be - read integer from a bitfield in big endian
370  */
371
372 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
373
374 #define bt_bitfield_read(_ptr, type, _start, _length, _vptr)            \
375         _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)
376
377 #define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)         \
378         _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)
379         
380 #define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)         \
381         _bt_bitfield_read_be(_ptr, unsigned char, _start, _length, _vptr)
382
383 #elif (__BYTE_ORDER == __BIG_ENDIAN)
384
385 #define bt_bitfield_read(_ptr, type, _start, _length, _vptr)            \
386         _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)
387
388 #define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)         \
389         _bt_bitfield_read_le(_ptr, unsigned char, _start, _length, _vptr)
390         
391 #define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)         \
392         _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)
393
394 #else /* (__BYTE_ORDER == __PDP_ENDIAN) */
395
396 #error "Byte order not supported"
397
398 #endif
399
400 #endif /* _BABELTRACE_BITFIELD_H */