xref: /qemu/include/qemu/bswap.h (revision 727385c4)
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 /* ! CONFIG_MACHINE_BSWAP_H */
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 #include "fpu/softfloat-types.h"
23 
24 #ifdef BSWAP_FROM_BYTESWAP
25 static inline uint16_t bswap16(uint16_t x)
26 {
27     return bswap_16(x);
28 }
29 
30 static inline uint32_t bswap32(uint32_t x)
31 {
32     return bswap_32(x);
33 }
34 
35 static inline uint64_t bswap64(uint64_t x)
36 {
37     return bswap_64(x);
38 }
39 #endif
40 
41 #ifdef BSWAP_FROM_FALLBACKS
42 static inline uint16_t bswap16(uint16_t x)
43 {
44     return (((x & 0x00ff) << 8) |
45             ((x & 0xff00) >> 8));
46 }
47 
48 static 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 
56 static 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 
72 static inline void bswap16s(uint16_t *s)
73 {
74     *s = bswap16(*s);
75 }
76 
77 static inline void bswap32s(uint32_t *s)
78 {
79     *s = bswap32(*s);
80 }
81 
82 static 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  * 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 
157 #define CPU_CONVERT(endian, size, type)\
158 static inline type endian ## size ## _to_cpu(type v)\
159 {\
160     return glue(endian, _bswap)(v, size);\
161 }\
162 \
163 static inline type cpu_to_ ## endian ## size(type v)\
164 {\
165     return glue(endian, _bswap)(v, size);\
166 }\
167 \
168 static inline void endian ## size ## _to_cpus(type *p)\
169 {\
170     glue(endian, _bswaps)(p, size);\
171 }\
172 \
173 static inline void cpu_to_ ## endian ## size ## s(type *p)\
174 {\
175     glue(endian, _bswaps)(p, size);\
176 }
177 
178 CPU_CONVERT(be, 16, uint16_t)
179 CPU_CONVERT(be, 32, uint32_t)
180 CPU_CONVERT(be, 64, uint64_t)
181 
182 CPU_CONVERT(le, 16, uint16_t)
183 CPU_CONVERT(le, 32, uint32_t)
184 CPU_CONVERT(le, 64, uint64_t)
185 
186 /*
187  * Same as cpu_to_le{16,32}, except that gcc will figure the result is
188  * a compile-time constant if you pass in a constant.  So this can be
189  * used to initialize static variables.
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 /* Unions for reinterpreting between floats and integers.  */
206 
207 typedef union {
208     float32 f;
209     uint32_t l;
210 } CPU_FloatU;
211 
212 typedef 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 
228 typedef union {
229      floatx80 d;
230      struct {
231          uint64_t lower;
232          uint16_t upper;
233      } l;
234 } CPU_LDoubleU;
235 
236 typedef 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 /* unaligned/endian-independent pointer access */
264 
265 /*
266  * the generic syntax is:
267  *
268  * load: ld{type}{sign}{size}_{endian}_p(ptr)
269  *
270  * store: st{type}{size}_{endian}_p(ptr, val)
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:
279  * (empty): for 32 or 64 bit sizes (including floats and doubles)
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:
290  *   he   : host endian
291  *   be   : big endian
292  *   le   : little endian
293  *   te   : target endian
294  * (except for byte accesses, which have no endian infix).
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.
303  *
304  * For cases where the size to be used is not fixed at compile time,
305  * there are
306  *  stn_{endian}_p(ptr, sz, val)
307  * which stores @val to @ptr as an @endian-order number @sz bytes in size
308  * and
309  *  ldn_{endian}_p(ptr, sz)
310  * which loads @sz bytes from @ptr as an unsigned @endian-order number
311  * and returns it in a uint64_t.
312  */
313 
314 static inline int ldub_p(const void *ptr)
315 {
316     return *(uint8_t *)ptr;
317 }
318 
319 static inline int ldsb_p(const void *ptr)
320 {
321     return *(int8_t *)ptr;
322 }
323 
324 static inline void stb_p(void *ptr, uint8_t v)
325 {
326     *(uint8_t *)ptr = v;
327 }
328 
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  */
338 
339 static 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 
346 static 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 
353 static inline void stw_he_p(void *ptr, uint16_t v)
354 {
355     __builtin_memcpy(ptr, &v, sizeof(v));
356 }
357 
358 static 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 
365 static inline void stl_he_p(void *ptr, uint32_t v)
366 {
367     __builtin_memcpy(ptr, &v, sizeof(v));
368 }
369 
370 static 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 
377 static inline void stq_he_p(void *ptr, uint64_t v)
378 {
379     __builtin_memcpy(ptr, &v, sizeof(v));
380 }
381 
382 static inline int lduw_le_p(const void *ptr)
383 {
384     return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
385 }
386 
387 static inline int ldsw_le_p(const void *ptr)
388 {
389     return (int16_t)le_bswap(lduw_he_p(ptr), 16);
390 }
391 
392 static inline int ldl_le_p(const void *ptr)
393 {
394     return le_bswap(ldl_he_p(ptr), 32);
395 }
396 
397 static inline uint64_t ldq_le_p(const void *ptr)
398 {
399     return le_bswap(ldq_he_p(ptr), 64);
400 }
401 
402 static inline void stw_le_p(void *ptr, uint16_t v)
403 {
404     stw_he_p(ptr, le_bswap(v, 16));
405 }
406 
407 static inline void stl_le_p(void *ptr, uint32_t v)
408 {
409     stl_he_p(ptr, le_bswap(v, 32));
410 }
411 
412 static inline void stq_le_p(void *ptr, uint64_t v)
413 {
414     stq_he_p(ptr, le_bswap(v, 64));
415 }
416 
417 static inline int lduw_be_p(const void *ptr)
418 {
419     return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
420 }
421 
422 static inline int ldsw_be_p(const void *ptr)
423 {
424     return (int16_t)be_bswap(lduw_he_p(ptr), 16);
425 }
426 
427 static inline int ldl_be_p(const void *ptr)
428 {
429     return be_bswap(ldl_he_p(ptr), 32);
430 }
431 
432 static inline uint64_t ldq_be_p(const void *ptr)
433 {
434     return be_bswap(ldq_he_p(ptr), 64);
435 }
436 
437 static inline void stw_be_p(void *ptr, uint16_t v)
438 {
439     stw_he_p(ptr, be_bswap(v, 16));
440 }
441 
442 static inline void stl_be_p(void *ptr, uint32_t v)
443 {
444     stl_he_p(ptr, be_bswap(v, 32));
445 }
446 
447 static inline void stq_be_p(void *ptr, uint64_t v)
448 {
449     stq_he_p(ptr, be_bswap(v, 64));
450 }
451 
452 static 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 /* 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 
500 DO_STN_LDN_P(he)
501 DO_STN_LDN_P(le)
502 DO_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 /* BSWAP_H */
516