1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
|
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
#ifndef APOS_BITS_H
#define APOS_BITS_H
/**
* @file bits.h
* Bit manipulations.
*/
#include <apos/types.h>
#include <apos/builtin.h>
/** @name Arithmetic integer bit manipulation. */
/** @{ */
/**
* Check if bits are set.
*
* @param x Value to check in.
* @param y Mask of bits to check.
* @return \c 0 if none of the bits aren't set, non-zero otherwise.
*/
#define is_set(x, y) ((x) & (y))
/**
* Set bits.
*
* @param x Value to set in.
* @param y Mask of bits to set.
*/
#define set_bits(x, y) ((x) |= (y))
/**
* Clear bits.
*
* @param x Value to clear in.
* @param y Mask of bits to clear.
*/
#define clear_bits(x, y) ((x) &= ~(y))
/**
* Set bit.
* Wrapper around \ref set_bits() for when only one bit is changed,
* mostly just for readability purposes.
*
* @param x Value to set in.
* @param y Mask of bit to set.
*/
#define set_bit(x, y) set_bits(x, y)
/** Clear bit.
* Wrapper around \ref clear_bits() for when only one bit is
* changed, mostly just for readability purposes.
*
* @param x Value to clear in.
* @param y Mask of bit to clear.
*/
#define clear_bit(x, y) clear_bits(x, y)
/**
* Is nth bit set.
*
* @param x Value to check in.
* @param y Index of bit to check.
* @return \c 0 if bit is not set, non-zero otherwise.
*/
#define is_nset(x, y) (is_set((x), 1UL << (y)))
/**
* Set nth bit.
*
* @param x Value to set in.
* @param y Index of bit to set.
*/
#define set_nbit(x, y) (set_bit((x), 1UL << (y)))
/** Clear nth bit.
*
* @param x Value to clear in.
* @param y Index of bit to clear.
*/
#define clear_nbit(x, y) (clear_bit((x), 1UL << (y)))
/** @} */
/**
* @name Bitmap manipulation.
* A bitmap can be any number of bits in an array-like structure.
*/
/** @{ */
/**
* Is nth bit set in bitmap.
*
* @param bmap Pointer to bitmap.
* @param n Index of bit to check.
* @return \c 0 if bit is not set, non-zero otherwise.
*/
static inline bool bitmap_is_set(void *bmap, size_t n)
{
uint8_t *bitmap = bmap;
size_t i = n / 8;
size_t r = n - (i * 8);
return is_nset(bitmap[i], r);
}
/**
* Set nth bit in bitmap.
*
* @param bmap Bitmap.
* @param n Index of bit to set.
*/
static inline void bitmap_set(void *bmap, size_t n)
{
uint8_t *bitmap = bmap;
size_t i = n / 8;
size_t r = n - (i * 8);
set_nbit(bitmap[i], r);
}
/**
* Clear nth bit in bitmap.
*
* @param bmap Bitmap.
* @param n Index of bit to clear.
*/
static inline void bitmap_clear(void *bmap, size_t n)
{
uint8_t *bitmap = bmap;
size_t i = n / 8;
size_t r = n - (i * 8);
clear_nbit(bitmap[i], r);
}
/** @} */
/**
* Swap byte order in \ref uint16_t.
*
* @param u \ref uint16_t to swap.
* @return \c u with its byte order swapper.
*/
uint16_t __bswap16(uint16_t u);
/**
* Swap byte order in \ref uint32_t.
*
* @param u \ref uint32_t to swap.
* @return \c u with its byte order swapped.
*/
uint32_t __bswap32(uint32_t u);
/**
* Swap byte order in \ref uint64_t.
*
* @param u \ref uint64_t to swap.
* @return \c u with its byte order swapped.
*/
uint64_t __bswap64(uint64_t u);
#if __has_builtin(__builtin_bswap16)
#define __bswap16(x) __builtin_bswap16(x)
#endif
#if __has_builtin(__builtin_bswap32)
#define __bswap32(x) __builtin_bswap32(x)
#endif
#if __has_builtin(__builtin_bswap64)
#define __bswap64(x) __builtin_bswap64(x)
#endif
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
/**
* Convert big endian \ref uint16_t to cpu endianness.
*
* @param x \ref uint16_t to convert.
* @return \c x in cpu endianness.
*/
#define be16_to_cpu(x) __bswap16(x)
/**
* Convert big endian \ref uint32_t to cpu endianness.
*
* @param x \ref uint32_t to convert.
* @return \c x in cpu endianness.
*/
#define be32_to_cpu(x) __bswap32(x)
/**
* Convert big endian \ref uint64_t to cpu endianness.
*
* @param x \ref uint64_t to convert.
* @return \c x in cpu endianness.
*/
#define be64_to_cpu(x) __bswap64(x)
/**
* Convert cpu endian \ref uint16_t to big endian.
*
* @param x \ref uint16_t to convert.
* @return \c x in big endian.
*/
#define cpu_to_be16(x) __bswap16(x)
/**
* Convert cpu endian \ref uint32_t to big endian.
*
* @param x \ref uint32_t to convert.
* @return \c x in big endian.
*/
#define cpu_to_be32(x) __bswap32(x)
/**
* Convert cpu endian to \ref uint64_t to big endian.
*
* @param x \ref uint64_t to convert.
* @return \c x in big endian.
*/
#define cpu_to_be64(x) __bswap64(x)
/**
* Convert little endian \ref uint16_t to cpu endianness.
*
* @param x \ref uint16_t to convert.
* @return \c x in cpu endianness.
*/
#define le16_to_cpu(x) (x)
/**
* Convert little endian \ref uint32_t to cpu endianness.
*
* @param x \ref uint32_t to convert.
* @return \c x in cpu endianness.
*/
#define le32_to_cpu(x) (x)
/**
* Convert little endian \ref uint64_t to cpu endianness.
*
* @param x \ref uint64_t to convert.
* @return \c x in cpu endianness.
*/
#define le64_to_cpu(x) (x)
/**
* Convert cpu endian \ref uint16_t to little endian.
*
* @param x \ref uint16_t to convert.
* @return \c x in little endian.
*/
#define cpu_to_le16(x) (x)
/**
* Convert cpu endian \ref uint32_t to little endian.
*
* @param x \ref uint32_t to convert.
* @return \c x in little endian.
*/
#define cpu_to_le32(x) (x)
/** Convert cpu endian \ref uint64_t to little endian.
*
* @param x \ref uint64_t to convert.
* @return \c x in little endian.
*/
#define cpu_to_le64(x) (x)
#else
#define be16_to_cpu(x) (x)
#define be32_to_cpu(x) (x)
#define be64_to_cpu(x) (x)
#define cpu_to_be16(x) (x)
#define cpu_to_be32(x) (x)
#define cpu_to_be64(x) (x)
#define le16_to_cpu(x) __bswap16(x)
#define le32_to_cpu(x) __bswap32(x)
#define le64_to_cpu(x) __bswap64(x)
#define cpu_to_le16(x) __bswap16(x)
#define cpu_to_le32(x) __bswap32(x)
#define cpu_to_le64(x) __bswap64(x)
#endif
#endif /* APOS_BITS_H */
|