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