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