1#ifndef BSWAP_H
2#define BSWAP_H
3
4#ifdef CONFIG_MACHINE_BSWAP_H
5# include <sys/endian.h>
6# include <machine/bswap.h>
7#elif defined(__FreeBSD__)
8# include <sys/endian.h>
9#elif defined(__HAIKU__)
10# include <endian.h>
11#elif defined(CONFIG_BYTESWAP_H)
12# include <byteswap.h>
13#define BSWAP_FROM_BYTESWAP
14# else
15#define BSWAP_FROM_FALLBACKS
16#endif
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22#ifdef BSWAP_FROM_BYTESWAP
23static inline uint16_t bswap16(uint16_t x)
24{
25 return bswap_16(x);
26}
27
28static inline uint32_t bswap32(uint32_t x)
29{
30 return bswap_32(x);
31}
32
33static inline uint64_t bswap64(uint64_t x)
34{
35 return bswap_64(x);
36}
37#endif
38
39#ifdef BSWAP_FROM_FALLBACKS
40static inline uint16_t bswap16(uint16_t x)
41{
42 return (((x & 0x00ff) << 8) |
43 ((x & 0xff00) >> 8));
44}
45
46static inline uint32_t bswap32(uint32_t x)
47{
48 return (((x & 0x000000ffU) << 24) |
49 ((x & 0x0000ff00U) << 8) |
50 ((x & 0x00ff0000U) >> 8) |
51 ((x & 0xff000000U) >> 24));
52}
53
54static inline uint64_t bswap64(uint64_t x)
55{
56 return (((x & 0x00000000000000ffULL) << 56) |
57 ((x & 0x000000000000ff00ULL) << 40) |
58 ((x & 0x0000000000ff0000ULL) << 24) |
59 ((x & 0x00000000ff000000ULL) << 8) |
60 ((x & 0x000000ff00000000ULL) >> 8) |
61 ((x & 0x0000ff0000000000ULL) >> 24) |
62 ((x & 0x00ff000000000000ULL) >> 40) |
63 ((x & 0xff00000000000000ULL) >> 56));
64}
65#endif
66
67#undef BSWAP_FROM_BYTESWAP
68#undef BSWAP_FROM_FALLBACKS
69
70static inline void bswap16s(uint16_t *s)
71{
72 *s = bswap16(*s);
73}
74
75static inline void bswap32s(uint32_t *s)
76{
77 *s = bswap32(*s);
78}
79
80static inline void bswap64s(uint64_t *s)
81{
82 *s = bswap64(*s);
83}
84
85#if HOST_BIG_ENDIAN
86#define be_bswap(v, size) (v)
87#define le_bswap(v, size) glue(bswap, size)(v)
88#define be_bswaps(v, size)
89#define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
90#else
91#define le_bswap(v, size) (v)
92#define be_bswap(v, size) glue(bswap, size)(v)
93#define le_bswaps(v, size)
94#define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
95#endif
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#define CPU_CONVERT(endian, size, type)\
156static inline type endian ## size ## _to_cpu(type v)\
157{\
158 return glue(endian, _bswap)(v, size);\
159}\
160\
161static inline type cpu_to_ ## endian ## size(type v)\
162{\
163 return glue(endian, _bswap)(v, size);\
164}\
165\
166static inline void endian ## size ## _to_cpus(type *p)\
167{\
168 glue(endian, _bswaps)(p, size);\
169}\
170\
171static inline void cpu_to_ ## endian ## size ## s(type *p)\
172{\
173 glue(endian, _bswaps)(p, size);\
174}
175
176CPU_CONVERT(be, 16, uint16_t)
177CPU_CONVERT(be, 32, uint32_t)
178CPU_CONVERT(be, 64, uint64_t)
179
180CPU_CONVERT(le, 16, uint16_t)
181CPU_CONVERT(le, 32, uint32_t)
182CPU_CONVERT(le, 64, uint64_t)
183
184
185
186
187
188
189#if HOST_BIG_ENDIAN
190# define const_le32(_x) \
191 ((((_x) & 0x000000ffU) << 24) | \
192 (((_x) & 0x0000ff00U) << 8) | \
193 (((_x) & 0x00ff0000U) >> 8) | \
194 (((_x) & 0xff000000U) >> 24))
195# define const_le16(_x) \
196 ((((_x) & 0x00ff) << 8) | \
197 (((_x) & 0xff00) >> 8))
198#else
199# define const_le32(_x) (_x)
200# define const_le16(_x) (_x)
201#endif
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
254static inline int ldub_p(const void *ptr)
255{
256 return *(uint8_t *)ptr;
257}
258
259static inline int ldsb_p(const void *ptr)
260{
261 return *(int8_t *)ptr;
262}
263
264static inline void stb_p(void *ptr, uint8_t v)
265{
266 *(uint8_t *)ptr = v;
267}
268
269
270
271
272
273
274
275
276
277
278
279static inline int lduw_he_p(const void *ptr)
280{
281 uint16_t r;
282 __builtin_memcpy(&r, ptr, sizeof(r));
283 return r;
284}
285
286static inline int ldsw_he_p(const void *ptr)
287{
288 int16_t r;
289 __builtin_memcpy(&r, ptr, sizeof(r));
290 return r;
291}
292
293static inline void stw_he_p(void *ptr, uint16_t v)
294{
295 __builtin_memcpy(ptr, &v, sizeof(v));
296}
297
298static inline int ldl_he_p(const void *ptr)
299{
300 int32_t r;
301 __builtin_memcpy(&r, ptr, sizeof(r));
302 return r;
303}
304
305static inline void stl_he_p(void *ptr, uint32_t v)
306{
307 __builtin_memcpy(ptr, &v, sizeof(v));
308}
309
310static inline uint64_t ldq_he_p(const void *ptr)
311{
312 uint64_t r;
313 __builtin_memcpy(&r, ptr, sizeof(r));
314 return r;
315}
316
317static inline void stq_he_p(void *ptr, uint64_t v)
318{
319 __builtin_memcpy(ptr, &v, sizeof(v));
320}
321
322static inline int lduw_le_p(const void *ptr)
323{
324 return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
325}
326
327static inline int ldsw_le_p(const void *ptr)
328{
329 return (int16_t)le_bswap(lduw_he_p(ptr), 16);
330}
331
332static inline int ldl_le_p(const void *ptr)
333{
334 return le_bswap(ldl_he_p(ptr), 32);
335}
336
337static inline uint64_t ldq_le_p(const void *ptr)
338{
339 return le_bswap(ldq_he_p(ptr), 64);
340}
341
342static inline void stw_le_p(void *ptr, uint16_t v)
343{
344 stw_he_p(ptr, le_bswap(v, 16));
345}
346
347static inline void stl_le_p(void *ptr, uint32_t v)
348{
349 stl_he_p(ptr, le_bswap(v, 32));
350}
351
352static inline void stq_le_p(void *ptr, uint64_t v)
353{
354 stq_he_p(ptr, le_bswap(v, 64));
355}
356
357static inline int lduw_be_p(const void *ptr)
358{
359 return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
360}
361
362static inline int ldsw_be_p(const void *ptr)
363{
364 return (int16_t)be_bswap(lduw_he_p(ptr), 16);
365}
366
367static inline int ldl_be_p(const void *ptr)
368{
369 return be_bswap(ldl_he_p(ptr), 32);
370}
371
372static inline uint64_t ldq_be_p(const void *ptr)
373{
374 return be_bswap(ldq_he_p(ptr), 64);
375}
376
377static inline void stw_be_p(void *ptr, uint16_t v)
378{
379 stw_he_p(ptr, be_bswap(v, 16));
380}
381
382static inline void stl_be_p(void *ptr, uint32_t v)
383{
384 stl_he_p(ptr, be_bswap(v, 32));
385}
386
387static inline void stq_be_p(void *ptr, uint64_t v)
388{
389 stq_he_p(ptr, be_bswap(v, 64));
390}
391
392static inline unsigned long leul_to_cpu(unsigned long v)
393{
394#if HOST_LONG_BITS == 32
395 return le_bswap(v, 32);
396#elif HOST_LONG_BITS == 64
397 return le_bswap(v, 64);
398#else
399# error Unknown sizeof long
400#endif
401}
402
403
404#define DO_STN_LDN_P(END) \
405 static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v) \
406 { \
407 switch (sz) { \
408 case 1: \
409 stb_p(ptr, v); \
410 break; \
411 case 2: \
412 stw_ ## END ## _p(ptr, v); \
413 break; \
414 case 4: \
415 stl_ ## END ## _p(ptr, v); \
416 break; \
417 case 8: \
418 stq_ ## END ## _p(ptr, v); \
419 break; \
420 default: \
421 g_assert_not_reached(); \
422 } \
423 } \
424 static inline uint64_t ldn_## END ## _p(const void *ptr, int sz) \
425 { \
426 switch (sz) { \
427 case 1: \
428 return ldub_p(ptr); \
429 case 2: \
430 return lduw_ ## END ## _p(ptr); \
431 case 4: \
432 return (uint32_t)ldl_ ## END ## _p(ptr); \
433 case 8: \
434 return ldq_ ## END ## _p(ptr); \
435 default: \
436 g_assert_not_reached(); \
437 } \
438 }
439
440DO_STN_LDN_P(he)
441DO_STN_LDN_P(le)
442DO_STN_LDN_P(be)
443
444#undef DO_STN_LDN_P
445
446#undef le_bswap
447#undef be_bswap
448#undef le_bswaps
449#undef be_bswaps
450
451#ifdef __cplusplus
452}
453#endif
454
455#endif
456