Commit | Line | Data |
---|---|---|
13405819 PP |
1 | # The MIT License (MIT) |
2 | # | |
3 | # Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com> | |
4 | # | |
5 | # Permission is hereby granted, free of charge, to any person obtaining a copy | |
6 | # of this software and associated documentation files (the "Software"), to deal | |
7 | # in the Software without restriction, including without limitation the rights | |
8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
9 | # copies of the Software, and to permit persons to whom the Software is | |
10 | # furnished to do so, subject to the following conditions: | |
11 | # | |
12 | # The above copyright notice and this permission notice shall be included in | |
13 | # all copies or substantial portions of the Software. | |
14 | # | |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
21 | # THE SOFTWARE. | |
22 | ||
e5aa0be3 PP |
23 | _CLOCK_CB = '{return_ctype} (*{cname}_clock_get_value)(void *);' |
24 | ||
25 | ||
26 | _PLATFORM_CALLBACKS_BEGIN = '''/* barectf platform callbacks */ | |
27 | struct {prefix}platform_callbacks {{ | |
28 | /* clock callbacks */''' | |
29 | ||
30 | ||
31 | _PLATFORM_CALLBACKS_END = ''' | |
32 | /* is back-end full? */ | |
33 | int (*is_backend_full)(void *); | |
34 | ||
35 | /* open packet */ | |
36 | void (*open_packet)(void *); | |
37 | ||
38 | /* close packet */ | |
39 | void (*close_packet)(void *); | |
40 | };''' | |
41 | ||
42 | ||
43 | _CTX_PARENT = '''/* common barectf context */ | |
44 | struct {prefix}ctx {{ | |
45 | /* platform callbacks */ | |
46 | struct {prefix}platform_callbacks cbs; | |
47 | ||
48 | /* platform data (passed to callbacks) */ | |
49 | void *data; | |
50 | ||
67bd189f | 51 | /* output buffer (will contain a CTF binary packet) */ |
e5aa0be3 | 52 | uint8_t *buf; |
67bd189f | 53 | |
e5aa0be3 | 54 | /* packet size in bits */ |
8079a626 | 55 | uint32_t packet_size; |
67bd189f | 56 | |
e5aa0be3 PP |
57 | /* content size in bits */ |
58 | uint32_t content_size; | |
59 | ||
60 | /* current position from beginning of packet in bits */ | |
67bd189f PP |
61 | uint32_t at; |
62 | ||
e5aa0be3 PP |
63 | /* packet header + context size (content offset) */ |
64 | uint32_t off_content; | |
65 | ||
66 | /* events discarded */ | |
67 | uint32_t events_discarded; | |
68 | ||
69 | /* current packet is opened */ | |
70 | int packet_is_open; | |
71 | }};''' | |
72 | ||
73 | ||
74 | _CTX_BEGIN = '''/* context for stream "{sname}" */ | |
75 | struct {prefix}{sname}_ctx {{ | |
76 | /* parent */ | |
77 | struct {prefix}ctx parent; | |
78 | ||
79 | /* config-specific members follow */''' | |
80 | ||
81 | ||
82 | _CTX_END = '};' | |
83 | ||
84 | ||
85 | _FUNC_INIT_PROTO = '''/* initialize context */ | |
86 | void {prefix}init( | |
87 | void *ctx, | |
88 | uint8_t *buf, | |
89 | uint32_t buf_size, | |
90 | struct {prefix}platform_callbacks cbs, | |
91 | void *data | |
92 | )''' | |
93 | ||
94 | ||
95 | _FUNC_INIT_BODY = '''{{ | |
96 | struct {prefix}ctx *{prefix}ctx = ctx; | |
97 | {prefix}ctx->cbs = cbs; | |
98 | {prefix}ctx->data = data; | |
99 | {prefix}ctx->buf = buf; | |
100 | {prefix}ctx->packet_size = _BYTES_TO_BITS(buf_size); | |
101 | {prefix}ctx->at = 0; | |
102 | {prefix}ctx->events_discarded = 0; | |
103 | {prefix}ctx->packet_is_open = 0; | |
104 | }}''' | |
105 | ||
106 | ||
107 | _FUNC_OPEN_PROTO_BEGIN = '''/* open packet for stream "{sname}" */ | |
108 | void {prefix}{sname}_open_packet( | |
109 | struct {prefix}{sname}_ctx *ctx''' | |
110 | ||
111 | ||
112 | _FUNC_OPEN_PROTO_END = ')' | |
113 | ||
114 | ||
115 | _FUNC_OPEN_BODY_BEGIN = '{' | |
116 | ||
117 | ||
118 | _FUNC_OPEN_BODY_END = ''' | |
119 | ctx->parent.off_content = ctx->parent.at; | |
120 | ||
121 | /* mark current packet as open */ | |
122 | ctx->parent.packet_is_open = 1; | |
123 | }''' | |
124 | ||
125 | ||
126 | _FUNC_CLOSE_PROTO = '''/* close packet for stream "{sname}" */ | |
127 | void {prefix}{sname}_close_packet(struct {prefix}{sname}_ctx *ctx)''' | |
128 | ||
129 | ||
130 | _FUNC_CLOSE_BODY_BEGIN = '{' | |
131 | ||
132 | ||
133 | _FUNC_CLOSE_BODY_END = ''' | |
134 | /* go back to end of packet */ | |
135 | ctx->parent.at = ctx->parent.packet_size; | |
136 | ||
137 | /* mark packet as closed */ | |
138 | ctx->parent.packet_is_open = 0; | |
139 | }''' | |
140 | ||
141 | ||
142 | _FUNC_TRACE_PROTO_BEGIN = '''/* trace (stream "{sname}", event "{evname}") */ | |
143 | void {prefix}{sname}_trace_{evname}( | |
144 | struct {prefix}{sname}_ctx *ctx''' | |
145 | ||
146 | ||
147 | _FUNC_TRACE_PROTO_END = ')' | |
148 | ||
149 | ||
150 | _FUNC_TRACE_BODY = '''{{ | |
151 | uint32_t ev_size; | |
152 | ||
153 | /* get event size */ | |
154 | ev_size = _get_event_size_{sname}_{evname}((void *) ctx{params}); | |
155 | ||
156 | /* do we have enough space to serialize? */ | |
157 | if (!_reserve_event_space((void *) ctx, ev_size)) {{ | |
158 | /* no: forget this */ | |
159 | return; | |
160 | }} | |
161 | ||
162 | /* serialize event */ | |
163 | _serialize_event_{sname}_{evname}((void *) ctx{params}); | |
164 | ||
165 | /* commit event */ | |
166 | _commit_event((void *) ctx); | |
167 | }}''' | |
168 | ||
169 | ||
170 | _FUNC_GET_EVENT_SIZE_PROTO_BEGIN = '''static uint32_t _get_event_size_{sname}_{evname}( | |
171 | struct {prefix}ctx *ctx''' | |
172 | ||
173 | ||
174 | _FUNC_GET_EVENT_SIZE_PROTO_END = ')' | |
175 | ||
176 | ||
177 | _FUNC_GET_EVENT_SIZE_BODY_BEGIN = '''{ | |
178 | uint32_t at = ctx->at;''' | |
179 | ||
180 | ||
181 | _FUNC_GET_EVENT_SIZE_BODY_END = ''' return at - ctx->at; | |
182 | }''' | |
183 | ||
184 | ||
185 | _FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_BEGIN = '''static void _serialize_stream_event_header_{sname}( | |
186 | struct {prefix}ctx *ctx, | |
187 | uint32_t event_id''' | |
df892ed5 | 188 | |
df892ed5 | 189 | |
e5aa0be3 | 190 | _FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_END = ')' |
67bd189f | 191 | |
df892ed5 | 192 | |
e5aa0be3 | 193 | _FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_BEGIN = '{' |
df892ed5 | 194 | |
df892ed5 | 195 | |
e5aa0be3 | 196 | _FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_END = '}' |
df892ed5 | 197 | |
6b9ba5f3 | 198 | |
e5aa0be3 PP |
199 | _FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_BEGIN = '''static void _serialize_stream_event_context_{sname}( |
200 | struct {prefix}ctx *ctx''' | |
201 | ||
202 | ||
203 | _FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_END = ')' | |
204 | ||
205 | ||
206 | _FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_BEGIN = '{' | |
207 | ||
208 | ||
209 | _FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_END = '}' | |
210 | ||
211 | ||
212 | _FUNC_SERIALIZE_EVENT_PROTO_BEGIN = '''static void _serialize_event_{sname}_{evname}( | |
213 | struct {prefix}ctx *ctx''' | |
214 | ||
215 | ||
216 | _FUNC_SERIALIZE_EVENT_PROTO_END = ')' | |
217 | ||
218 | ||
219 | _FUNC_SERIALIZE_EVENT_BODY_BEGIN = '{' | |
220 | ||
221 | ||
222 | _FUNC_SERIALIZE_EVENT_BODY_END = '}' | |
223 | ||
224 | ||
225 | _HEADER_BEGIN = '''#ifndef _{ucprefix}H | |
226 | #define _{ucprefix}H | |
227 | ||
228 | /* | |
229 | * The following C code was generated by barectf {version} | |
230 | * on {date}. | |
231 | * | |
232 | * For more details, see <https://github.com/efficios/barectf>. | |
233 | */ | |
67bd189f PP |
234 | |
235 | #include <stdint.h> | |
236 | ||
e5aa0be3 | 237 | #include "{bitfield_header_filename}" |
445687b2 | 238 | |
e5aa0be3 | 239 | struct {prefix}ctx; |
67bd189f | 240 | |
e5aa0be3 PP |
241 | uint32_t {prefix}packet_size(void *ctx); |
242 | int {prefix}packet_is_full(void *ctx); | |
243 | int {prefix}packet_is_empty(void *ctx); | |
244 | uint32_t {prefix}packet_events_discarded(void *ctx); | |
245 | uint8_t *{prefix}packet_buf(void *ctx); | |
246 | void {prefix}packet_set_buf(void *ctx, uint8_t *buf, uint32_t buf_size); | |
247 | uint32_t {prefix}packet_buf_size(void *ctx); | |
248 | int {prefix}packet_is_open(void *ctx);''' | |
67bd189f | 249 | |
67bd189f | 250 | |
e5aa0be3 | 251 | _HEADER_END = '#endif /* _{ucprefix}H */' |
67bd189f | 252 | |
67bd189f | 253 | |
e5aa0be3 PP |
254 | _C_SRC = '''/* |
255 | * The following C code was generated by barectf {version} | |
256 | * on {date}. | |
257 | * | |
258 | * For more details, see <https://github.com/efficios/barectf>. | |
259 | */ | |
445687b2 | 260 | |
e5aa0be3 | 261 | #include <stdint.h> |
8079a626 | 262 | #include <string.h> |
e5aa0be3 PP |
263 | #include <assert.h> |
264 | ||
265 | #include "{header_filename}" | |
266 | ||
1645a650 PP |
267 | #define _ALIGN(_at, _align) \\ |
268 | do {{ \\ | |
e5aa0be3 PP |
269 | (_at) = ((_at) + ((_align) - 1)) & -(_align); \\ |
270 | }} while (0) | |
8079a626 | 271 | |
e5aa0be3 PP |
272 | #define _BITS_TO_BYTES(_x) ((_x) >> 3) |
273 | #define _BYTES_TO_BITS(_x) ((_x) << 3) | |
445687b2 | 274 | |
1405552b PP |
275 | union f2u {{ |
276 | float f; | |
277 | uint32_t u; | |
278 | }}; | |
279 | ||
280 | union d2u {{ | |
281 | double f; | |
282 | uint64_t u; | |
283 | }}; | |
284 | ||
e5aa0be3 PP |
285 | uint32_t {prefix}packet_size(void *ctx) |
286 | {{ | |
287 | return ((struct {prefix}ctx *) ctx)->packet_size; | |
288 | }} | |
9a0782f7 | 289 | |
e5aa0be3 PP |
290 | int {prefix}packet_is_full(void *ctx) |
291 | {{ | |
292 | struct {prefix}ctx *cctx = ctx; | |
293 | ||
294 | return cctx->at == cctx->packet_size; | |
295 | }} | |
296 | ||
297 | int {prefix}packet_is_empty(void *ctx) | |
298 | {{ | |
299 | struct {prefix}ctx *cctx = ctx; | |
300 | ||
301 | return cctx->at <= cctx->off_content; | |
302 | }} | |
303 | ||
304 | uint32_t {prefix}packet_events_discarded(void *ctx) | |
305 | {{ | |
306 | return ((struct {prefix}ctx *) ctx)->events_discarded; | |
307 | }} | |
308 | ||
309 | uint8_t *{prefix}packet_buf(void *ctx) | |
310 | {{ | |
311 | return ((struct {prefix}ctx *) ctx)->buf; | |
312 | }} | |
313 | ||
314 | uint32_t {prefix}packet_buf_size(void *ctx) | |
315 | {{ | |
316 | return _BITS_TO_BYTES(((struct {prefix}ctx *) ctx)->packet_size); | |
317 | }} | |
318 | ||
319 | void {prefix}packet_set_buf(void *ctx, uint8_t *buf, uint32_t buf_size) | |
320 | {{ | |
321 | struct {prefix}ctx *{prefix}ctx = ctx; | |
322 | ||
323 | {prefix}ctx->buf = buf; | |
324 | {prefix}ctx->packet_size = _BYTES_TO_BITS(buf_size); | |
325 | }} | |
326 | ||
327 | int {prefix}packet_is_open(void *ctx) | |
328 | {{ | |
329 | return ((struct {prefix}ctx *) ctx)->packet_is_open; | |
330 | }} | |
331 | ||
332 | static | |
ca275dc0 | 333 | void _write_cstring(struct {prefix}ctx *ctx, const char *src) |
e5aa0be3 PP |
334 | {{ |
335 | uint32_t sz = strlen(src) + 1; | |
336 | ||
337 | memcpy(&ctx->buf[_BITS_TO_BYTES(ctx->at)], src, sz); | |
338 | ctx->at += _BYTES_TO_BITS(sz); | |
339 | }} | |
340 | ||
341 | static inline | |
342 | int _packet_is_full(struct {prefix}ctx *ctx) | |
343 | {{ | |
344 | return {prefix}packet_is_full(ctx); | |
345 | }} | |
346 | ||
347 | static | |
348 | int _reserve_event_space(struct {prefix}ctx *ctx, uint32_t ev_size) | |
349 | {{ | |
350 | /* event _cannot_ fit? */ | |
351 | if (ev_size > (ctx->packet_size - ctx->off_content)) {{ | |
352 | ctx->events_discarded++; | |
353 | ||
354 | return 0; | |
355 | }} | |
356 | ||
357 | /* packet is full? */ | |
358 | if ({prefix}packet_is_full(ctx)) {{ | |
359 | /* yes: is back-end full? */ | |
360 | if (ctx->cbs.is_backend_full(ctx->data)) {{ | |
361 | /* yes: discard event */ | |
362 | ctx->events_discarded++; | |
363 | ||
364 | return 0; | |
365 | }} | |
366 | ||
367 | /* back-end is not full: open new packet */ | |
368 | ctx->cbs.open_packet(ctx->data); | |
369 | }} | |
370 | ||
371 | /* event fits the current packet? */ | |
372 | if (ev_size > (ctx->packet_size - ctx->at)) {{ | |
373 | /* no: close packet now */ | |
374 | ctx->cbs.close_packet(ctx->data); | |
375 | ||
376 | /* is back-end full? */ | |
377 | if (ctx->cbs.is_backend_full(ctx->data)) {{ | |
378 | /* yes: discard event */ | |
379 | ctx->events_discarded++; | |
380 | ||
381 | return 0; | |
382 | }} | |
383 | ||
384 | /* back-end is not full: open new packet */ | |
385 | ctx->cbs.open_packet(ctx->data); | |
386 | assert(ev_size <= (ctx->packet_size - ctx->at)); | |
387 | }} | |
388 | ||
389 | return 1; | |
390 | }} | |
391 | ||
392 | static | |
393 | void _commit_event(struct {prefix}ctx *ctx) | |
394 | {{ | |
395 | /* is packet full? */ | |
396 | if ({prefix}packet_is_full(ctx)) {{ | |
397 | /* yes: close it now */ | |
398 | ctx->cbs.close_packet(ctx->data); | |
399 | }} | |
400 | }}''' | |
401 | ||
402 | ||
403 | _BITFIELD = '''#ifndef _$PREFIX$BITFIELD_H | |
404 | #define _$PREFIX$BITFIELD_H | |
9a0782f7 PP |
405 | |
406 | /* | |
407 | * BabelTrace | |
408 | * | |
409 | * Bitfields read/write functions. | |
410 | * | |
411 | * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
412 | * | |
413 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
414 | * of this software and associated documentation files (the "Software"), to deal | |
415 | * in the Software without restriction, including without limitation the rights | |
416 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
417 | * copies of the Software, and to permit persons to whom the Software is | |
418 | * furnished to do so, subject to the following conditions: | |
419 | * | |
420 | * The above copyright notice and this permission notice shall be included in | |
421 | * all copies or substantial portions of the Software. | |
422 | * | |
423 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
424 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
425 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
426 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
427 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
428 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
429 | * SOFTWARE. | |
430 | */ | |
431 | ||
432 | #include <stdint.h> /* C99 5.2.4.2 Numerical limits */ | |
8079a626 | 433 | #include <limits.h> |
9a0782f7 | 434 | |
e5aa0be3 | 435 | #define $PREFIX$BYTE_ORDER $ENDIAN_DEF$ |
9a0782f7 PP |
436 | |
437 | /* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */ | |
e5aa0be3 | 438 | #define _$prefix$bt_piecewise_rshift(_v, _shift) \\ |
c19e7f1f | 439 | __extension__ ({ \\ |
e5aa0be3 PP |
440 | __typeof__(_v) ___v = (_v); \\ |
441 | __typeof__(_shift) ___shift = (_shift); \\ | |
9a0782f7 PP |
442 | unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \\ |
443 | unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \\ | |
444 | \\ | |
445 | for (; sb; sb--) \\ | |
446 | ___v >>= sizeof(___v) * CHAR_BIT - 1; \\ | |
447 | ___v >>= final; \\ | |
448 | }) | |
449 | ||
e5aa0be3 | 450 | #define _$prefix$bt_piecewise_lshift(_v, _shift) \\ |
c19e7f1f | 451 | __extension__ ({ \\ |
e5aa0be3 PP |
452 | __typeof__(_v) ___v = (_v); \\ |
453 | __typeof__(_shift) ___shift = (_shift); \\ | |
9a0782f7 PP |
454 | unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \\ |
455 | unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \\ | |
456 | \\ | |
457 | for (; sb; sb--) \\ | |
458 | ___v <<= sizeof(___v) * CHAR_BIT - 1; \\ | |
459 | ___v <<= final; \\ | |
460 | }) | |
461 | ||
e5aa0be3 | 462 | #define _$prefix$bt_is_signed_type(type) ((type) -1 < (type) 0) |
9a0782f7 | 463 | |
e5aa0be3 | 464 | #define _$prefix$bt_unsigned_cast(type, v) \\ |
c19e7f1f | 465 | __extension__ ({ \\ |
9a0782f7 PP |
466 | (sizeof(v) < sizeof(type)) ? \\ |
467 | ((type) (v)) & (~(~(type) 0 << (sizeof(v) * CHAR_BIT))) : \\ | |
468 | (type) (v); \\ | |
469 | }) | |
470 | ||
471 | /* | |
e5aa0be3 | 472 | * $prefix$bt_bitfield_write - write integer to a bitfield in native endianness |
9a0782f7 PP |
473 | * |
474 | * Save integer to the bitfield, which starts at the "start" bit, has "len" | |
475 | * bits. | |
476 | * The inside of a bitfield is from high bits to low bits. | |
477 | * Uses native endianness. | |
478 | * For unsigned "v", pad MSB with 0 if bitfield is larger than v. | |
479 | * For signed "v", sign-extend v if bitfield is larger than v. | |
480 | * | |
481 | * On little endian, bytes are placed from the less significant to the most | |
482 | * significant. Also, consecutive bitfields are placed from lower bits to higher | |
483 | * bits. | |
484 | * | |
485 | * On big endian, bytes are places from most significant to less significant. | |
486 | * Also, consecutive bitfields are placed from higher to lower bits. | |
487 | */ | |
488 | ||
e5aa0be3 | 489 | #define _$prefix$bt_bitfield_write_le(_ptr, type, _start, _length, _v) \\ |
9a0782f7 | 490 | do { \\ |
e5aa0be3 | 491 | __typeof__(_v) __v = (_v); \\ |
9a0782f7 PP |
492 | type *__ptr = (void *) (_ptr); \\ |
493 | unsigned long __start = (_start), __length = (_length); \\ | |
494 | type mask, cmask; \\ | |
495 | unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \\ | |
496 | unsigned long start_unit, end_unit, this_unit; \\ | |
497 | unsigned long end, cshift; /* cshift is "complement shift" */ \\ | |
498 | \\ | |
499 | if (!__length) \\ | |
500 | break; \\ | |
501 | \\ | |
502 | end = __start + __length; \\ | |
503 | start_unit = __start / ts; \\ | |
504 | end_unit = (end + (ts - 1)) / ts; \\ | |
505 | \\ | |
506 | /* Trim v high bits */ \\ | |
507 | if (__length < sizeof(__v) * CHAR_BIT) \\ | |
e5aa0be3 | 508 | __v &= ~((~(__typeof__(__v)) 0) << __length); \\ |
9a0782f7 PP |
509 | \\ |
510 | /* We can now append v with a simple "or", shift it piece-wise */ \\ | |
511 | this_unit = start_unit; \\ | |
512 | if (start_unit == end_unit - 1) { \\ | |
513 | mask = ~((~(type) 0) << (__start % ts)); \\ | |
514 | if (end % ts) \\ | |
515 | mask |= (~(type) 0) << (end % ts); \\ | |
516 | cmask = (type) __v << (__start % ts); \\ | |
517 | cmask &= ~mask; \\ | |
518 | __ptr[this_unit] &= mask; \\ | |
519 | __ptr[this_unit] |= cmask; \\ | |
520 | break; \\ | |
521 | } \\ | |
522 | if (__start % ts) { \\ | |
523 | cshift = __start % ts; \\ | |
524 | mask = ~((~(type) 0) << cshift); \\ | |
525 | cmask = (type) __v << cshift; \\ | |
526 | cmask &= ~mask; \\ | |
527 | __ptr[this_unit] &= mask; \\ | |
528 | __ptr[this_unit] |= cmask; \\ | |
e5aa0be3 | 529 | __v = _$prefix$bt_piecewise_rshift(__v, ts - cshift); \\ |
9a0782f7 PP |
530 | __start += ts - cshift; \\ |
531 | this_unit++; \\ | |
532 | } \\ | |
533 | for (; this_unit < end_unit - 1; this_unit++) { \\ | |
534 | __ptr[this_unit] = (type) __v; \\ | |
e5aa0be3 | 535 | __v = _$prefix$bt_piecewise_rshift(__v, ts); \\ |
9a0782f7 PP |
536 | __start += ts; \\ |
537 | } \\ | |
538 | if (end % ts) { \\ | |
539 | mask = (~(type) 0) << (end % ts); \\ | |
540 | cmask = (type) __v; \\ | |
541 | cmask &= ~mask; \\ | |
542 | __ptr[this_unit] &= mask; \\ | |
543 | __ptr[this_unit] |= cmask; \\ | |
544 | } else \\ | |
545 | __ptr[this_unit] = (type) __v; \\ | |
546 | } while (0) | |
547 | ||
e5aa0be3 | 548 | #define _$prefix$bt_bitfield_write_be(_ptr, type, _start, _length, _v) \\ |
9a0782f7 | 549 | do { \\ |
e5aa0be3 | 550 | __typeof__(_v) __v = (_v); \\ |
9a0782f7 PP |
551 | type *__ptr = (void *) (_ptr); \\ |
552 | unsigned long __start = (_start), __length = (_length); \\ | |
553 | type mask, cmask; \\ | |
554 | unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \\ | |
555 | unsigned long start_unit, end_unit, this_unit; \\ | |
556 | unsigned long end, cshift; /* cshift is "complement shift" */ \\ | |
557 | \\ | |
558 | if (!__length) \\ | |
559 | break; \\ | |
560 | \\ | |
561 | end = __start + __length; \\ | |
562 | start_unit = __start / ts; \\ | |
563 | end_unit = (end + (ts - 1)) / ts; \\ | |
564 | \\ | |
565 | /* Trim v high bits */ \\ | |
566 | if (__length < sizeof(__v) * CHAR_BIT) \\ | |
e5aa0be3 | 567 | __v &= ~((~(__typeof__(__v)) 0) << __length); \\ |
9a0782f7 PP |
568 | \\ |
569 | /* We can now append v with a simple "or", shift it piece-wise */ \\ | |
570 | this_unit = end_unit - 1; \\ | |
571 | if (start_unit == end_unit - 1) { \\ | |
572 | mask = ~((~(type) 0) << ((ts - (end % ts)) % ts)); \\ | |
573 | if (__start % ts) \\ | |
574 | mask |= (~((type) 0)) << (ts - (__start % ts)); \\ | |
575 | cmask = (type) __v << ((ts - (end % ts)) % ts); \\ | |
576 | cmask &= ~mask; \\ | |
577 | __ptr[this_unit] &= mask; \\ | |
578 | __ptr[this_unit] |= cmask; \\ | |
579 | break; \\ | |
580 | } \\ | |
581 | if (end % ts) { \\ | |
582 | cshift = end % ts; \\ | |
583 | mask = ~((~(type) 0) << (ts - cshift)); \\ | |
584 | cmask = (type) __v << (ts - cshift); \\ | |
585 | cmask &= ~mask; \\ | |
586 | __ptr[this_unit] &= mask; \\ | |
587 | __ptr[this_unit] |= cmask; \\ | |
e5aa0be3 | 588 | __v = _$prefix$bt_piecewise_rshift(__v, cshift); \\ |
9a0782f7 PP |
589 | end -= cshift; \\ |
590 | this_unit--; \\ | |
591 | } \\ | |
592 | for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \\ | |
593 | __ptr[this_unit] = (type) __v; \\ | |
e5aa0be3 | 594 | __v = _$prefix$bt_piecewise_rshift(__v, ts); \\ |
9a0782f7 PP |
595 | end -= ts; \\ |
596 | } \\ | |
597 | if (__start % ts) { \\ | |
598 | mask = (~(type) 0) << (ts - (__start % ts)); \\ | |
599 | cmask = (type) __v; \\ | |
600 | cmask &= ~mask; \\ | |
601 | __ptr[this_unit] &= mask; \\ | |
602 | __ptr[this_unit] |= cmask; \\ | |
603 | } else \\ | |
604 | __ptr[this_unit] = (type) __v; \\ | |
605 | } while (0) | |
606 | ||
607 | /* | |
e5aa0be3 PP |
608 | * $prefix$bt_bitfield_write_le - write integer to a bitfield in little endian |
609 | * $prefix$bt_bitfield_write_be - write integer to a bitfield in big endian | |
9a0782f7 PP |
610 | */ |
611 | ||
e5aa0be3 | 612 | #if ($PREFIX$BYTE_ORDER == LITTLE_ENDIAN) |
9a0782f7 | 613 | |
e5aa0be3 PP |
614 | #define $prefix$bt_bitfield_write_le(ptr, type, _start, _length, _v) \\ |
615 | _$prefix$bt_bitfield_write_le(ptr, type, _start, _length, _v) | |
9a0782f7 | 616 | |
e5aa0be3 PP |
617 | #define $prefix$bt_bitfield_write_be(ptr, type, _start, _length, _v) \\ |
618 | _$prefix$bt_bitfield_write_be(ptr, unsigned char, _start, _length, _v) | |
9a0782f7 | 619 | |
e5aa0be3 | 620 | #elif ($PREFIX$BYTE_ORDER == BIG_ENDIAN) |
9a0782f7 | 621 | |
e5aa0be3 PP |
622 | #define $prefix$bt_bitfield_write_le(ptr, type, _start, _length, _v) \\ |
623 | _$prefix$bt_bitfield_write_le(ptr, unsigned char, _start, _length, _v) | |
9a0782f7 | 624 | |
e5aa0be3 PP |
625 | #define $prefix$bt_bitfield_write_be(ptr, type, _start, _length, _v) \\ |
626 | _$prefix$bt_bitfield_write_be(ptr, type, _start, _length, _v) | |
9a0782f7 | 627 | |
e5aa0be3 | 628 | #else /* ($PREFIX$BYTE_ORDER == PDP_ENDIAN) */ |
9a0782f7 PP |
629 | |
630 | #error "Byte order not supported" | |
631 | ||
632 | #endif | |
633 | ||
e5aa0be3 PP |
634 | #endif /* _$PREFIX$BITFIELD_H */ |
635 | ''' |