]> git.proxmox.com Git - mirror_qemu.git/blame - include/qemu/bswap.h
Replace config-time define HOST_WORDS_BIGENDIAN
[mirror_qemu.git] / include / qemu / bswap.h
CommitLineData
ab93bbe2
FB
1#ifndef BSWAP_H
2#define BSWAP_H
3
5735147e 4#ifdef CONFIG_MACHINE_BSWAP_H
cdfe2851 5# include <sys/endian.h>
cdfe2851 6# include <machine/bswap.h>
de03c316
AF
7#elif defined(__FreeBSD__)
8# include <sys/endian.h>
652a46eb
DC
9#elif defined(__HAIKU__)
10# include <endian.h>
cdfe2851
RH
11#elif defined(CONFIG_BYTESWAP_H)
12# include <byteswap.h>
b30a8c24
PM
13#define BSWAP_FROM_BYTESWAP
14# else
15#define BSWAP_FROM_FALLBACKS
16#endif /* ! CONFIG_MACHINE_BSWAP_H */
ab93bbe2 17
b30a8c24
PM
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22#include "fpu/softfloat-types.h"
23
24#ifdef BSWAP_FROM_BYTESWAP
ab93bbe2
FB
25static inline uint16_t bswap16(uint16_t x)
26{
27 return bswap_16(x);
28}
29
5fafdf24 30static inline uint32_t bswap32(uint32_t x)
ab93bbe2
FB
31{
32 return bswap_32(x);
33}
34
5fafdf24 35static inline uint64_t bswap64(uint64_t x)
ab93bbe2
FB
36{
37 return bswap_64(x);
38}
b30a8c24
PM
39#endif
40
41#ifdef BSWAP_FROM_FALLBACKS
cdfe2851
RH
42static inline uint16_t bswap16(uint16_t x)
43{
44 return (((x & 0x00ff) << 8) |
45 ((x & 0xff00) >> 8));
46}
ab93bbe2 47
cdfe2851
RH
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}
b30a8c24
PM
67#endif
68
69#undef BSWAP_FROM_BYTESWAP
70#undef BSWAP_FROM_FALLBACKS
1360677c 71
ab93bbe2
FB
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
e03b5686 87#if HOST_BIG_ENDIAN
af8ffdfd 88#define be_bswap(v, size) (v)
a4cbfe24 89#define le_bswap(v, size) glue(bswap, size)(v)
af8ffdfd 90#define be_bswaps(v, size)
a4cbfe24 91#define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
af8ffdfd
FB
92#else
93#define le_bswap(v, size) (v)
a4cbfe24 94#define be_bswap(v, size) glue(bswap, size)(v)
af8ffdfd 95#define le_bswaps(v, size)
a4cbfe24 96#define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
af8ffdfd
FB
97#endif
98
7d820b76
PM
99/**
100 * Endianness conversion functions between host cpu and specified endianness.
101 * (We list the complete set of prototypes produced by the macros below
102 * to assist people who search the headers to find their definitions.)
103 *
104 * uint16_t le16_to_cpu(uint16_t v);
105 * uint32_t le32_to_cpu(uint32_t v);
106 * uint64_t le64_to_cpu(uint64_t v);
107 * uint16_t be16_to_cpu(uint16_t v);
108 * uint32_t be32_to_cpu(uint32_t v);
109 * uint64_t be64_to_cpu(uint64_t v);
110 *
111 * Convert the value @v from the specified format to the native
112 * endianness of the host CPU by byteswapping if necessary, and
113 * return the converted value.
114 *
115 * uint16_t cpu_to_le16(uint16_t v);
116 * uint32_t cpu_to_le32(uint32_t v);
117 * uint64_t cpu_to_le64(uint64_t v);
118 * uint16_t cpu_to_be16(uint16_t v);
119 * uint32_t cpu_to_be32(uint32_t v);
120 * uint64_t cpu_to_be64(uint64_t v);
121 *
122 * Convert the value @v from the native endianness of the host CPU to
123 * the specified format by byteswapping if necessary, and return
124 * the converted value.
125 *
126 * void le16_to_cpus(uint16_t *v);
127 * void le32_to_cpus(uint32_t *v);
128 * void le64_to_cpus(uint64_t *v);
129 * void be16_to_cpus(uint16_t *v);
130 * void be32_to_cpus(uint32_t *v);
131 * void be64_to_cpus(uint64_t *v);
132 *
133 * Do an in-place conversion of the value pointed to by @v from the
134 * specified format to the native endianness of the host CPU.
135 *
136 * void cpu_to_le16s(uint16_t *v);
137 * void cpu_to_le32s(uint32_t *v);
138 * void cpu_to_le64s(uint64_t *v);
139 * void cpu_to_be16s(uint16_t *v);
140 * void cpu_to_be32s(uint32_t *v);
141 * void cpu_to_be64s(uint64_t *v);
142 *
143 * Do an in-place conversion of the value pointed to by @v from the
144 * native endianness of the host CPU to the specified format.
145 *
146 * Both X_to_cpu() and cpu_to_X() perform the same operation; you
147 * should use whichever one is better documenting of the function your
148 * code is performing.
149 *
150 * Do not use these functions for conversion of values which are in guest
151 * memory, since the data may not be sufficiently aligned for the host CPU's
152 * load and store instructions. Instead you should use the ld*_p() and
153 * st*_p() functions, which perform loads and stores of data of any
154 * required size and endianness and handle possible misalignment.
155 */
156
af8ffdfd
FB
157#define CPU_CONVERT(endian, size, type)\
158static inline type endian ## size ## _to_cpu(type v)\
159{\
a4cbfe24 160 return glue(endian, _bswap)(v, size);\
af8ffdfd
FB
161}\
162\
163static inline type cpu_to_ ## endian ## size(type v)\
164{\
a4cbfe24 165 return glue(endian, _bswap)(v, size);\
af8ffdfd
FB
166}\
167\
168static inline void endian ## size ## _to_cpus(type *p)\
169{\
a4cbfe24 170 glue(endian, _bswaps)(p, size);\
af8ffdfd
FB
171}\
172\
173static inline void cpu_to_ ## endian ## size ## s(type *p)\
174{\
a4cbfe24 175 glue(endian, _bswaps)(p, size);\
af8ffdfd
FB
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
441330f7 186/*
cbe967f4 187 * Same as cpu_to_le{16,32}, except that gcc will figure the result is
441330f7
GH
188 * a compile-time constant if you pass in a constant. So this can be
189 * used to initialize static variables.
190 */
e03b5686 191#if HOST_BIG_ENDIAN
441330f7
GH
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
7db2145a
RH
205/* Unions for reinterpreting between floats and integers. */
206
cbbab922
PB
207typedef union {
208 float32 f;
209 uint32_t l;
210} CPU_FloatU;
211
212typedef union {
213 float64 d;
e03b5686 214#if HOST_BIG_ENDIAN
cbbab922
PB
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;
e03b5686 238#if HOST_BIG_ENDIAN
cbbab922
PB
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/* unaligned/endian-independent pointer access */
264
265/*
266 * the generic syntax is:
267 *
acfea137 268 * load: ld{type}{sign}{size}_{endian}_p(ptr)
cbbab922 269 *
acfea137 270 * store: st{type}{size}_{endian}_p(ptr, val)
cbbab922
PB
271 *
272 * Note there are small differences with the softmmu access API!
273 *
274 * type is:
275 * (empty): integer access
276 * f : float access
277 *
278 * sign is:
db5fd8d7 279 * (empty): for 32 or 64 bit sizes (including floats and doubles)
cbbab922
PB
280 * u : unsigned
281 * s : signed
282 *
283 * size is:
284 * b: 8 bits
285 * w: 16 bits
286 * l: 32 bits
287 * q: 64 bits
288 *
289 * endian is:
1a3de8db 290 * he : host endian
cbbab922
PB
291 * be : big endian
292 * le : little endian
db5fd8d7 293 * te : target endian
1a3de8db 294 * (except for byte accesses, which have no endian infix).
db5fd8d7
PM
295 *
296 * The target endian accessors are obviously only available to source
297 * files which are built per-target; they are defined in cpu-all.h.
298 *
299 * In all cases these functions take a host pointer.
300 * For accessors that take a guest address rather than a
301 * host address, see the cpu_{ld,st}_* accessors defined in
302 * cpu_ldst.h.
afa4f665
PM
303 *
304 * For cases where the size to be used is not fixed at compile time,
305 * there are
acfea137 306 * stn_{endian}_p(ptr, sz, val)
afa4f665
PM
307 * which stores @val to @ptr as an @endian-order number @sz bytes in size
308 * and
acfea137 309 * ldn_{endian}_p(ptr, sz)
afa4f665
PM
310 * which loads @sz bytes from @ptr as an unsigned @endian-order number
311 * and returns it in a uint64_t.
cbbab922 312 */
c732a52d 313
cbbab922
PB
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
0064aceb 324static inline void stb_p(void *ptr, uint8_t v)
cbbab922
PB
325{
326 *(uint8_t *)ptr = v;
327}
328
77b17570
PM
329/*
330 * Any compiler worth its salt will turn these memcpy into native unaligned
331 * operations. Thus we don't need to play games with packed attributes, or
332 * inline byte-by-byte stores.
333 * Some compilation environments (eg some fortify-source implementations)
334 * may intercept memcpy() in a way that defeats the compiler optimization,
335 * though, so we use __builtin_memcpy() to give ourselves the best chance
336 * of good performance.
337 */
7db2145a 338
1a3de8db 339static inline int lduw_he_p(const void *ptr)
7db2145a
RH
340{
341 uint16_t r;
77b17570 342 __builtin_memcpy(&r, ptr, sizeof(r));
7db2145a
RH
343 return r;
344}
345
1a3de8db 346static inline int ldsw_he_p(const void *ptr)
7db2145a
RH
347{
348 int16_t r;
77b17570 349 __builtin_memcpy(&r, ptr, sizeof(r));
7db2145a
RH
350 return r;
351}
352
1a3de8db 353static inline void stw_he_p(void *ptr, uint16_t v)
7db2145a 354{
77b17570 355 __builtin_memcpy(ptr, &v, sizeof(v));
7db2145a
RH
356}
357
1a3de8db 358static inline int ldl_he_p(const void *ptr)
7db2145a
RH
359{
360 int32_t r;
77b17570 361 __builtin_memcpy(&r, ptr, sizeof(r));
7db2145a
RH
362 return r;
363}
364
1a3de8db 365static inline void stl_he_p(void *ptr, uint32_t v)
7db2145a 366{
77b17570 367 __builtin_memcpy(ptr, &v, sizeof(v));
7db2145a
RH
368}
369
1a3de8db 370static inline uint64_t ldq_he_p(const void *ptr)
7db2145a
RH
371{
372 uint64_t r;
77b17570 373 __builtin_memcpy(&r, ptr, sizeof(r));
7db2145a
RH
374 return r;
375}
376
1a3de8db 377static inline void stq_he_p(void *ptr, uint64_t v)
7db2145a 378{
77b17570 379 __builtin_memcpy(ptr, &v, sizeof(v));
7db2145a
RH
380}
381
cbbab922
PB
382static inline int lduw_le_p(const void *ptr)
383{
1a3de8db 384 return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
cbbab922
PB
385}
386
387static inline int ldsw_le_p(const void *ptr)
388{
1a3de8db 389 return (int16_t)le_bswap(lduw_he_p(ptr), 16);
cbbab922
PB
390}
391
392static inline int ldl_le_p(const void *ptr)
393{
1a3de8db 394 return le_bswap(ldl_he_p(ptr), 32);
cbbab922
PB
395}
396
397static inline uint64_t ldq_le_p(const void *ptr)
398{
1a3de8db 399 return le_bswap(ldq_he_p(ptr), 64);
cbbab922
PB
400}
401
55e7c29e 402static inline void stw_le_p(void *ptr, uint16_t v)
cbbab922 403{
1a3de8db 404 stw_he_p(ptr, le_bswap(v, 16));
cbbab922
PB
405}
406
55e7c29e 407static inline void stl_le_p(void *ptr, uint32_t v)
cbbab922 408{
1a3de8db 409 stl_he_p(ptr, le_bswap(v, 32));
cbbab922
PB
410}
411
412static inline void stq_le_p(void *ptr, uint64_t v)
413{
1a3de8db 414 stq_he_p(ptr, le_bswap(v, 64));
cbbab922
PB
415}
416
cbbab922
PB
417static inline int lduw_be_p(const void *ptr)
418{
1a3de8db 419 return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
cbbab922
PB
420}
421
422static inline int ldsw_be_p(const void *ptr)
423{
1a3de8db 424 return (int16_t)be_bswap(lduw_he_p(ptr), 16);
cbbab922
PB
425}
426
427static inline int ldl_be_p(const void *ptr)
428{
1a3de8db 429 return be_bswap(ldl_he_p(ptr), 32);
cbbab922
PB
430}
431
432static inline uint64_t ldq_be_p(const void *ptr)
433{
1a3de8db 434 return be_bswap(ldq_he_p(ptr), 64);
cbbab922
PB
435}
436
55e7c29e 437static inline void stw_be_p(void *ptr, uint16_t v)
cbbab922 438{
1a3de8db 439 stw_he_p(ptr, be_bswap(v, 16));
cbbab922
PB
440}
441
55e7c29e 442static inline void stl_be_p(void *ptr, uint32_t v)
cbbab922 443{
1a3de8db 444 stl_he_p(ptr, be_bswap(v, 32));
cbbab922
PB
445}
446
447static inline void stq_be_p(void *ptr, uint64_t v)
448{
1a3de8db 449 stq_he_p(ptr, be_bswap(v, 64));
cbbab922
PB
450}
451
c732a52d
RH
452static inline unsigned long leul_to_cpu(unsigned long v)
453{
a8139632 454#if HOST_LONG_BITS == 32
91107fdf 455 return le_bswap(v, 32);
a8139632 456#elif HOST_LONG_BITS == 64
91107fdf
RH
457 return le_bswap(v, 64);
458#else
459# error Unknown sizeof long
460#endif
c732a52d
RH
461}
462
afa4f665
PM
463/* Store v to p as a sz byte value in host order */
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
612d590e
RH
506#undef le_bswap
507#undef be_bswap
508#undef le_bswaps
509#undef be_bswaps
cbbab922 510
b30a8c24
PM
511#ifdef __cplusplus
512}
513#endif
514
ab93bbe2 515#endif /* BSWAP_H */