xref: /qemu/include/exec/tswap.h (revision b939b8e42acedc2ff35534f96fae026f8fe2efcf)
124be3369SThomas Huth /*
224be3369SThomas Huth  * Macros for swapping a value if the endianness is different
324be3369SThomas Huth  * between the target and the host.
424be3369SThomas Huth  *
524be3369SThomas Huth  * SPDX-License-Identifier: LGPL-2.1-or-later
624be3369SThomas Huth  */
724be3369SThomas Huth 
824be3369SThomas Huth #ifndef TSWAP_H
924be3369SThomas Huth #define TSWAP_H
1024be3369SThomas Huth 
1124be3369SThomas Huth #include "qemu/bswap.h"
1224be3369SThomas Huth 
1342508261SPhilippe Mathieu-Daudé /**
14*b939b8e4SPhilippe Mathieu-Daudé  * target_big_endian:
1542508261SPhilippe Mathieu-Daudé  * Returns true if the (default) endianness of the target is big endian,
16cfac5cdfSPierrick Bouvier  * false otherwise. Common code should normally never need to know about the
17cfac5cdfSPierrick Bouvier  * endianness of the target, so please do *not* use this function unless you
18cfac5cdfSPierrick Bouvier  * know very well what you are doing!
1942508261SPhilippe Mathieu-Daudé  */
20*b939b8e4SPhilippe Mathieu-Daudé bool target_big_endian(void);
21cfac5cdfSPierrick Bouvier #ifdef COMPILING_PER_TARGET
22*b939b8e4SPhilippe Mathieu-Daudé #define target_big_endian()   TARGET_BIG_ENDIAN
23cfac5cdfSPierrick Bouvier #endif
2442508261SPhilippe Mathieu-Daudé 
2524be3369SThomas Huth /*
2624be3369SThomas Huth  * If we're in target-specific code, we can hard-code the swapping
2724be3369SThomas Huth  * condition, otherwise we have to do (slower) run-time checks.
2824be3369SThomas Huth  */
297d7a21baSPhilippe Mathieu-Daudé #ifdef COMPILING_PER_TARGET
3024be3369SThomas Huth #define target_needs_bswap()  (HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN)
3124be3369SThomas Huth #else
32*b939b8e4SPhilippe Mathieu-Daudé #define target_needs_bswap()  (HOST_BIG_ENDIAN != target_big_endian())
337d7a21baSPhilippe Mathieu-Daudé #endif /* COMPILING_PER_TARGET */
3424be3369SThomas Huth 
3524be3369SThomas Huth static inline uint16_t tswap16(uint16_t s)
3624be3369SThomas Huth {
3724be3369SThomas Huth     if (target_needs_bswap()) {
3824be3369SThomas Huth         return bswap16(s);
3924be3369SThomas Huth     } else {
4024be3369SThomas Huth         return s;
4124be3369SThomas Huth     }
4224be3369SThomas Huth }
4324be3369SThomas Huth 
4424be3369SThomas Huth static inline uint32_t tswap32(uint32_t s)
4524be3369SThomas Huth {
4624be3369SThomas Huth     if (target_needs_bswap()) {
4724be3369SThomas Huth         return bswap32(s);
4824be3369SThomas Huth     } else {
4924be3369SThomas Huth         return s;
5024be3369SThomas Huth     }
5124be3369SThomas Huth }
5224be3369SThomas Huth 
5324be3369SThomas Huth static inline uint64_t tswap64(uint64_t s)
5424be3369SThomas Huth {
5524be3369SThomas Huth     if (target_needs_bswap()) {
5624be3369SThomas Huth         return bswap64(s);
5724be3369SThomas Huth     } else {
5824be3369SThomas Huth         return s;
5924be3369SThomas Huth     }
6024be3369SThomas Huth }
6124be3369SThomas Huth 
6224be3369SThomas Huth static inline void tswap16s(uint16_t *s)
6324be3369SThomas Huth {
6424be3369SThomas Huth     if (target_needs_bswap()) {
6524be3369SThomas Huth         *s = bswap16(*s);
6624be3369SThomas Huth     }
6724be3369SThomas Huth }
6824be3369SThomas Huth 
6924be3369SThomas Huth static inline void tswap32s(uint32_t *s)
7024be3369SThomas Huth {
7124be3369SThomas Huth     if (target_needs_bswap()) {
7224be3369SThomas Huth         *s = bswap32(*s);
7324be3369SThomas Huth     }
7424be3369SThomas Huth }
7524be3369SThomas Huth 
7624be3369SThomas Huth static inline void tswap64s(uint64_t *s)
7724be3369SThomas Huth {
7824be3369SThomas Huth     if (target_needs_bswap()) {
7924be3369SThomas Huth         *s = bswap64(*s);
8024be3369SThomas Huth     }
8124be3369SThomas Huth }
8224be3369SThomas Huth 
83663310b0SPierrick Bouvier /* Return ld{word}_{le,be}_p following target endianness. */
84663310b0SPierrick Bouvier #define LOAD_IMPL(word, args...)                    \
85663310b0SPierrick Bouvier do {                                                \
86*b939b8e4SPhilippe Mathieu-Daudé     if (target_big_endian()) {                      \
87663310b0SPierrick Bouvier         return glue(glue(ld, word), _be_p)(args);   \
88663310b0SPierrick Bouvier     } else {                                        \
89663310b0SPierrick Bouvier         return glue(glue(ld, word), _le_p)(args);   \
90663310b0SPierrick Bouvier     }                                               \
91663310b0SPierrick Bouvier } while (0)
92663310b0SPierrick Bouvier 
93663310b0SPierrick Bouvier static inline int lduw_p(const void *ptr)
94663310b0SPierrick Bouvier {
95663310b0SPierrick Bouvier     LOAD_IMPL(uw, ptr);
96663310b0SPierrick Bouvier }
97663310b0SPierrick Bouvier 
98663310b0SPierrick Bouvier static inline int ldsw_p(const void *ptr)
99663310b0SPierrick Bouvier {
100663310b0SPierrick Bouvier     LOAD_IMPL(sw, ptr);
101663310b0SPierrick Bouvier }
102663310b0SPierrick Bouvier 
103663310b0SPierrick Bouvier static inline int ldl_p(const void *ptr)
104663310b0SPierrick Bouvier {
105663310b0SPierrick Bouvier     LOAD_IMPL(l, ptr);
106663310b0SPierrick Bouvier }
107663310b0SPierrick Bouvier 
108663310b0SPierrick Bouvier static inline uint64_t ldq_p(const void *ptr)
109663310b0SPierrick Bouvier {
110663310b0SPierrick Bouvier     LOAD_IMPL(q, ptr);
111663310b0SPierrick Bouvier }
112663310b0SPierrick Bouvier 
113663310b0SPierrick Bouvier static inline uint64_t ldn_p(const void *ptr, int sz)
114663310b0SPierrick Bouvier {
115663310b0SPierrick Bouvier     LOAD_IMPL(n, ptr, sz);
116663310b0SPierrick Bouvier }
117663310b0SPierrick Bouvier 
118663310b0SPierrick Bouvier #undef LOAD_IMPL
119663310b0SPierrick Bouvier 
120663310b0SPierrick Bouvier /* Call st{word}_{le,be}_p following target endianness. */
121663310b0SPierrick Bouvier #define STORE_IMPL(word, args...)           \
122663310b0SPierrick Bouvier do {                                        \
123*b939b8e4SPhilippe Mathieu-Daudé     if (target_big_endian()) {              \
124663310b0SPierrick Bouvier         glue(glue(st, word), _be_p)(args);  \
125663310b0SPierrick Bouvier     } else {                                \
126663310b0SPierrick Bouvier         glue(glue(st, word), _le_p)(args);  \
127663310b0SPierrick Bouvier     }                                       \
128663310b0SPierrick Bouvier } while (0)
129663310b0SPierrick Bouvier 
130663310b0SPierrick Bouvier 
131663310b0SPierrick Bouvier static inline void stw_p(void *ptr, uint16_t v)
132663310b0SPierrick Bouvier {
133663310b0SPierrick Bouvier     STORE_IMPL(w, ptr, v);
134663310b0SPierrick Bouvier }
135663310b0SPierrick Bouvier 
136663310b0SPierrick Bouvier static inline void stl_p(void *ptr, uint32_t v)
137663310b0SPierrick Bouvier {
138663310b0SPierrick Bouvier     STORE_IMPL(l, ptr, v);
139663310b0SPierrick Bouvier }
140663310b0SPierrick Bouvier 
141663310b0SPierrick Bouvier static inline void stq_p(void *ptr, uint64_t v)
142663310b0SPierrick Bouvier {
143663310b0SPierrick Bouvier     STORE_IMPL(q, ptr, v);
144663310b0SPierrick Bouvier }
145663310b0SPierrick Bouvier 
146663310b0SPierrick Bouvier static inline void stn_p(void *ptr, int sz, uint64_t v)
147663310b0SPierrick Bouvier {
148663310b0SPierrick Bouvier     STORE_IMPL(n, ptr, sz, v);
149663310b0SPierrick Bouvier }
150663310b0SPierrick Bouvier 
151663310b0SPierrick Bouvier #undef STORE_IMPL
152663310b0SPierrick Bouvier 
15324be3369SThomas Huth #endif  /* TSWAP_H */
154