Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[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  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE.
28  */
29
30 #include "../lttng-endian.h"
31
32 #ifndef CHAR_BIT
33 #define CHAR_BIT 8
34 #endif
35
36 /* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */
37 #define _bt_piecewise_rshift(_v, _shift)                                \
38 ({                                                                      \
39         typeof(_v) ___v = (_v);                                         \
40         typeof(_shift) ___shift = (_shift);                             \
41         unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1);  \
42         unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \
43                                                                         \
44         for (; sb; sb--)                                                \
45                 ___v >>= sizeof(___v) * CHAR_BIT - 1;                   \
46         ___v >>= final;                                                 \
47 })
48
49 #define _bt_piecewise_lshift(_v, _shift)                                \
50 ({                                                                      \
51         typeof(_v) ___v = (_v);                                         \
52         typeof(_shift) ___shift = (_shift);                             \
53         unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1);  \
54         unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \
55                                                                         \
56         for (; sb; sb--)                                                \
57                 ___v <<= sizeof(___v) * CHAR_BIT - 1;                   \
58         ___v <<= final;                                                 \
59 })
60
61 #define _bt_is_signed_type(type)        (((type)(-1)) < 0)
62
63 #define _bt_unsigned_cast(type, v)                                      \
64 ({                                                                      \
65         (sizeof(v) < sizeof(type)) ?                                    \
66                 ((type) (v)) & (~(~(type) 0 << (sizeof(v) * CHAR_BIT))) : \
67                 (type) (v);                                             \
68 })
69
70 /*
71  * bt_bitfield_write - write integer to a bitfield in native endianness
72  *
73  * Save integer to the bitfield, which starts at the "start" bit, has "len"
74  * bits.
75  * The inside of a bitfield is from high bits to low bits.
76  * Uses native endianness.
77  * For unsigned "v", pad MSB with 0 if bitfield is larger than v.
78  * For signed "v", sign-extend v if bitfield is larger than v.
79  *
80  * On little endian, bytes are placed from the less significant to the most
81  * significant. Also, consecutive bitfields are placed from lower bits to higher
82  * bits.
83  *
84  * On big endian, bytes are places from most significant to less significant.
85  * Also, consecutive bitfields are placed from higher to lower bits.
86  */
87
88 #define _bt_bitfield_write_le(_ptr, type, _start, _length, _v)          \
89 do {                                                                    \
90         typeof(_v) __v = (_v);                                          \
91         type *__ptr = (void *) (_ptr);                                  \
92         unsigned long __start = (_start), __length = (_length);         \
93         type mask, cmask;                                               \
94         unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */     \
95         unsigned long start_unit, end_unit, this_unit;                  \
96         unsigned long end, cshift; /* cshift is "complement shift" */   \
97                                                                         \
98         if (!__length)                                                  \
99                 break;                                                  \
100                                                                         \
101         end = __start + __length;                                       \
102         start_unit = __start / ts;                                      \
103         end_unit = (end + (ts - 1)) / ts;                               \
104                                                                         \
105         /* Trim v high bits */                                          \
106         if (__length < sizeof(__v) * CHAR_BIT)                          \
107                 __v &= ~((~(typeof(__v)) 0) << __length);               \
108                                                                         \
109         /* We can now append v with a simple "or", shift it piece-wise */ \
110         this_unit = start_unit;                                         \
111         if (start_unit == end_unit - 1) {                               \
112                 mask = ~((~(type) 0) << (__start % ts));                \
113                 if (end % ts)                                           \
114                         mask |= (~(type) 0) << (end % ts);              \
115                 cmask = (type) __v << (__start % ts);                   \
116                 cmask &= ~mask;                                         \
117                 __ptr[this_unit] &= mask;                               \
118                 __ptr[this_unit] |= cmask;                              \
119                 break;                                                  \
120         }                                                               \
121         if (__start % ts) {                                             \
122                 cshift = __start % ts;                                  \
123                 mask = ~((~(type) 0) << cshift);                        \
124                 cmask = (type) __v << cshift;                           \
125                 cmask &= ~mask;                                         \
126                 __ptr[this_unit] &= mask;                               \
127                 __ptr[this_unit] |= cmask;                              \
128                 __v = _bt_piecewise_rshift(__v, ts - cshift);           \
129                 __start += ts - cshift;                                 \
130                 this_unit++;                                            \
131         }                                                               \
132         for (; this_unit < end_unit - 1; this_unit++) {                 \
133                 __ptr[this_unit] = (type) __v;                          \
134                 __v = _bt_piecewise_rshift(__v, ts);                    \
135                 __start += ts;                                          \
136         }                                                               \
137         if (end % ts) {                                                 \
138                 mask = (~(type) 0) << (end % ts);                       \
139                 cmask = (type) __v;                                     \
140                 cmask &= ~mask;                                         \
141                 __ptr[this_unit] &= mask;                               \
142                 __ptr[this_unit] |= cmask;                              \
143         } else                                                          \
144                 __ptr[this_unit] = (type) __v;                          \
145 } while (0)
146
147 #define _bt_bitfield_write_be(_ptr, type, _start, _length, _v)          \
148 do {                                                                    \
149         typeof(_v) __v = (_v);                                          \
150         type *__ptr = (void *) (_ptr);                                  \
151         unsigned long __start = (_start), __length = (_length);         \
152         type mask, cmask;                                               \
153         unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */     \
154         unsigned long start_unit, end_unit, this_unit;                  \
155         unsigned long end, cshift; /* cshift is "complement shift" */   \
156                                                                         \
157         if (!__length)                                                  \
158                 break;                                                  \
159                                                                         \
160         end = __start + __length;                                       \
161         start_unit = __start / ts;                                      \
162         end_unit = (end + (ts - 1)) / ts;                               \
163                                                                         \
164         /* Trim v high bits */                                          \
165         if (__length < sizeof(__v) * CHAR_BIT)                          \
166                 __v &= ~((~(typeof(__v)) 0) << __length);               \
167                                                                         \
168         /* We can now append v with a simple "or", shift it piece-wise */ \
169         this_unit = end_unit - 1;                                       \
170         if (start_unit == end_unit - 1) {                               \
171                 mask = ~((~(type) 0) << ((ts - (end % ts)) % ts));      \
172                 if (__start % ts)                                       \
173                         mask |= (~((type) 0)) << (ts - (__start % ts)); \
174                 cmask = (type) __v << ((ts - (end % ts)) % ts);         \
175                 cmask &= ~mask;                                         \
176                 __ptr[this_unit] &= mask;                               \
177                 __ptr[this_unit] |= cmask;                              \
178                 break;                                                  \
179         }                                                               \
180         if (end % ts) {                                                 \
181                 cshift = end % ts;                                      \
182                 mask = ~((~(type) 0) << (ts - cshift));                 \
183                 cmask = (type) __v << (ts - cshift);                    \
184                 cmask &= ~mask;                                         \
185                 __ptr[this_unit] &= mask;                               \
186                 __ptr[this_unit] |= cmask;                              \
187                 __v = _bt_piecewise_rshift(__v, cshift);                \
188                 end -= cshift;                                          \
189                 this_unit--;                                            \
190         }                                                               \
191         for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
192                 __ptr[this_unit] = (type) __v;                          \
193                 __v = _bt_piecewise_rshift(__v, ts);                    \
194                 end -= ts;                                              \
195         }                                                               \
196         if (__start % ts) {                                             \
197                 mask = (~(type) 0) << (ts - (__start % ts));            \
198                 cmask = (type) __v;                                     \
199                 cmask &= ~mask;                                         \
200                 __ptr[this_unit] &= mask;                               \
201                 __ptr[this_unit] |= cmask;                              \
202         } else                                                          \
203                 __ptr[this_unit] = (type) __v;                          \
204 } while (0)
205
206 /*
207  * bt_bitfield_write - write integer to a bitfield in native endianness
208  * bt_bitfield_write_le - write integer to a bitfield in little endian
209  * bt_bitfield_write_be - write integer to a bitfield in big endian
210  */
211
212 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
213
214 #define bt_bitfield_write(ptr, type, _start, _length, _v)               \
215         _bt_bitfield_write_le(ptr, type, _start, _length, _v)
216
217 #define bt_bitfield_write_le(ptr, type, _start, _length, _v)            \
218         _bt_bitfield_write_le(ptr, type, _start, _length, _v)
219
220 #define bt_bitfield_write_be(ptr, type, _start, _length, _v)            \
221         _bt_bitfield_write_be(ptr, unsigned char, _start, _length, _v)
222
223 #elif (__BYTE_ORDER == __BIG_ENDIAN)
224
225 #define bt_bitfield_write(ptr, type, _start, _length, _v)               \
226         _bt_bitfield_write_be(ptr, type, _start, _length, _v)
227
228 #define bt_bitfield_write_le(ptr, type, _start, _length, _v)            \
229         _bt_bitfield_write_le(ptr, unsigned char, _start, _length, _v)
230
231 #define bt_bitfield_write_be(ptr, type, _start, _length, _v)            \
232         _bt_bitfield_write_be(ptr, type, _start, _length, _v)
233
234 #else /* (BYTE_ORDER == PDP_ENDIAN) */
235
236 #error "Byte order not supported"
237
238 #endif
239
240 #define _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)        \
241 do {                                                                    \
242         typeof(*(_vptr)) *__vptr = (_vptr);                             \
243         typeof(*__vptr) __v;                                            \
244         type *__ptr = (void *) (_ptr);                                  \
245         unsigned long __start = (_start), __length = (_length);         \
246         type mask, cmask;                                               \
247         unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */     \
248         unsigned long start_unit, end_unit, this_unit;                  \
249         unsigned long end, cshift; /* cshift is "complement shift" */   \
250                                                                         \
251         if (!__length) {                                                \
252                 *__vptr = 0;                                            \
253                 break;                                                  \
254         }                                                               \
255                                                                         \
256         end = __start + __length;                                       \
257         start_unit = __start / ts;                                      \
258         end_unit = (end + (ts - 1)) / ts;                               \
259                                                                         \
260         this_unit = end_unit - 1;                                       \
261         if (_bt_is_signed_type(typeof(__v))                             \
262             && (__ptr[this_unit] & ((type) 1 << ((end % ts ? : ts) - 1)))) \
263                 __v = ~(typeof(__v)) 0;                                 \
264         else                                                            \
265                 __v = 0;                                                \
266         if (start_unit == end_unit - 1) {                               \
267                 cmask = __ptr[this_unit];                               \
268                 cmask >>= (__start % ts);                               \
269                 if ((end - __start) % ts) {                             \
270                         mask = ~((~(type) 0) << (end - __start));       \
271                         cmask &= mask;                                  \
272                 }                                                       \
273                 __v = _bt_piecewise_lshift(__v, end - __start);         \
274                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
275                 *__vptr = __v;                                          \
276                 break;                                                  \
277         }                                                               \
278         if (end % ts) {                                                 \
279                 cshift = end % ts;                                      \
280                 mask = ~((~(type) 0) << cshift);                        \
281                 cmask = __ptr[this_unit];                               \
282                 cmask &= mask;                                          \
283                 __v = _bt_piecewise_lshift(__v, cshift);                \
284                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
285                 end -= cshift;                                          \
286                 this_unit--;                                            \
287         }                                                               \
288         for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
289                 __v = _bt_piecewise_lshift(__v, ts);                    \
290                 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
291                 end -= ts;                                              \
292         }                                                               \
293         if (__start % ts) {                                             \
294                 mask = ~((~(type) 0) << (ts - (__start % ts)));         \
295                 cmask = __ptr[this_unit];                               \
296                 cmask >>= (__start % ts);                               \
297                 cmask &= mask;                                          \
298                 __v = _bt_piecewise_lshift(__v, ts - (__start % ts));   \
299                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
300         } else {                                                        \
301                 __v = _bt_piecewise_lshift(__v, ts);                    \
302                 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
303         }                                                               \
304         *__vptr = __v;                                                  \
305 } while (0)
306
307 #define _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)        \
308 do {                                                                    \
309         typeof(*(_vptr)) *__vptr = (_vptr);                             \
310         typeof(*__vptr) __v;                                            \
311         type *__ptr = (void *) (_ptr);                                  \
312         unsigned long __start = (_start), __length = (_length);         \
313         type mask, cmask;                                               \
314         unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */     \
315         unsigned long start_unit, end_unit, this_unit;                  \
316         unsigned long end, cshift; /* cshift is "complement shift" */   \
317                                                                         \
318         if (!__length) {                                                \
319                 *__vptr = 0;                                            \
320                 break;                                                  \
321         }                                                               \
322                                                                         \
323         end = __start + __length;                                       \
324         start_unit = __start / ts;                                      \
325         end_unit = (end + (ts - 1)) / ts;                               \
326                                                                         \
327         this_unit = start_unit;                                         \
328         if (_bt_is_signed_type(typeof(__v))                             \
329             && (__ptr[this_unit] & ((type) 1 << (ts - (__start % ts) - 1)))) \
330                 __v = ~(typeof(__v)) 0;                                 \
331         else                                                            \
332                 __v = 0;                                                \
333         if (start_unit == end_unit - 1) {                               \
334                 cmask = __ptr[this_unit];                               \
335                 cmask >>= (ts - (end % ts)) % ts;                       \
336                 if ((end - __start) % ts) {                             \
337                         mask = ~((~(type) 0) << (end - __start));       \
338                         cmask &= mask;                                  \
339                 }                                                       \
340                 __v = _bt_piecewise_lshift(__v, end - __start);         \
341                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
342                 *__vptr = __v;                                          \
343                 break;                                                  \
344         }                                                               \
345         if (__start % ts) {                                             \
346                 cshift = __start % ts;                                  \
347                 mask = ~((~(type) 0) << (ts - cshift));                 \
348                 cmask = __ptr[this_unit];                               \
349                 cmask &= mask;                                          \
350                 __v = _bt_piecewise_lshift(__v, ts - cshift);           \
351                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
352                 __start += ts - cshift;                                 \
353                 this_unit++;                                            \
354         }                                                               \
355         for (; this_unit < end_unit - 1; this_unit++) {                 \
356                 __v = _bt_piecewise_lshift(__v, ts);                    \
357                 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
358                 __start += ts;                                          \
359         }                                                               \
360         if (end % ts) {                                                 \
361                 mask = ~((~(type) 0) << (end % ts));                    \
362                 cmask = __ptr[this_unit];                               \
363                 cmask >>= ts - (end % ts);                              \
364                 cmask &= mask;                                          \
365                 __v = _bt_piecewise_lshift(__v, end % ts);              \
366                 __v |= _bt_unsigned_cast(typeof(__v), cmask);           \
367         } else {                                                        \
368                 __v = _bt_piecewise_lshift(__v, ts);                    \
369                 __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\
370         }                                                               \
371         *__vptr = __v;                                                  \
372 } while (0)
373
374 /*
375  * bt_bitfield_read - read integer from a bitfield in native endianness
376  * bt_bitfield_read_le - read integer from a bitfield in little endian
377  * bt_bitfield_read_be - read integer from a bitfield in big endian
378  */
379
380 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
381
382 #define bt_bitfield_read(_ptr, type, _start, _length, _vptr)            \
383         _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)
384
385 #define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)         \
386         _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)
387
388 #define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)         \
389         _bt_bitfield_read_be(_ptr, unsigned char, _start, _length, _vptr)
390
391 #elif (__BYTE_ORDER == __BIG_ENDIAN)
392
393 #define bt_bitfield_read(_ptr, type, _start, _length, _vptr)            \
394         _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)
395
396 #define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr)         \
397         _bt_bitfield_read_le(_ptr, unsigned char, _start, _length, _vptr)
398
399 #define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)         \
400         _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr)
401
402 #else /* (__BYTE_ORDER == __PDP_ENDIAN) */
403
404 #error "Byte order not supported"
405
406 #endif
407
408 #endif /* _BABELTRACE_BITFIELD_H */