config: replace trace type's default BO with configuration's target BO
[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
e72875eb
PP
30{% include 'licence-header.j2' %}
31
75bae33c
PP
32
33#include <limits.h>
34
35#ifdef __cplusplus
696d6508 36# define _CAST_PTR(_type, _value) \
75bae33c
PP
37 static_cast<_type>(static_cast<void *>(_value))
38#else
696d6508 39# define _CAST_PTR(_type, _value) ((void *) (_value))
75bae33c
PP
40#endif
41
7fffc7d1
PP
42{% set tgt_bo = cfg.target_byte_order %}
43{% set tgt_bo_str = 'LITTLE_ENDIAN' if tgt_bo == barectf_config.ByteOrder.LITTLE_ENDIAN else 'BIG_ENDIAN' %}
44#define _BYTE_ORDER {{ tgt_bo_str }}
75bae33c
PP
45
46/* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */
696d6508 47#define _bt_piecewise_rshift(_vtype, _v, _shift) \
75bae33c
PP
48do { \
49 unsigned long ___shift = (_shift); \
50 unsigned long sb = (___shift) / (sizeof(_v) * CHAR_BIT - 1); \
51 unsigned long final = (___shift) % (sizeof(_v) * CHAR_BIT - 1); \
52 \
53 for (; sb; sb--) \
54 _v >>= sizeof(_v) * CHAR_BIT - 1; \
55 _v >>= final; \
56} while (0)
57
58/*
696d6508 59 * bt_bitfield_write - write integer to a bitfield in native endianness
75bae33c
PP
60 *
61 * Save integer to the bitfield, which starts at the "start" bit, has "len"
62 * bits.
63 * The inside of a bitfield is from high bits to low bits.
64 * Uses native endianness.
65 * For unsigned "v", pad MSB with 0 if bitfield is larger than v.
66 * For signed "v", sign-extend v if bitfield is larger than v.
67 *
68 * On little endian, bytes are placed from the less significant to the most
69 * significant. Also, consecutive bitfields are placed from lower bits to higher
70 * bits.
71 *
72 * On big endian, bytes are places from most significant to less significant.
73 * Also, consecutive bitfields are placed from higher to lower bits.
74 */
75
696d6508 76#define _bt_bitfield_write_le(_ptr, type, _start, _length, _vtype, _v) \
75bae33c
PP
77do { \
78 _vtype __v = (_v); \
696d6508 79 type *__ptr = _CAST_PTR(type *, _ptr); \
75bae33c
PP
80 unsigned long __start = (_start), __length = (_length); \
81 type mask, cmask; \
82 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
83 unsigned long start_unit, end_unit, this_unit; \
84 unsigned long end, cshift; /* cshift is "complement shift" */ \
85 \
86 if (!__length) \
87 break; \
88 \
89 end = __start + __length; \
90 start_unit = __start / ts; \
91 end_unit = (end + (ts - 1)) / ts; \
92 \
93 /* Trim v high bits */ \
94 if (__length < sizeof(__v) * CHAR_BIT) \
95 __v &= ~((~(_vtype) 0) << __length); \
96 \
97 /* We can now append v with a simple "or", shift it piece-wise */ \
98 this_unit = start_unit; \
99 if (start_unit == end_unit - 1) { \
100 mask = ~((~(type) 0) << (__start % ts)); \
101 if (end % ts) \
102 mask |= (~(type) 0) << (end % ts); \
103 cmask = (type) __v << (__start % ts); \
104 cmask &= ~mask; \
105 __ptr[this_unit] &= mask; \
106 __ptr[this_unit] |= cmask; \
107 break; \
108 } \
109 if (__start % ts) { \
110 cshift = __start % ts; \
111 mask = ~((~(type) 0) << cshift); \
112 cmask = (type) __v << cshift; \
113 cmask &= ~mask; \
114 __ptr[this_unit] &= mask; \
115 __ptr[this_unit] |= cmask; \
696d6508 116 _bt_piecewise_rshift(_vtype, __v, ts - cshift); \
75bae33c
PP
117 __start += ts - cshift; \
118 this_unit++; \
119 } \
120 for (; this_unit < end_unit - 1; this_unit++) { \
121 __ptr[this_unit] = (type) __v; \
696d6508 122 _bt_piecewise_rshift(_vtype, __v, ts); \
75bae33c
PP
123 __start += ts; \
124 } \
125 if (end % ts) { \
126 mask = (~(type) 0) << (end % ts); \
127 cmask = (type) __v; \
128 cmask &= ~mask; \
129 __ptr[this_unit] &= mask; \
130 __ptr[this_unit] |= cmask; \
131 } else \
132 __ptr[this_unit] = (type) __v; \
133} while (0)
134
696d6508 135#define _bt_bitfield_write_be(_ptr, type, _start, _length, _vtype, _v) \
75bae33c
PP
136do { \
137 _vtype __v = (_v); \
696d6508 138 type *__ptr = _CAST_PTR(type *, _ptr); \
75bae33c
PP
139 unsigned long __start = (_start), __length = (_length); \
140 type mask, cmask; \
141 unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \
142 unsigned long start_unit, end_unit, this_unit; \
143 unsigned long end, cshift; /* cshift is "complement shift" */ \
144 \
145 if (!__length) \
146 break; \
147 \
148 end = __start + __length; \
149 start_unit = __start / ts; \
150 end_unit = (end + (ts - 1)) / ts; \
151 \
152 /* Trim v high bits */ \
153 if (__length < sizeof(__v) * CHAR_BIT) \
154 __v &= ~((~(_vtype) 0) << __length); \
155 \
156 /* We can now append v with a simple "or", shift it piece-wise */ \
157 this_unit = end_unit - 1; \
158 if (start_unit == end_unit - 1) { \
159 mask = ~((~(type) 0) << ((ts - (end % ts)) % ts)); \
160 if (__start % ts) \
161 mask |= (~((type) 0)) << (ts - (__start % ts)); \
162 cmask = (type) __v << ((ts - (end % ts)) % ts); \
163 cmask &= ~mask; \
164 __ptr[this_unit] &= mask; \
165 __ptr[this_unit] |= cmask; \
166 break; \
167 } \
168 if (end % ts) { \
169 cshift = end % ts; \
170 mask = ~((~(type) 0) << (ts - cshift)); \
171 cmask = (type) __v << (ts - cshift); \
172 cmask &= ~mask; \
173 __ptr[this_unit] &= mask; \
174 __ptr[this_unit] |= cmask; \
696d6508 175 _bt_piecewise_rshift(_vtype, __v, cshift); \
75bae33c
PP
176 end -= cshift; \
177 this_unit--; \
178 } \
179 for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \
180 __ptr[this_unit] = (type) __v; \
696d6508 181 _bt_piecewise_rshift(_vtype, __v, ts); \
75bae33c
PP
182 end -= ts; \
183 } \
184 if (__start % ts) { \
185 mask = (~(type) 0) << (ts - (__start % ts)); \
186 cmask = (type) __v; \
187 cmask &= ~mask; \
188 __ptr[this_unit] &= mask; \
189 __ptr[this_unit] |= cmask; \
190 } else \
191 __ptr[this_unit] = (type) __v; \
192} while (0)
193
194/*
696d6508
PP
195 * bt_bitfield_write_le - write integer to a bitfield in little endian
196 * bt_bitfield_write_be - write integer to a bitfield in big endian
75bae33c
PP
197 */
198
696d6508 199#if (_BYTE_ORDER == LITTLE_ENDIAN)
75bae33c 200
696d6508
PP
201#define bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v) \
202 _bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v)
75bae33c 203
696d6508
PP
204#define bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v) \
205 _bt_bitfield_write_be(ptr, unsigned char, _start, _length, _vtype, _v)
75bae33c 206
696d6508 207#elif (_BYTE_ORDER == BIG_ENDIAN)
75bae33c 208
696d6508
PP
209#define bt_bitfield_write_le(ptr, type, _start, _length, _vtype, _v) \
210 _bt_bitfield_write_le(ptr, unsigned char, _start, _length, _vtype, _v)
75bae33c 211
696d6508
PP
212#define bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v) \
213 _bt_bitfield_write_be(ptr, type, _start, _length, _vtype, _v)
75bae33c 214
696d6508 215#else /* (_BYTE_ORDER == PDP_ENDIAN) */
75bae33c
PP
216
217#error "Byte order not supported"
218
219#endif
220
221#endif /* _{{ ucprefix }}BITFIELD_H */
This page took 0.031575 seconds and 4 git commands to generate.