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