d19951d46454379c58134257f984212cd3417197
[deliverable/barectf.git] / barectf / templates / bitfield.h.j2
1 {% set prefix = cfg.options.code_generation_options.identifier_prefix %}
2 {% set ucprefix = prefix | upper %}
3 #ifndef _{{ ucprefix }}BITFIELD_H
4 #define _{{ ucprefix }}BITFIELD_H
5
6 /*
7 * BabelTrace
8 *
9 * Bitfields read/write functions.
10 *
11 * Copyright (c) 2010-2020 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34 #include <limits.h>
35
36 #ifdef __cplusplus
37 # define CAST_PTR(_type, _value) \
38 static_cast<_type>(static_cast<void *>(_value))
39 #else
40 # define CAST_PTR(_type, _value) ((void *) (_value))
41 #endif
42
43 {% set def_bo = cfg.trace.type.default_byte_order %}
44 {% set def_bo_str = 'LITTLE_ENDIAN' if def_bo == barectf_config.ByteOrder.LITTLE_ENDIAN else 'BIG_ENDIAN' %}
45 #define {{ ucprefix }}BYTE_ORDER {{ def_bo_str }}
46
47
48 /* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */
49 #define _{{ prefix }}bt_piecewise_rshift(_vtype, _v, _shift) \
50 do { \
51 unsigned long ___shift = (_shift); \
52 unsigned long sb = (___shift) / (sizeof(_v) * CHAR_BIT - 1); \
53 unsigned long final = (___shift) % (sizeof(_v) * CHAR_BIT - 1); \
54 \
55 for (; sb; sb--) \
56 _v >>= sizeof(_v) * CHAR_BIT - 1; \
57 _v >>= final; \
58 } while (0)
59
60 /*
61 * {{ prefix }}bt_bitfield_write - write integer to a bitfield in native endianness
62 *
63 * Save integer to the bitfield, which starts at the "start" bit, has "len"
64 * bits.
65 * The inside of a bitfield is from high bits to low bits.
66 * Uses native endianness.
67 * For unsigned "v", pad MSB with 0 if bitfield is larger than v.
68 * For signed "v", sign-extend v if bitfield is larger than v.
69 *
70 * On little endian, bytes are placed from the less significant to the most
71 * significant. Also, consecutive bitfields are placed from lower bits to higher
72 * bits.
73 *
74 * On big endian, bytes are places from most significant to less significant.
75 * Also, consecutive bitfields are placed from higher to lower bits.
76 */
77
78 #define _{{ prefix }}bt_bitfield_write_le(_ptr, type, _start, _length, _vtype, _v) \
79 do { \
80 _vtype __v = (_v); \
81 type *__ptr = CAST_PTR(type *, _ptr); \
82 unsigned long __start = (_start), __length = (_length); \
83 type mask, cmask; \
84 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
85 unsigned long start_unit, end_unit, this_unit; \
86 unsigned long end, cshift; /* cshift is "complement shift" */ \
87 \
88 if (!__length) \
89 break; \
90 \
91 end = __start + __length; \
92 start_unit = __start / ts; \
93 end_unit = (end + (ts - 1)) / ts; \
94 \
95 /* Trim v high bits */ \
96 if (__length < sizeof(__v) * CHAR_BIT) \
97 __v &= ~((~(_vtype) 0) << __length); \
98 \
99 /* We can now append v with a simple "or", shift it piece-wise */ \
100 this_unit = start_unit; \
101 if (start_unit == end_unit - 1) { \
102 mask = ~((~(type) 0) << (__start % ts)); \
103 if (end % ts) \
104 mask |= (~(type) 0) << (end % ts); \
105 cmask = (type) __v << (__start % ts); \
106 cmask &= ~mask; \
107 __ptr[this_unit] &= mask; \
108 __ptr[this_unit] |= cmask; \
109 break; \
110 } \
111 if (__start % ts) { \
112 cshift = __start % ts; \
113 mask = ~((~(type) 0) << cshift); \
114 cmask = (type) __v << cshift; \
115 cmask &= ~mask; \
116 __ptr[this_unit] &= mask; \
117 __ptr[this_unit] |= cmask; \
118 _{{ prefix }}bt_piecewise_rshift(_vtype, __v, ts - cshift); \
119 __start += ts - cshift; \
120 this_unit++; \
121 } \
122 for (; this_unit < end_unit - 1; this_unit++) { \
123 __ptr[this_unit] = (type) __v; \
124 _{{ prefix }}bt_piecewise_rshift(_vtype, __v, ts); \
125 __start += ts; \
126 } \
127 if (end % ts) { \
128 mask = (~(type) 0) << (end % ts); \
129 cmask = (type) __v; \
130 cmask &= ~mask; \
131 __ptr[this_unit] &= mask; \
132 __ptr[this_unit] |= cmask; \
133 } else \
134 __ptr[this_unit] = (type) __v; \
135 } while (0)
136
137 #define _{{ prefix }}bt_bitfield_write_be(_ptr, type, _start, _length, _vtype, _v) \
138 do { \
139 _vtype __v = (_v); \
140 type *__ptr = CAST_PTR(type *, _ptr); \
141 unsigned long __start = (_start), __length = (_length); \
142 type mask, cmask; \
143 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
144 unsigned long start_unit, end_unit, this_unit; \
145 unsigned long end, cshift; /* cshift is "complement shift" */ \
146 \
147 if (!__length) \
148 break; \
149 \
150 end = __start + __length; \
151 start_unit = __start / ts; \
152 end_unit = (end + (ts - 1)) / ts; \
153 \
154 /* Trim v high bits */ \
155 if (__length < sizeof(__v) * CHAR_BIT) \
156 __v &= ~((~(_vtype) 0) << __length); \
157 \
158 /* We can now append v with a simple "or", shift it piece-wise */ \
159 this_unit = end_unit - 1; \
160 if (start_unit == end_unit - 1) { \
161 mask = ~((~(type) 0) << ((ts - (end % ts)) % ts)); \
162 if (__start % ts) \
163 mask |= (~((type) 0)) << (ts - (__start % ts)); \
164 cmask = (type) __v << ((ts - (end % ts)) % ts); \
165 cmask &= ~mask; \
166 __ptr[this_unit] &= mask; \
167 __ptr[this_unit] |= cmask; \
168 break; \
169 } \
170 if (end % ts) { \
171 cshift = end % ts; \
172 mask = ~((~(type) 0) << (ts - cshift)); \
173 cmask = (type) __v << (ts - cshift); \
174 cmask &= ~mask; \
175 __ptr[this_unit] &= mask; \
176 __ptr[this_unit] |= cmask; \
177 _{{ prefix }}bt_piecewise_rshift(_vtype, __v, cshift); \
178 end -= cshift; \
179 this_unit--; \
180 } \
181 for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
182 __ptr[this_unit] = (type) __v; \
183 _{{ prefix }}bt_piecewise_rshift(_vtype, __v, ts); \
184 end -= ts; \
185 } \
186 if (__start % ts) { \
187 mask = (~(type) 0) << (ts - (__start % ts)); \
188 cmask = (type) __v; \
189 cmask &= ~mask; \
190 __ptr[this_unit] &= mask; \
191 __ptr[this_unit] |= cmask; \
192 } else \
193 __ptr[this_unit] = (type) __v; \
194 } while (0)
195
196 /*
197 * {{ prefix }}bt_bitfield_write_le - write integer to a bitfield in little endian
198 * {{ prefix }}bt_bitfield_write_be - write integer to a bitfield in big endian
199 */
200
201 #if ({{ ucprefix }}BYTE_ORDER == LITTLE_ENDIAN)
202
203 #define {{ prefix }}bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v) \
204 _{{ prefix }}bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v)
205
206 #define {{ prefix }}bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v) \
207 _{{ prefix }}bt_bitfield_write_be(ptr, unsigned char, _start, _length, _vtype, _v)
208
209 #elif ({{ ucprefix }}BYTE_ORDER == BIG_ENDIAN)
210
211 #define {{ prefix }}bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v) \
212 _{{ prefix }}bt_bitfield_write_le(ptr, unsigned char, _start, _length, _vtype, _v)
213
214 #define {{ prefix }}bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v) \
215 _{{ prefix }}bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v)
216
217 #else /* ({{ ucprefix }}BYTE_ORDER == PDP_ENDIAN) */
218
219 #error "Byte order not supported"
220
221 #endif
222
223 #endif /* _{{ ucprefix }}BITFIELD_H */
This page took 0.041356 seconds and 3 git commands to generate.