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
323static inline int lduw_he_p(const void *ptr)
324{
325 uint16_t r;
326 memcpy(&r, ptr, sizeof(r));
327 return r;
328}
329
330static inline int ldsw_he_p(const void *ptr)
331{
332 int16_t r;
333 memcpy(&r, ptr, sizeof(r));
334 return r;
335}
336
337static inline void stw_he_p(void *ptr, uint16_t v)
338{
339 memcpy(ptr, &v, sizeof(v));
340}
341
342static inline int ldl_he_p(const void *ptr)
343{
344 int32_t r;
345 memcpy(&r, ptr, sizeof(r));
346 return r;
347}
348
349static inline void stl_he_p(void *ptr, uint32_t v)
350{
351 memcpy(ptr, &v, sizeof(v));
352}
353
354static inline uint64_t ldq_he_p(const void *ptr)
355{
356 uint64_t r;
357 memcpy(&r, ptr, sizeof(r));
358 return r;
359}
360
361static inline void stq_he_p(void *ptr, uint64_t v)
362{
363 memcpy(ptr, &v, sizeof(v));
364}
365
366static inline int lduw_le_p(const void *ptr)
367{
368 return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
369}
370
371static inline int ldsw_le_p(const void *ptr)
372{
373 return (int16_t)le_bswap(lduw_he_p(ptr), 16);
374}
375
376static inline int ldl_le_p(const void *ptr)
377{
378 return le_bswap(ldl_he_p(ptr), 32);
379}
380
381static inline uint64_t ldq_le_p(const void *ptr)
382{
383 return le_bswap(ldq_he_p(ptr), 64);
384}
385
386static inline void stw_le_p(void *ptr, uint16_t v)
387{
388 stw_he_p(ptr, le_bswap(v, 16));
389}
390
391static inline void stl_le_p(void *ptr, uint32_t v)
392{
393 stl_he_p(ptr, le_bswap(v, 32));
394}
395
396static inline void stq_le_p(void *ptr, uint64_t v)
397{
398 stq_he_p(ptr, le_bswap(v, 64));
399}
400
401
402
403static inline float32 ldfl_le_p(const void *ptr)
404{
405 CPU_FloatU u;
406 u.l = ldl_le_p(ptr);
407 return u.f;
408}
409
410static inline void stfl_le_p(void *ptr, float32 v)
411{
412 CPU_FloatU u;
413 u.f = v;
414 stl_le_p(ptr, u.l);
415}
416
417static inline float64 ldfq_le_p(const void *ptr)
418{
419 CPU_DoubleU u;
420 u.ll = ldq_le_p(ptr);
421 return u.d;
422}
423
424static inline void stfq_le_p(void *ptr, float64 v)
425{
426 CPU_DoubleU u;
427 u.d = v;
428 stq_le_p(ptr, u.ll);
429}
430
431static inline int lduw_be_p(const void *ptr)
432{
433 return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
434}
435
436static inline int ldsw_be_p(const void *ptr)
437{
438 return (int16_t)be_bswap(lduw_he_p(ptr), 16);
439}
440
441static inline int ldl_be_p(const void *ptr)
442{
443 return be_bswap(ldl_he_p(ptr), 32);
444}
445
446static inline uint64_t ldq_be_p(const void *ptr)
447{
448 return be_bswap(ldq_he_p(ptr), 64);
449}
450
451static inline void stw_be_p(void *ptr, uint16_t v)
452{
453 stw_he_p(ptr, be_bswap(v, 16));
454}
455
456static inline void stl_be_p(void *ptr, uint32_t v)
457{
458 stl_he_p(ptr, be_bswap(v, 32));
459}
460
461static inline void stq_be_p(void *ptr, uint64_t v)
462{
463 stq_he_p(ptr, be_bswap(v, 64));
464}
465
466
467
468static inline float32 ldfl_be_p(const void *ptr)
469{
470 CPU_FloatU u;
471 u.l = ldl_be_p(ptr);
472 return u.f;
473}
474
475static inline void stfl_be_p(void *ptr, float32 v)
476{
477 CPU_FloatU u;
478 u.f = v;
479 stl_be_p(ptr, u.l);
480}
481
482static inline float64 ldfq_be_p(const void *ptr)
483{
484 CPU_DoubleU u;
485 u.ll = ldq_be_p(ptr);
486 return u.d;
487}
488
489static inline void stfq_be_p(void *ptr, float64 v)
490{
491 CPU_DoubleU u;
492 u.d = v;
493 stq_be_p(ptr, u.ll);
494}
495
496static inline unsigned long leul_to_cpu(unsigned long v)
497{
498#if HOST_LONG_BITS == 32
499 return le_bswap(v, 32);
500#elif HOST_LONG_BITS == 64
501 return le_bswap(v, 64);
502#else
503# error Unknown sizeof long
504#endif
505}
506
507
508#define DO_STN_LDN_P(END) \
509 static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v) \
510 { \
511 switch (sz) { \
512 case 1: \
513 stb_p(ptr, v); \
514 break; \
515 case 2: \
516 stw_ ## END ## _p(ptr, v); \
517 break; \
518 case 4: \
519 stl_ ## END ## _p(ptr, v); \
520 break; \
521 case 8: \
522 stq_ ## END ## _p(ptr, v); \
523 break; \
524 default: \
525 g_assert_not_reached(); \
526 } \
527 } \
528 static inline uint64_t ldn_## END ## _p(const void *ptr, int sz) \
529 { \
530 switch (sz) { \
531 case 1: \
532 return ldub_p(ptr); \
533 case 2: \
534 return lduw_ ## END ## _p(ptr); \
535 case 4: \
536 return (uint32_t)ldl_ ## END ## _p(ptr); \
537 case 8: \
538 return ldq_ ## END ## _p(ptr); \
539 default: \
540 g_assert_not_reached(); \
541 } \
542 }
543
544DO_STN_LDN_P(he)
545DO_STN_LDN_P(le)
546DO_STN_LDN_P(be)
547
548#undef DO_STN_LDN_P
549
550#undef le_bswap
551#undef be_bswap
552#undef le_bswaps
553#undef be_bswaps
554
555#endif
556