Commit | Line | Data |
---|---|---|
9f36eaed MJ |
1 | /* SPDX-License-Identifier: MIT |
2 | * | |
73ca4981 | 3 | * Copyright 2010-2019 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
9115fbdc MD |
4 | */ |
5 | ||
9f36eaed MJ |
6 | #ifndef _BABELTRACE_BITFIELD_H |
7 | #define _BABELTRACE_BITFIELD_H | |
8 | ||
73ca4981 | 9 | #include <linux/types.h> |
5671a661 | 10 | #include <lttng-endian.h> |
9115fbdc MD |
11 | |
12 | #ifndef CHAR_BIT | |
13 | #define CHAR_BIT 8 | |
14 | #endif | |
15 | ||
73ca4981 MD |
16 | /* |
17 | * This header strictly follows the C99 standard, except for use of the | |
18 | * compiler-specific __typeof__. | |
19 | */ | |
20 | ||
21 | /* | |
22 | * This bitfield header requires the compiler representation of signed | |
23 | * integers to be two's complement. | |
24 | */ | |
25 | #if (-1 != ~0) | |
26 | #error "bitfield.h requires the compiler representation of signed integers to be two's complement." | |
27 | #endif | |
28 | ||
29 | #define _bt_is_signed_type(type) ((type) -1 < (type) 0) | |
30 | ||
31 | /* | |
32 | * Produce a build-time error if the condition `cond` is non-zero. | |
33 | * Evaluates as a size_t expression. | |
34 | */ | |
35 | #define _BT_BUILD_ASSERT(cond) \ | |
36 | sizeof(struct { int f:(2 * !!(cond) - 1); }) | |
37 | ||
38 | /* | |
39 | * Cast value `v` to an unsigned integer of the same size as `v`. | |
40 | */ | |
41 | #define _bt_cast_value_to_unsigned(v) \ | |
42 | (sizeof(v) == sizeof(uint8_t) ? (uint8_t) (v) : \ | |
43 | sizeof(v) == sizeof(uint16_t) ? (uint16_t) (v) : \ | |
44 | sizeof(v) == sizeof(uint32_t) ? (uint32_t) (v) : \ | |
45 | sizeof(v) == sizeof(uint64_t) ? (uint64_t) (v) : \ | |
46 | _BT_BUILD_ASSERT(sizeof(v) <= sizeof(uint64_t))) | |
47 | ||
48 | /* | |
49 | * Cast value `v` to an unsigned integer type of the size of type `type` | |
50 | * *without* sign-extension. | |
51 | * | |
52 | * The unsigned cast ensures that we're not shifting a negative value, | |
53 | * which is undefined in C. However, this limits the maximum type size | |
54 | * of `type` to 64-bit. Generate a compile-time error if the size of | |
55 | * `type` is larger than 64-bit. | |
56 | */ | |
57 | #define _bt_cast_value_to_unsigned_type(type, v) \ | |
58 | (sizeof(type) == sizeof(uint8_t) ? \ | |
59 | (uint8_t) _bt_cast_value_to_unsigned(v) : \ | |
60 | sizeof(type) == sizeof(uint16_t) ? \ | |
61 | (uint16_t) _bt_cast_value_to_unsigned(v) : \ | |
62 | sizeof(type) == sizeof(uint32_t) ? \ | |
63 | (uint32_t) _bt_cast_value_to_unsigned(v) : \ | |
64 | sizeof(type) == sizeof(uint64_t) ? \ | |
65 | (uint64_t) _bt_cast_value_to_unsigned(v) : \ | |
66 | _BT_BUILD_ASSERT(sizeof(v) <= sizeof(uint64_t))) | |
67 | ||
68 | /* | |
69 | * _bt_fill_mask evaluates to a "type" integer with all bits set. | |
70 | */ | |
71 | #define _bt_fill_mask(type) ((type) ~(type) 0) | |
72 | ||
73 | /* | |
74 | * Left shift a value `v` of `shift` bits. | |
75 | * | |
76 | * The type of `v` can be signed or unsigned integer. | |
77 | * The value of `shift` must be less than the size of `v` (in bits), | |
78 | * otherwise the behavior is undefined. | |
79 | * Evaluates to the result of the shift operation. | |
80 | * | |
81 | * According to the C99 standard, left shift of a left hand-side signed | |
82 | * type is undefined if it has a negative value or if the result cannot | |
83 | * be represented in the result type. This bitfield header discards the | |
84 | * bits that are left-shifted beyond the result type representation, | |
85 | * which is the behavior of an unsigned type left shift operation. | |
86 | * Therefore, always perform left shift on an unsigned type. | |
87 | * | |
88 | * This macro should not be used if `shift` can be greater or equal than | |
89 | * the bitwidth of `v`. See `_bt_safe_lshift`. | |
90 | */ | |
91 | #define _bt_lshift(v, shift) \ | |
92 | ((__typeof__(v)) (_bt_cast_value_to_unsigned(v) << (shift))) | |
9115fbdc | 93 | |
73ca4981 MD |
94 | /* |
95 | * Generate a mask of type `type` with the `length` least significant bits | |
96 | * cleared, and the most significant bits set. | |
97 | */ | |
98 | #define _bt_make_mask_complement(type, length) \ | |
99 | _bt_lshift(_bt_fill_mask(type), length) | |
9115fbdc | 100 | |
73ca4981 MD |
101 | /* |
102 | * Generate a mask of type `type` with the `length` least significant bits | |
103 | * set, and the most significant bits cleared. | |
104 | */ | |
105 | #define _bt_make_mask(type, length) \ | |
106 | ((type) ~_bt_make_mask_complement(type, length)) | |
107 | ||
108 | /* | |
109 | * Right shift a value `v` of `shift` bits. | |
110 | * | |
111 | * The type of `v` can be signed or unsigned integer. | |
112 | * The value of `shift` must be less than the size of `v` (in bits), | |
113 | * otherwise the behavior is undefined. | |
114 | * Evaluates to the result of the shift operation. | |
115 | * | |
116 | * According to the C99 standard, right shift of a left hand-side signed | |
117 | * type which has a negative value is implementation defined. This | |
118 | * bitfield header relies on the right shift implementation carrying the | |
119 | * sign bit. If the compiler implementation has a different behavior, | |
120 | * emulate carrying the sign bit. | |
121 | * | |
122 | * This macro should not be used if `shift` can be greater or equal than | |
123 | * the bitwidth of `v`. See `_bt_safe_rshift`. | |
124 | */ | |
125 | #if ((-1 >> 1) == -1) | |
126 | #define _bt_rshift(v, shift) ((v) >> (shift)) | |
127 | #else | |
128 | #define _bt_rshift(v, shift) \ | |
129 | ((__typeof__(v)) ((_bt_cast_value_to_unsigned(v) >> (shift)) | \ | |
130 | ((v) < 0 ? _bt_make_mask_complement(__typeof__(v), \ | |
131 | sizeof(v) * CHAR_BIT - (shift)) : 0))) | |
132 | #endif | |
133 | ||
134 | /* | |
135 | * Right shift a signed or unsigned integer with `shift` value being an | |
136 | * arbitrary number of bits. `v` is modified by this macro. The shift | |
137 | * is transformed into a sequence of `_nr_partial_shifts` consecutive | |
138 | * shift operations, each of a number of bits smaller than the bitwidth | |
139 | * of `v`, ending with a shift of the number of left over bits. | |
140 | */ | |
141 | #define _bt_safe_rshift(v, shift) \ | |
142 | do { \ | |
143 | unsigned long _nr_partial_shifts = (shift) / (sizeof(v) * CHAR_BIT - 1); \ | |
144 | unsigned long _leftover_bits = (shift) % (sizeof(v) * CHAR_BIT - 1); \ | |
145 | \ | |
146 | for (; _nr_partial_shifts; _nr_partial_shifts--) \ | |
147 | (v) = _bt_rshift(v, sizeof(v) * CHAR_BIT - 1); \ | |
148 | (v) = _bt_rshift(v, _leftover_bits); \ | |
149 | } while (0) | |
150 | ||
151 | /* | |
152 | * Left shift a signed or unsigned integer with `shift` value being an | |
153 | * arbitrary number of bits. `v` is modified by this macro. The shift | |
154 | * is transformed into a sequence of `_nr_partial_shifts` consecutive | |
155 | * shift operations, each of a number of bits smaller than the bitwidth | |
156 | * of `v`, ending with a shift of the number of left over bits. | |
157 | */ | |
158 | #define _bt_safe_lshift(v, shift) \ | |
159 | do { \ | |
160 | unsigned long _nr_partial_shifts = (shift) / (sizeof(v) * CHAR_BIT - 1); \ | |
161 | unsigned long _leftover_bits = (shift) % (sizeof(v) * CHAR_BIT - 1); \ | |
162 | \ | |
163 | for (; _nr_partial_shifts; _nr_partial_shifts--) \ | |
164 | (v) = _bt_lshift(v, sizeof(v) * CHAR_BIT - 1); \ | |
165 | (v) = _bt_lshift(v, _leftover_bits); \ | |
166 | } while (0) | |
9115fbdc MD |
167 | |
168 | /* | |
169 | * bt_bitfield_write - write integer to a bitfield in native endianness | |
170 | * | |
171 | * Save integer to the bitfield, which starts at the "start" bit, has "len" | |
172 | * bits. | |
173 | * The inside of a bitfield is from high bits to low bits. | |
174 | * Uses native endianness. | |
175 | * For unsigned "v", pad MSB with 0 if bitfield is larger than v. | |
176 | * For signed "v", sign-extend v if bitfield is larger than v. | |
177 | * | |
178 | * On little endian, bytes are placed from the less significant to the most | |
179 | * significant. Also, consecutive bitfields are placed from lower bits to higher | |
180 | * bits. | |
181 | * | |
182 | * On big endian, bytes are places from most significant to less significant. | |
183 | * Also, consecutive bitfields are placed from higher to lower bits. | |
184 | */ | |
185 | ||
186 | #define _bt_bitfield_write_le(_ptr, type, _start, _length, _v) \ | |
187 | do { \ | |
73ca4981 | 188 | __typeof__(_v) __v = (_v); \ |
9115fbdc MD |
189 | type *__ptr = (void *) (_ptr); \ |
190 | unsigned long __start = (_start), __length = (_length); \ | |
191 | type mask, cmask; \ | |
192 | unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ | |
193 | unsigned long start_unit, end_unit, this_unit; \ | |
194 | unsigned long end, cshift; /* cshift is "complement shift" */ \ | |
195 | \ | |
196 | if (!__length) \ | |
197 | break; \ | |
198 | \ | |
199 | end = __start + __length; \ | |
200 | start_unit = __start / ts; \ | |
201 | end_unit = (end + (ts - 1)) / ts; \ | |
202 | \ | |
203 | /* Trim v high bits */ \ | |
204 | if (__length < sizeof(__v) * CHAR_BIT) \ | |
73ca4981 | 205 | __v &= _bt_make_mask(__typeof__(__v), __length); \ |
9115fbdc MD |
206 | \ |
207 | /* We can now append v with a simple "or", shift it piece-wise */ \ | |
208 | this_unit = start_unit; \ | |
209 | if (start_unit == end_unit - 1) { \ | |
73ca4981 | 210 | mask = _bt_make_mask(type, __start % ts); \ |
9115fbdc | 211 | if (end % ts) \ |
73ca4981 MD |
212 | mask |= _bt_make_mask_complement(type, end % ts); \ |
213 | cmask = _bt_lshift((type) (__v), __start % ts); \ | |
9115fbdc MD |
214 | cmask &= ~mask; \ |
215 | __ptr[this_unit] &= mask; \ | |
216 | __ptr[this_unit] |= cmask; \ | |
217 | break; \ | |
218 | } \ | |
219 | if (__start % ts) { \ | |
220 | cshift = __start % ts; \ | |
73ca4981 MD |
221 | mask = _bt_make_mask(type, cshift); \ |
222 | cmask = _bt_lshift((type) (__v), cshift); \ | |
9115fbdc MD |
223 | cmask &= ~mask; \ |
224 | __ptr[this_unit] &= mask; \ | |
225 | __ptr[this_unit] |= cmask; \ | |
73ca4981 | 226 | _bt_safe_rshift(__v, ts - cshift); \ |
9115fbdc MD |
227 | __start += ts - cshift; \ |
228 | this_unit++; \ | |
229 | } \ | |
230 | for (; this_unit < end_unit - 1; this_unit++) { \ | |
231 | __ptr[this_unit] = (type) __v; \ | |
73ca4981 | 232 | _bt_safe_rshift(__v, ts); \ |
9115fbdc MD |
233 | __start += ts; \ |
234 | } \ | |
235 | if (end % ts) { \ | |
73ca4981 | 236 | mask = _bt_make_mask_complement(type, end % ts); \ |
9115fbdc MD |
237 | cmask = (type) __v; \ |
238 | cmask &= ~mask; \ | |
239 | __ptr[this_unit] &= mask; \ | |
240 | __ptr[this_unit] |= cmask; \ | |
241 | } else \ | |
242 | __ptr[this_unit] = (type) __v; \ | |
243 | } while (0) | |
244 | ||
245 | #define _bt_bitfield_write_be(_ptr, type, _start, _length, _v) \ | |
246 | do { \ | |
73ca4981 | 247 | __typeof__(_v) __v = (_v); \ |
9115fbdc MD |
248 | type *__ptr = (void *) (_ptr); \ |
249 | unsigned long __start = (_start), __length = (_length); \ | |
250 | type mask, cmask; \ | |
251 | unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ | |
252 | unsigned long start_unit, end_unit, this_unit; \ | |
253 | unsigned long end, cshift; /* cshift is "complement shift" */ \ | |
254 | \ | |
255 | if (!__length) \ | |
256 | break; \ | |
257 | \ | |
258 | end = __start + __length; \ | |
259 | start_unit = __start / ts; \ | |
260 | end_unit = (end + (ts - 1)) / ts; \ | |
261 | \ | |
262 | /* Trim v high bits */ \ | |
263 | if (__length < sizeof(__v) * CHAR_BIT) \ | |
73ca4981 | 264 | __v &= _bt_make_mask(__typeof__(__v), __length); \ |
9115fbdc MD |
265 | \ |
266 | /* We can now append v with a simple "or", shift it piece-wise */ \ | |
267 | this_unit = end_unit - 1; \ | |
268 | if (start_unit == end_unit - 1) { \ | |
73ca4981 | 269 | mask = _bt_make_mask(type, (ts - (end % ts)) % ts); \ |
9115fbdc | 270 | if (__start % ts) \ |
73ca4981 MD |
271 | mask |= _bt_make_mask_complement(type, ts - (__start % ts)); \ |
272 | cmask = _bt_lshift((type) (__v), (ts - (end % ts)) % ts); \ | |
9115fbdc MD |
273 | cmask &= ~mask; \ |
274 | __ptr[this_unit] &= mask; \ | |
275 | __ptr[this_unit] |= cmask; \ | |
276 | break; \ | |
277 | } \ | |
278 | if (end % ts) { \ | |
279 | cshift = end % ts; \ | |
73ca4981 MD |
280 | mask = _bt_make_mask(type, ts - cshift); \ |
281 | cmask = _bt_lshift((type) (__v), ts - cshift); \ | |
9115fbdc MD |
282 | cmask &= ~mask; \ |
283 | __ptr[this_unit] &= mask; \ | |
284 | __ptr[this_unit] |= cmask; \ | |
73ca4981 | 285 | _bt_safe_rshift(__v, cshift); \ |
9115fbdc MD |
286 | end -= cshift; \ |
287 | this_unit--; \ | |
288 | } \ | |
289 | for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \ | |
290 | __ptr[this_unit] = (type) __v; \ | |
73ca4981 | 291 | _bt_safe_rshift(__v, ts); \ |
9115fbdc MD |
292 | end -= ts; \ |
293 | } \ | |
294 | if (__start % ts) { \ | |
73ca4981 | 295 | mask = _bt_make_mask_complement(type, ts - (__start % ts)); \ |
9115fbdc MD |
296 | cmask = (type) __v; \ |
297 | cmask &= ~mask; \ | |
298 | __ptr[this_unit] &= mask; \ | |
299 | __ptr[this_unit] |= cmask; \ | |
300 | } else \ | |
301 | __ptr[this_unit] = (type) __v; \ | |
302 | } while (0) | |
303 | ||
304 | /* | |
305 | * bt_bitfield_write - write integer to a bitfield in native endianness | |
306 | * bt_bitfield_write_le - write integer to a bitfield in little endian | |
307 | * bt_bitfield_write_be - write integer to a bitfield in big endian | |
308 | */ | |
309 | ||
310 | #if (__BYTE_ORDER == __LITTLE_ENDIAN) | |
311 | ||
312 | #define bt_bitfield_write(ptr, type, _start, _length, _v) \ | |
313 | _bt_bitfield_write_le(ptr, type, _start, _length, _v) | |
314 | ||
315 | #define bt_bitfield_write_le(ptr, type, _start, _length, _v) \ | |
316 | _bt_bitfield_write_le(ptr, type, _start, _length, _v) | |
73ca4981 | 317 | |
9115fbdc MD |
318 | #define bt_bitfield_write_be(ptr, type, _start, _length, _v) \ |
319 | _bt_bitfield_write_be(ptr, unsigned char, _start, _length, _v) | |
320 | ||
321 | #elif (__BYTE_ORDER == __BIG_ENDIAN) | |
322 | ||
323 | #define bt_bitfield_write(ptr, type, _start, _length, _v) \ | |
324 | _bt_bitfield_write_be(ptr, type, _start, _length, _v) | |
325 | ||
326 | #define bt_bitfield_write_le(ptr, type, _start, _length, _v) \ | |
327 | _bt_bitfield_write_le(ptr, unsigned char, _start, _length, _v) | |
73ca4981 | 328 | |
9115fbdc MD |
329 | #define bt_bitfield_write_be(ptr, type, _start, _length, _v) \ |
330 | _bt_bitfield_write_be(ptr, type, _start, _length, _v) | |
331 | ||
73ca4981 | 332 | #else /* (__BYTE_ORDER == __PDP_ENDIAN) */ |
9115fbdc MD |
333 | |
334 | #error "Byte order not supported" | |
335 | ||
336 | #endif | |
337 | ||
338 | #define _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \ | |
339 | do { \ | |
73ca4981 MD |
340 | __typeof__(*(_vptr)) *__vptr = (_vptr); \ |
341 | __typeof__(*__vptr) __v; \ | |
9115fbdc MD |
342 | type *__ptr = (void *) (_ptr); \ |
343 | unsigned long __start = (_start), __length = (_length); \ | |
344 | type mask, cmask; \ | |
345 | unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ | |
346 | unsigned long start_unit, end_unit, this_unit; \ | |
347 | unsigned long end, cshift; /* cshift is "complement shift" */ \ | |
348 | \ | |
349 | if (!__length) { \ | |
350 | *__vptr = 0; \ | |
351 | break; \ | |
352 | } \ | |
353 | \ | |
354 | end = __start + __length; \ | |
355 | start_unit = __start / ts; \ | |
356 | end_unit = (end + (ts - 1)) / ts; \ | |
357 | \ | |
358 | this_unit = end_unit - 1; \ | |
73ca4981 MD |
359 | if (_bt_is_signed_type(__typeof__(__v)) \ |
360 | && (__ptr[this_unit] & _bt_lshift((type) 1, (end % ts ? end % ts : ts) - 1))) \ | |
361 | __v = ~(__typeof__(__v)) 0; \ | |
9115fbdc MD |
362 | else \ |
363 | __v = 0; \ | |
364 | if (start_unit == end_unit - 1) { \ | |
365 | cmask = __ptr[this_unit]; \ | |
73ca4981 | 366 | cmask = _bt_rshift(cmask, __start % ts); \ |
9115fbdc | 367 | if ((end - __start) % ts) { \ |
73ca4981 | 368 | mask = _bt_make_mask(type, end - __start); \ |
9115fbdc MD |
369 | cmask &= mask; \ |
370 | } \ | |
73ca4981 MD |
371 | _bt_safe_lshift(__v, end - __start); \ |
372 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), cmask); \ | |
9115fbdc MD |
373 | *__vptr = __v; \ |
374 | break; \ | |
375 | } \ | |
376 | if (end % ts) { \ | |
377 | cshift = end % ts; \ | |
73ca4981 | 378 | mask = _bt_make_mask(type, cshift); \ |
9115fbdc MD |
379 | cmask = __ptr[this_unit]; \ |
380 | cmask &= mask; \ | |
73ca4981 MD |
381 | _bt_safe_lshift(__v, cshift); \ |
382 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), cmask); \ | |
9115fbdc MD |
383 | end -= cshift; \ |
384 | this_unit--; \ | |
385 | } \ | |
386 | for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \ | |
73ca4981 MD |
387 | _bt_safe_lshift(__v, ts); \ |
388 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), __ptr[this_unit]); \ | |
9115fbdc MD |
389 | end -= ts; \ |
390 | } \ | |
391 | if (__start % ts) { \ | |
73ca4981 | 392 | mask = _bt_make_mask(type, ts - (__start % ts)); \ |
9115fbdc | 393 | cmask = __ptr[this_unit]; \ |
73ca4981 | 394 | cmask = _bt_rshift(cmask, __start % ts); \ |
9115fbdc | 395 | cmask &= mask; \ |
73ca4981 MD |
396 | _bt_safe_lshift(__v, ts - (__start % ts)); \ |
397 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), cmask); \ | |
9115fbdc | 398 | } else { \ |
73ca4981 MD |
399 | _bt_safe_lshift(__v, ts); \ |
400 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), __ptr[this_unit]); \ | |
9115fbdc MD |
401 | } \ |
402 | *__vptr = __v; \ | |
403 | } while (0) | |
404 | ||
405 | #define _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \ | |
406 | do { \ | |
73ca4981 MD |
407 | __typeof__(*(_vptr)) *__vptr = (_vptr); \ |
408 | __typeof__(*__vptr) __v; \ | |
9115fbdc MD |
409 | type *__ptr = (void *) (_ptr); \ |
410 | unsigned long __start = (_start), __length = (_length); \ | |
411 | type mask, cmask; \ | |
412 | unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ | |
413 | unsigned long start_unit, end_unit, this_unit; \ | |
414 | unsigned long end, cshift; /* cshift is "complement shift" */ \ | |
415 | \ | |
416 | if (!__length) { \ | |
417 | *__vptr = 0; \ | |
418 | break; \ | |
419 | } \ | |
420 | \ | |
421 | end = __start + __length; \ | |
422 | start_unit = __start / ts; \ | |
423 | end_unit = (end + (ts - 1)) / ts; \ | |
424 | \ | |
425 | this_unit = start_unit; \ | |
73ca4981 MD |
426 | if (_bt_is_signed_type(__typeof__(__v)) \ |
427 | && (__ptr[this_unit] & _bt_lshift((type) 1, ts - (__start % ts) - 1))) \ | |
428 | __v = ~(__typeof__(__v)) 0; \ | |
9115fbdc MD |
429 | else \ |
430 | __v = 0; \ | |
431 | if (start_unit == end_unit - 1) { \ | |
432 | cmask = __ptr[this_unit]; \ | |
73ca4981 | 433 | cmask = _bt_rshift(cmask, (ts - (end % ts)) % ts); \ |
9115fbdc | 434 | if ((end - __start) % ts) { \ |
73ca4981 | 435 | mask = _bt_make_mask(type, end - __start); \ |
9115fbdc MD |
436 | cmask &= mask; \ |
437 | } \ | |
73ca4981 MD |
438 | _bt_safe_lshift(__v, end - __start); \ |
439 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), cmask); \ | |
9115fbdc MD |
440 | *__vptr = __v; \ |
441 | break; \ | |
442 | } \ | |
443 | if (__start % ts) { \ | |
444 | cshift = __start % ts; \ | |
73ca4981 | 445 | mask = _bt_make_mask(type, ts - cshift); \ |
9115fbdc MD |
446 | cmask = __ptr[this_unit]; \ |
447 | cmask &= mask; \ | |
73ca4981 MD |
448 | _bt_safe_lshift(__v, ts - cshift); \ |
449 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), cmask); \ | |
9115fbdc MD |
450 | __start += ts - cshift; \ |
451 | this_unit++; \ | |
452 | } \ | |
453 | for (; this_unit < end_unit - 1; this_unit++) { \ | |
73ca4981 MD |
454 | _bt_safe_lshift(__v, ts); \ |
455 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), __ptr[this_unit]); \ | |
9115fbdc MD |
456 | __start += ts; \ |
457 | } \ | |
458 | if (end % ts) { \ | |
73ca4981 | 459 | mask = _bt_make_mask(type, end % ts); \ |
9115fbdc | 460 | cmask = __ptr[this_unit]; \ |
73ca4981 | 461 | cmask = _bt_rshift(cmask, ts - (end % ts)); \ |
9115fbdc | 462 | cmask &= mask; \ |
73ca4981 MD |
463 | _bt_safe_lshift(__v, end % ts); \ |
464 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), cmask); \ | |
9115fbdc | 465 | } else { \ |
73ca4981 MD |
466 | _bt_safe_lshift(__v, ts); \ |
467 | __v |= _bt_cast_value_to_unsigned_type(__typeof__(__v), __ptr[this_unit]); \ | |
9115fbdc MD |
468 | } \ |
469 | *__vptr = __v; \ | |
470 | } while (0) | |
471 | ||
472 | /* | |
473 | * bt_bitfield_read - read integer from a bitfield in native endianness | |
474 | * bt_bitfield_read_le - read integer from a bitfield in little endian | |
475 | * bt_bitfield_read_be - read integer from a bitfield in big endian | |
476 | */ | |
477 | ||
478 | #if (__BYTE_ORDER == __LITTLE_ENDIAN) | |
479 | ||
480 | #define bt_bitfield_read(_ptr, type, _start, _length, _vptr) \ | |
481 | _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) | |
482 | ||
483 | #define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \ | |
484 | _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) | |
73ca4981 | 485 | |
9115fbdc MD |
486 | #define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \ |
487 | _bt_bitfield_read_be(_ptr, unsigned char, _start, _length, _vptr) | |
488 | ||
489 | #elif (__BYTE_ORDER == __BIG_ENDIAN) | |
490 | ||
491 | #define bt_bitfield_read(_ptr, type, _start, _length, _vptr) \ | |
492 | _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) | |
493 | ||
494 | #define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \ | |
495 | _bt_bitfield_read_le(_ptr, unsigned char, _start, _length, _vptr) | |
73ca4981 | 496 | |
9115fbdc MD |
497 | #define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \ |
498 | _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) | |
499 | ||
500 | #else /* (__BYTE_ORDER == __PDP_ENDIAN) */ | |
501 | ||
502 | #error "Byte order not supported" | |
503 | ||
504 | #endif | |
505 | ||
506 | #endif /* _BABELTRACE_BITFIELD_H */ |