1#ifndef BSWAP_H
2#define BSWAP_H
3
4#include "config-host.h"
5#include <inttypes.h>
6#include <limits.h>
7#include <string.h>
8#include "fpu/softfloat.h"
9
10#ifdef CONFIG_MACHINE_BSWAP_H
11# include <sys/endian.h>
12# include <sys/types.h>
13# include <machine/bswap.h>
14#elif defined(__FreeBSD__)
15# include <sys/endian.h>
16#elif defined(CONFIG_BYTESWAP_H)
17# include <byteswap.h>
18
19static inline uint16_t bswap16(uint16_t x)
20{
21 return bswap_16(x);
22}
23
24static inline uint32_t bswap32(uint32_t x)
25{
26 return bswap_32(x);
27}
28
29static inline uint64_t bswap64(uint64_t x)
30{
31 return bswap_64(x);
32}
33# else
34static inline uint16_t bswap16(uint16_t x)
35{
36 return (((x & 0x00ff) << 8) |
37 ((x & 0xff00) >> 8));
38}
39
40static inline uint32_t bswap32(uint32_t x)
41{
42 return (((x & 0x000000ffU) << 24) |
43 ((x & 0x0000ff00U) << 8) |
44 ((x & 0x00ff0000U) >> 8) |
45 ((x & 0xff000000U) >> 24));
46}
47
48static inline uint64_t bswap64(uint64_t x)
49{
50 return (((x & 0x00000000000000ffULL) << 56) |
51 ((x & 0x000000000000ff00ULL) << 40) |
52 ((x & 0x0000000000ff0000ULL) << 24) |
53 ((x & 0x00000000ff000000ULL) << 8) |
54 ((x & 0x000000ff00000000ULL) >> 8) |
55 ((x & 0x0000ff0000000000ULL) >> 24) |
56 ((x & 0x00ff000000000000ULL) >> 40) |
57 ((x & 0xff00000000000000ULL) >> 56));
58}
59#endif
60
61static inline void bswap16s(uint16_t *s)
62{
63 *s = bswap16(*s);
64}
65
66static inline void bswap32s(uint32_t *s)
67{
68 *s = bswap32(*s);
69}
70
71static inline void bswap64s(uint64_t *s)
72{
73 *s = bswap64(*s);
74}
75
76#if defined(HOST_WORDS_BIGENDIAN)
77#define be_bswap(v, size) (v)
78#define le_bswap(v, size) glue(bswap, size)(v)
79#define be_bswaps(v, size)
80#define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
81#else
82#define le_bswap(v, size) (v)
83#define be_bswap(v, size) glue(bswap, size)(v)
84#define le_bswaps(v, size)
85#define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
86#endif
87
88#define CPU_CONVERT(endian, size, type)\
89static inline type endian ## size ## _to_cpu(type v)\
90{\
91 return glue(endian, _bswap)(v, size);\
92}\
93\
94static inline type cpu_to_ ## endian ## size(type v)\
95{\
96 return glue(endian, _bswap)(v, size);\
97}\
98\
99static inline void endian ## size ## _to_cpus(type *p)\
100{\
101 glue(endian, _bswaps)(p, size);\
102}\
103\
104static inline void cpu_to_ ## endian ## size ## s(type *p)\
105{\
106 glue(endian, _bswaps)(p, size);\
107}\
108\
109static inline type endian ## size ## _to_cpup(const type *p)\
110{\
111 return glue(glue(endian, size), _to_cpu)(*p);\
112}\
113\
114static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
115{\
116 *p = glue(glue(cpu_to_, endian), size)(v);\
117}
118
119CPU_CONVERT(be, 16, uint16_t)
120CPU_CONVERT(be, 32, uint32_t)
121CPU_CONVERT(be, 64, uint64_t)
122
123CPU_CONVERT(le, 16, uint16_t)
124CPU_CONVERT(le, 32, uint32_t)
125CPU_CONVERT(le, 64, uint64_t)
126
127
128static inline uint32_t qemu_bswap_len(uint32_t value, int len)
129{
130 return bswap32(value) >> (32 - 8 * len);
131}
132
133
134
135typedef union {
136 float32 f;
137 uint32_t l;
138} CPU_FloatU;
139
140typedef union {
141 float64 d;
142#if defined(HOST_WORDS_BIGENDIAN)
143 struct {
144 uint32_t upper;
145 uint32_t lower;
146 } l;
147#else
148 struct {
149 uint32_t lower;
150 uint32_t upper;
151 } l;
152#endif
153 uint64_t ll;
154} CPU_DoubleU;
155
156typedef union {
157 floatx80 d;
158 struct {
159 uint64_t lower;
160 uint16_t upper;
161 } l;
162} CPU_LDoubleU;
163
164typedef union {
165 float128 q;
166#if defined(HOST_WORDS_BIGENDIAN)
167 struct {
168 uint32_t upmost;
169 uint32_t upper;
170 uint32_t lower;
171 uint32_t lowest;
172 } l;
173 struct {
174 uint64_t upper;
175 uint64_t lower;
176 } ll;
177#else
178 struct {
179 uint32_t lowest;
180 uint32_t lower;
181 uint32_t upper;
182 uint32_t upmost;
183 } l;
184 struct {
185 uint64_t lower;
186 uint64_t upper;
187 } ll;
188#endif
189} CPU_QuadU;
190
191
192
193
194
195
196
197
198
199
200
201
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
233static inline int ldub_p(const void *ptr)
234{
235 return *(uint8_t *)ptr;
236}
237
238static inline int ldsb_p(const void *ptr)
239{
240 return *(int8_t *)ptr;
241}
242
243static inline void stb_p(void *ptr, uint8_t v)
244{
245 *(uint8_t *)ptr = v;
246}
247
248
249
250
251
252static inline int lduw_he_p(const void *ptr)
253{
254 uint16_t r;
255 memcpy(&r, ptr, sizeof(r));
256 return r;
257}
258
259static inline int ldsw_he_p(const void *ptr)
260{
261 int16_t r;
262 memcpy(&r, ptr, sizeof(r));
263 return r;
264}
265
266static inline void stw_he_p(void *ptr, uint16_t v)
267{
268 memcpy(ptr, &v, sizeof(v));
269}
270
271static inline int ldl_he_p(const void *ptr)
272{
273 int32_t r;
274 memcpy(&r, ptr, sizeof(r));
275 return r;
276}
277
278static inline void stl_he_p(void *ptr, uint32_t v)
279{
280 memcpy(ptr, &v, sizeof(v));
281}
282
283static inline uint64_t ldq_he_p(const void *ptr)
284{
285 uint64_t r;
286 memcpy(&r, ptr, sizeof(r));
287 return r;
288}
289
290static inline void stq_he_p(void *ptr, uint64_t v)
291{
292 memcpy(ptr, &v, sizeof(v));
293}
294
295static inline int lduw_le_p(const void *ptr)
296{
297 return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
298}
299
300static inline int ldsw_le_p(const void *ptr)
301{
302 return (int16_t)le_bswap(lduw_he_p(ptr), 16);
303}
304
305static inline int ldl_le_p(const void *ptr)
306{
307 return le_bswap(ldl_he_p(ptr), 32);
308}
309
310static inline uint64_t ldq_le_p(const void *ptr)
311{
312 return le_bswap(ldq_he_p(ptr), 64);
313}
314
315static inline void stw_le_p(void *ptr, uint16_t v)
316{
317 stw_he_p(ptr, le_bswap(v, 16));
318}
319
320static inline void stl_le_p(void *ptr, uint32_t v)
321{
322 stl_he_p(ptr, le_bswap(v, 32));
323}
324
325static inline void stq_le_p(void *ptr, uint64_t v)
326{
327 stq_he_p(ptr, le_bswap(v, 64));
328}
329
330
331
332static inline float32 ldfl_le_p(const void *ptr)
333{
334 CPU_FloatU u;
335 u.l = ldl_le_p(ptr);
336 return u.f;
337}
338
339static inline void stfl_le_p(void *ptr, float32 v)
340{
341 CPU_FloatU u;
342 u.f = v;
343 stl_le_p(ptr, u.l);
344}
345
346static inline float64 ldfq_le_p(const void *ptr)
347{
348 CPU_DoubleU u;
349 u.ll = ldq_le_p(ptr);
350 return u.d;
351}
352
353static inline void stfq_le_p(void *ptr, float64 v)
354{
355 CPU_DoubleU u;
356 u.d = v;
357 stq_le_p(ptr, u.ll);
358}
359
360static inline int lduw_be_p(const void *ptr)
361{
362 return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
363}
364
365static inline int ldsw_be_p(const void *ptr)
366{
367 return (int16_t)be_bswap(lduw_he_p(ptr), 16);
368}
369
370static inline int ldl_be_p(const void *ptr)
371{
372 return be_bswap(ldl_he_p(ptr), 32);
373}
374
375static inline uint64_t ldq_be_p(const void *ptr)
376{
377 return be_bswap(ldq_he_p(ptr), 64);
378}
379
380static inline void stw_be_p(void *ptr, uint16_t v)
381{
382 stw_he_p(ptr, be_bswap(v, 16));
383}
384
385static inline void stl_be_p(void *ptr, uint32_t v)
386{
387 stl_he_p(ptr, be_bswap(v, 32));
388}
389
390static inline void stq_be_p(void *ptr, uint64_t v)
391{
392 stq_he_p(ptr, be_bswap(v, 64));
393}
394
395
396
397static inline float32 ldfl_be_p(const void *ptr)
398{
399 CPU_FloatU u;
400 u.l = ldl_be_p(ptr);
401 return u.f;
402}
403
404static inline void stfl_be_p(void *ptr, float32 v)
405{
406 CPU_FloatU u;
407 u.f = v;
408 stl_be_p(ptr, u.l);
409}
410
411static inline float64 ldfq_be_p(const void *ptr)
412{
413 CPU_DoubleU u;
414 u.ll = ldq_be_p(ptr);
415 return u.d;
416}
417
418static inline void stfq_be_p(void *ptr, float64 v)
419{
420 CPU_DoubleU u;
421 u.d = v;
422 stq_be_p(ptr, u.ll);
423}
424
425static inline unsigned long leul_to_cpu(unsigned long v)
426{
427
428
429#if ULONG_MAX == UINT32_MAX
430 return le_bswap(v, 32);
431#elif ULONG_MAX == UINT64_MAX
432 return le_bswap(v, 64);
433#else
434# error Unknown sizeof long
435#endif
436}
437
438#undef le_bswap
439#undef be_bswap
440#undef le_bswaps
441#undef be_bswaps
442
443#endif
444