1#ifndef BSWAP_H
2#define BSWAP_H
3
4#include "fpu/softfloat-types.h"
5
6#ifdef CONFIG_MACHINE_BSWAP_H
7# include <sys/endian.h>
8# include <machine/bswap.h>
9#elif defined(__FreeBSD__)
10# include <sys/endian.h>
11#elif defined(__HAIKU__)
12# include <endian.h>
13#elif defined(CONFIG_BYTESWAP_H)
14# include <byteswap.h>
15
16static inline uint16_t bswap16(uint16_t x)
17{
18 return bswap_16(x);
19}
20
21static inline uint32_t bswap32(uint32_t x)
22{
23 return bswap_32(x);
24}
25
26static inline uint64_t bswap64(uint64_t x)
27{
28 return bswap_64(x);
29}
30# else
31static inline uint16_t bswap16(uint16_t x)
32{
33 return (((x & 0x00ff) << 8) |
34 ((x & 0xff00) >> 8));
35}
36
37static inline uint32_t bswap32(uint32_t x)
38{
39 return (((x & 0x000000ffU) << 24) |
40 ((x & 0x0000ff00U) << 8) |
41 ((x & 0x00ff0000U) >> 8) |
42 ((x & 0xff000000U) >> 24));
43}
44
45static inline uint64_t bswap64(uint64_t x)
46{
47 return (((x & 0x00000000000000ffULL) << 56) |
48 ((x & 0x000000000000ff00ULL) << 40) |
49 ((x & 0x0000000000ff0000ULL) << 24) |
50 ((x & 0x00000000ff000000ULL) << 8) |
51 ((x & 0x000000ff00000000ULL) >> 8) |
52 ((x & 0x0000ff0000000000ULL) >> 24) |
53 ((x & 0x00ff000000000000ULL) >> 40) |
54 ((x & 0xff00000000000000ULL) >> 56));
55}
56#endif
57
58static inline void bswap16s(uint16_t *s)
59{
60 *s = bswap16(*s);
61}
62
63static inline void bswap32s(uint32_t *s)
64{
65 *s = bswap32(*s);
66}
67
68static inline void bswap64s(uint64_t *s)
69{
70 *s = bswap64(*s);
71}
72
73#if defined(HOST_WORDS_BIGENDIAN)
74#define be_bswap(v, size) (v)
75#define le_bswap(v, size) glue(bswap, size)(v)
76#define be_bswaps(v, size)
77#define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
78#else
79#define le_bswap(v, size) (v)
80#define be_bswap(v, size) glue(bswap, size)(v)
81#define le_bswaps(v, size)
82#define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
83#endif
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#define CPU_CONVERT(endian, size, type)\
144static inline type endian ## size ## _to_cpu(type v)\
145{\
146 return glue(endian, _bswap)(v, size);\
147}\
148\
149static inline type cpu_to_ ## endian ## size(type v)\
150{\
151 return glue(endian, _bswap)(v, size);\
152}\
153\
154static inline void endian ## size ## _to_cpus(type *p)\
155{\
156 glue(endian, _bswaps)(p, size);\
157}\
158\
159static inline void cpu_to_ ## endian ## size ## s(type *p)\
160{\
161 glue(endian, _bswaps)(p, size);\
162}
163
164CPU_CONVERT(be, 16, uint16_t)
165CPU_CONVERT(be, 32, uint32_t)
166CPU_CONVERT(be, 64, uint64_t)
167
168CPU_CONVERT(le, 16, uint16_t)
169CPU_CONVERT(le, 32, uint32_t)
170CPU_CONVERT(le, 64, uint64_t)
171
172
173
174
175
176
177#if defined(HOST_WORDS_BIGENDIAN)
178# define const_le32(_x) \
179 ((((_x) & 0x000000ffU) << 24) | \
180 (((_x) & 0x0000ff00U) << 8) | \
181 (((_x) & 0x00ff0000U) >> 8) | \
182 (((_x) & 0xff000000U) >> 24))
183# define const_le16(_x) \
184 ((((_x) & 0x00ff) << 8) | \
185 (((_x) & 0xff00) >> 8))
186#else
187# define const_le32(_x) (_x)
188# define const_le16(_x) (_x)
189#endif
190
191
192
193typedef union {
194 float32 f;
195 uint32_t l;
196} CPU_FloatU;
197
198typedef union {
199 float64 d;
200#if defined(HOST_WORDS_BIGENDIAN)
201 struct {
202 uint32_t upper;
203 uint32_t lower;
204 } l;
205#else
206 struct {
207 uint32_t lower;
208 uint32_t upper;
209 } l;
210#endif
211 uint64_t ll;
212} CPU_DoubleU;
213
214typedef union {
215 floatx80 d;
216 struct {
217 uint64_t lower;
218 uint16_t upper;
219 } l;
220} CPU_LDoubleU;
221
222typedef union {
223 float128 q;
224#if defined(HOST_WORDS_BIGENDIAN)
225 struct {
226 uint32_t upmost;
227 uint32_t upper;
228 uint32_t lower;
229 uint32_t lowest;
230 } l;
231 struct {
232 uint64_t upper;
233 uint64_t lower;
234 } ll;
235#else
236 struct {
237 uint32_t lowest;
238 uint32_t lower;
239 uint32_t upper;
240 uint32_t upmost;
241 } l;
242 struct {
243 uint64_t lower;
244 uint64_t upper;
245 } ll;
246#endif
247} CPU_QuadU;
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
293
294
295
296
297
298
299
300static inline int ldub_p(const void *ptr)
301{
302 return *(uint8_t *)ptr;
303}
304
305static inline int ldsb_p(const void *ptr)
306{
307 return *(int8_t *)ptr;
308}
309
310static inline void stb_p(void *ptr, uint8_t v)
311{
312 *(uint8_t *)ptr = v;
313}
314
315
316
317
318
319
320
321
322
323
324
325static inline int lduw_he_p(const void *ptr)
326{
327 uint16_t r;
328 __builtin_memcpy(&r, ptr, sizeof(r));
329 return r;
330}
331
332static inline int ldsw_he_p(const void *ptr)
333{
334 int16_t r;
335 __builtin_memcpy(&r, ptr, sizeof(r));
336 return r;
337}
338
339static inline void stw_he_p(void *ptr, uint16_t v)
340{
341 __builtin_memcpy(ptr, &v, sizeof(v));
342}
343
344static inline int ldl_he_p(const void *ptr)
345{
346 int32_t r;
347 __builtin_memcpy(&r, ptr, sizeof(r));
348 return r;
349}
350
351static inline void stl_he_p(void *ptr, uint32_t v)
352{
353 __builtin_memcpy(ptr, &v, sizeof(v));
354}
355
356static inline uint64_t ldq_he_p(const void *ptr)
357{
358 uint64_t r;
359 __builtin_memcpy(&r, ptr, sizeof(r));
360 return r;
361}
362
363static inline void stq_he_p(void *ptr, uint64_t v)
364{
365 __builtin_memcpy(ptr, &v, sizeof(v));
366}
367
368static inline int lduw_le_p(const void *ptr)
369{
370 return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
371}
372
373static inline int ldsw_le_p(const void *ptr)
374{
375 return (int16_t)le_bswap(lduw_he_p(ptr), 16);
376}
377
378static inline int ldl_le_p(const void *ptr)
379{
380 return le_bswap(ldl_he_p(ptr), 32);
381}
382
383static inline uint64_t ldq_le_p(const void *ptr)
384{
385 return le_bswap(ldq_he_p(ptr), 64);
386}
387
388static inline void stw_le_p(void *ptr, uint16_t v)
389{
390 stw_he_p(ptr, le_bswap(v, 16));
391}
392
393static inline void stl_le_p(void *ptr, uint32_t v)
394{
395 stl_he_p(ptr, le_bswap(v, 32));
396}
397
398static inline void stq_le_p(void *ptr, uint64_t v)
399{
400 stq_he_p(ptr, le_bswap(v, 64));
401}
402
403static inline int lduw_be_p(const void *ptr)
404{
405 return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
406}
407
408static inline int ldsw_be_p(const void *ptr)
409{
410 return (int16_t)be_bswap(lduw_he_p(ptr), 16);
411}
412
413static inline int ldl_be_p(const void *ptr)
414{
415 return be_bswap(ldl_he_p(ptr), 32);
416}
417
418static inline uint64_t ldq_be_p(const void *ptr)
419{
420 return be_bswap(ldq_he_p(ptr), 64);
421}
422
423static inline void stw_be_p(void *ptr, uint16_t v)
424{
425 stw_he_p(ptr, be_bswap(v, 16));
426}
427
428static inline void stl_be_p(void *ptr, uint32_t v)
429{
430 stl_he_p(ptr, be_bswap(v, 32));
431}
432
433static inline void stq_be_p(void *ptr, uint64_t v)
434{
435 stq_he_p(ptr, be_bswap(v, 64));
436}
437
438static inline unsigned long leul_to_cpu(unsigned long v)
439{
440#if HOST_LONG_BITS == 32
441 return le_bswap(v, 32);
442#elif HOST_LONG_BITS == 64
443 return le_bswap(v, 64);
444#else
445# error Unknown sizeof long
446#endif
447}
448
449
450#define DO_STN_LDN_P(END) \
451 static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v) \
452 { \
453 switch (sz) { \
454 case 1: \
455 stb_p(ptr, v); \
456 break; \
457 case 2: \
458 stw_ ## END ## _p(ptr, v); \
459 break; \
460 case 4: \
461 stl_ ## END ## _p(ptr, v); \
462 break; \
463 case 8: \
464 stq_ ## END ## _p(ptr, v); \
465 break; \
466 default: \
467 g_assert_not_reached(); \
468 } \
469 } \
470 static inline uint64_t ldn_## END ## _p(const void *ptr, int sz) \
471 { \
472 switch (sz) { \
473 case 1: \
474 return ldub_p(ptr); \
475 case 2: \
476 return lduw_ ## END ## _p(ptr); \
477 case 4: \
478 return (uint32_t)ldl_ ## END ## _p(ptr); \
479 case 8: \
480 return ldq_ ## END ## _p(ptr); \
481 default: \
482 g_assert_not_reached(); \
483 } \
484 }
485
486DO_STN_LDN_P(he)
487DO_STN_LDN_P(le)
488DO_STN_LDN_P(be)
489
490#undef DO_STN_LDN_P
491
492#undef le_bswap
493#undef be_bswap
494#undef le_bswaps
495#undef be_bswaps
496
497#endif
498