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