xref: /openbmc/qemu/include/exec/tswap.h (revision 749c21cf6d8ff8eff094137c4ca1298c8f714066)
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 #include "qemu/target-info.h"
13 
14 /*
15  * If we're in target-specific code, we can hard-code the swapping
16  * condition, otherwise we have to do (slower) run-time checks.
17  */
18 #ifdef COMPILING_PER_TARGET
19 #define target_needs_bswap()  (HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN)
20 #else
21 #define target_needs_bswap()  (HOST_BIG_ENDIAN != target_big_endian())
22 #endif /* COMPILING_PER_TARGET */
23 
24 static inline uint16_t tswap16(uint16_t s)
25 {
26     if (target_needs_bswap()) {
27         return bswap16(s);
28     } else {
29         return s;
30     }
31 }
32 
33 static inline uint32_t tswap32(uint32_t s)
34 {
35     if (target_needs_bswap()) {
36         return bswap32(s);
37     } else {
38         return s;
39     }
40 }
41 
42 static inline uint64_t tswap64(uint64_t s)
43 {
44     if (target_needs_bswap()) {
45         return bswap64(s);
46     } else {
47         return s;
48     }
49 }
50 
51 static inline void tswap16s(uint16_t *s)
52 {
53     if (target_needs_bswap()) {
54         *s = bswap16(*s);
55     }
56 }
57 
58 static inline void tswap32s(uint32_t *s)
59 {
60     if (target_needs_bswap()) {
61         *s = bswap32(*s);
62     }
63 }
64 
65 static inline void tswap64s(uint64_t *s)
66 {
67     if (target_needs_bswap()) {
68         *s = bswap64(*s);
69     }
70 }
71 
72 /* Return ld{word}_{le,be}_p following target endianness. */
73 #define LOAD_IMPL(word, args...)                    \
74 do {                                                \
75     if (target_big_endian()) {                      \
76         return glue(glue(ld, word), _be_p)(args);   \
77     } else {                                        \
78         return glue(glue(ld, word), _le_p)(args);   \
79     }                                               \
80 } while (0)
81 
82 static inline int lduw_p(const void *ptr)
83 {
84     LOAD_IMPL(uw, ptr);
85 }
86 
87 static inline int ldsw_p(const void *ptr)
88 {
89     LOAD_IMPL(sw, ptr);
90 }
91 
92 static inline int ldl_p(const void *ptr)
93 {
94     LOAD_IMPL(l, ptr);
95 }
96 
97 static inline uint64_t ldq_p(const void *ptr)
98 {
99     LOAD_IMPL(q, ptr);
100 }
101 
102 static inline uint64_t ldn_p(const void *ptr, int sz)
103 {
104     LOAD_IMPL(n, ptr, sz);
105 }
106 
107 #undef LOAD_IMPL
108 
109 /* Call st{word}_{le,be}_p following target endianness. */
110 #define STORE_IMPL(word, args...)           \
111 do {                                        \
112     if (target_big_endian()) {              \
113         glue(glue(st, word), _be_p)(args);  \
114     } else {                                \
115         glue(glue(st, word), _le_p)(args);  \
116     }                                       \
117 } while (0)
118 
119 
120 static inline void stw_p(void *ptr, uint16_t v)
121 {
122     STORE_IMPL(w, ptr, v);
123 }
124 
125 static inline void stl_p(void *ptr, uint32_t v)
126 {
127     STORE_IMPL(l, ptr, v);
128 }
129 
130 static inline void stq_p(void *ptr, uint64_t v)
131 {
132     STORE_IMPL(q, ptr, v);
133 }
134 
135 static inline void stn_p(void *ptr, int sz, uint64_t v)
136 {
137     STORE_IMPL(n, ptr, sz, v);
138 }
139 
140 #undef STORE_IMPL
141 
142 #endif  /* TSWAP_H */
143