xref: /qemu/include/exec/tswap.h (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
1 /*
2  * Macros for swapping a value if the endianness is different
3  * between the target and the host.
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  */
7 
8 #ifndef TSWAP_H
9 #define TSWAP_H
10 
11 #include "qemu/bswap.h"
12 
13 /**
14  * target_big_endian:
15  * Returns true if the (default) endianness of the target is big endian,
16  * false otherwise. Common code should normally never need to know about the
17  * endianness of the target, so please do *not* use this function unless you
18  * know very well what you are doing!
19  */
20 bool target_big_endian(void);
21 #ifdef COMPILING_PER_TARGET
22 #define target_big_endian()   TARGET_BIG_ENDIAN
23 #endif
24 
25 /*
26  * If we're in target-specific code, we can hard-code the swapping
27  * condition, otherwise we have to do (slower) run-time checks.
28  */
29 #ifdef COMPILING_PER_TARGET
30 #define target_needs_bswap()  (HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN)
31 #else
32 #define target_needs_bswap()  (HOST_BIG_ENDIAN != target_big_endian())
33 #endif /* COMPILING_PER_TARGET */
34 
tswap16(uint16_t s)35 static inline uint16_t tswap16(uint16_t s)
36 {
37     if (target_needs_bswap()) {
38         return bswap16(s);
39     } else {
40         return s;
41     }
42 }
43 
tswap32(uint32_t s)44 static inline uint32_t tswap32(uint32_t s)
45 {
46     if (target_needs_bswap()) {
47         return bswap32(s);
48     } else {
49         return s;
50     }
51 }
52 
tswap64(uint64_t s)53 static inline uint64_t tswap64(uint64_t s)
54 {
55     if (target_needs_bswap()) {
56         return bswap64(s);
57     } else {
58         return s;
59     }
60 }
61 
tswap16s(uint16_t * s)62 static inline void tswap16s(uint16_t *s)
63 {
64     if (target_needs_bswap()) {
65         *s = bswap16(*s);
66     }
67 }
68 
tswap32s(uint32_t * s)69 static inline void tswap32s(uint32_t *s)
70 {
71     if (target_needs_bswap()) {
72         *s = bswap32(*s);
73     }
74 }
75 
tswap64s(uint64_t * s)76 static inline void tswap64s(uint64_t *s)
77 {
78     if (target_needs_bswap()) {
79         *s = bswap64(*s);
80     }
81 }
82 
83 /* Return ld{word}_{le,be}_p following target endianness. */
84 #define LOAD_IMPL(word, args...)                    \
85 do {                                                \
86     if (target_big_endian()) {                      \
87         return glue(glue(ld, word), _be_p)(args);   \
88     } else {                                        \
89         return glue(glue(ld, word), _le_p)(args);   \
90     }                                               \
91 } while (0)
92 
lduw_p(const void * ptr)93 static inline int lduw_p(const void *ptr)
94 {
95     LOAD_IMPL(uw, ptr);
96 }
97 
ldsw_p(const void * ptr)98 static inline int ldsw_p(const void *ptr)
99 {
100     LOAD_IMPL(sw, ptr);
101 }
102 
ldl_p(const void * ptr)103 static inline int ldl_p(const void *ptr)
104 {
105     LOAD_IMPL(l, ptr);
106 }
107 
ldq_p(const void * ptr)108 static inline uint64_t ldq_p(const void *ptr)
109 {
110     LOAD_IMPL(q, ptr);
111 }
112 
ldn_p(const void * ptr,int sz)113 static inline uint64_t ldn_p(const void *ptr, int sz)
114 {
115     LOAD_IMPL(n, ptr, sz);
116 }
117 
118 #undef LOAD_IMPL
119 
120 /* Call st{word}_{le,be}_p following target endianness. */
121 #define STORE_IMPL(word, args...)           \
122 do {                                        \
123     if (target_big_endian()) {              \
124         glue(glue(st, word), _be_p)(args);  \
125     } else {                                \
126         glue(glue(st, word), _le_p)(args);  \
127     }                                       \
128 } while (0)
129 
130 
stw_p(void * ptr,uint16_t v)131 static inline void stw_p(void *ptr, uint16_t v)
132 {
133     STORE_IMPL(w, ptr, v);
134 }
135 
stl_p(void * ptr,uint32_t v)136 static inline void stl_p(void *ptr, uint32_t v)
137 {
138     STORE_IMPL(l, ptr, v);
139 }
140 
stq_p(void * ptr,uint64_t v)141 static inline void stq_p(void *ptr, uint64_t v)
142 {
143     STORE_IMPL(q, ptr, v);
144 }
145 
stn_p(void * ptr,int sz,uint64_t v)146 static inline void stn_p(void *ptr, int sz, uint64_t v)
147 {
148     STORE_IMPL(n, ptr, sz, v);
149 }
150 
151 #undef STORE_IMPL
152 
153 #endif  /* TSWAP_H */
154