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