xref: /openbmc/qemu/include/qemu/bswap.h (revision 08ae519ab8eb6c9abbd97156cb3678f372521501)
1 #ifndef BSWAP_H
2 #define BSWAP_H
3 
4 #undef  bswap16
5 #define bswap16(_x) __builtin_bswap16(_x)
6 #undef  bswap32
7 #define bswap32(_x) __builtin_bswap32(_x)
8 #undef  bswap64
9 #define bswap64(_x) __builtin_bswap64(_x)
10 
bswap24(uint32_t x)11 static inline uint32_t bswap24(uint32_t x)
12 {
13     return (((x & 0x000000ffU) << 16) |
14             ((x & 0x0000ff00U) <<  0) |
15             ((x & 0x00ff0000U) >> 16));
16 }
17 
bswap16s(uint16_t * s)18 static inline void bswap16s(uint16_t *s)
19 {
20     *s = __builtin_bswap16(*s);
21 }
22 
bswap24s(uint32_t * s)23 static inline void bswap24s(uint32_t *s)
24 {
25     *s = bswap24(*s & 0x00ffffffU);
26 }
27 
bswap32s(uint32_t * s)28 static inline void bswap32s(uint32_t *s)
29 {
30     *s = __builtin_bswap32(*s);
31 }
32 
bswap64s(uint64_t * s)33 static inline void bswap64s(uint64_t *s)
34 {
35     *s = __builtin_bswap64(*s);
36 }
37 
38 #if HOST_BIG_ENDIAN
39 #define be_bswap(v, size) (v)
40 #define le_bswap(v, size) glue(__builtin_bswap, size)(v)
41 #define be_bswap24(v) (v)
42 #define le_bswap24(v) bswap24(v)
43 #define be_bswaps(v, size)
44 #define le_bswaps(p, size) \
45             do { *p = glue(__builtin_bswap, size)(*p); } while (0)
46 #else
47 #define le_bswap(v, size) (v)
48 #define be_bswap24(v) bswap24(v)
49 #define le_bswap24(v) (v)
50 #define be_bswap(v, size) glue(__builtin_bswap, size)(v)
51 #define le_bswaps(v, size)
52 #define be_bswaps(p, size) \
53             do { *p = glue(__builtin_bswap, size)(*p); } while (0)
54 #endif
55 
56 /**
57  * Endianness conversion functions between host cpu and specified endianness.
58  * (We list the complete set of prototypes produced by the macros below
59  * to assist people who search the headers to find their definitions.)
60  *
61  * uint16_t le16_to_cpu(uint16_t v);
62  * uint32_t le32_to_cpu(uint32_t v);
63  * uint64_t le64_to_cpu(uint64_t v);
64  * uint16_t be16_to_cpu(uint16_t v);
65  * uint32_t be32_to_cpu(uint32_t v);
66  * uint64_t be64_to_cpu(uint64_t v);
67  *
68  * Convert the value @v from the specified format to the native
69  * endianness of the host CPU by byteswapping if necessary, and
70  * return the converted value.
71  *
72  * uint16_t cpu_to_le16(uint16_t v);
73  * uint32_t cpu_to_le32(uint32_t v);
74  * uint64_t cpu_to_le64(uint64_t v);
75  * uint16_t cpu_to_be16(uint16_t v);
76  * uint32_t cpu_to_be32(uint32_t v);
77  * uint64_t cpu_to_be64(uint64_t v);
78  *
79  * Convert the value @v from the native endianness of the host CPU to
80  * the specified format by byteswapping if necessary, and return
81  * the converted value.
82  *
83  * void le16_to_cpus(uint16_t *v);
84  * void le32_to_cpus(uint32_t *v);
85  * void le64_to_cpus(uint64_t *v);
86  * void be16_to_cpus(uint16_t *v);
87  * void be32_to_cpus(uint32_t *v);
88  * void be64_to_cpus(uint64_t *v);
89  *
90  * Do an in-place conversion of the value pointed to by @v from the
91  * specified format to the native endianness of the host CPU.
92  *
93  * void cpu_to_le16s(uint16_t *v);
94  * void cpu_to_le32s(uint32_t *v);
95  * void cpu_to_le64s(uint64_t *v);
96  * void cpu_to_be16s(uint16_t *v);
97  * void cpu_to_be32s(uint32_t *v);
98  * void cpu_to_be64s(uint64_t *v);
99  *
100  * Do an in-place conversion of the value pointed to by @v from the
101  * native endianness of the host CPU to the specified format.
102  *
103  * Both X_to_cpu() and cpu_to_X() perform the same operation; you
104  * should use whichever one is better documenting of the function your
105  * code is performing.
106  *
107  * Do not use these functions for conversion of values which are in guest
108  * memory, since the data may not be sufficiently aligned for the host CPU's
109  * load and store instructions. Instead you should use the ld*_p() and
110  * st*_p() functions, which perform loads and stores of data of any
111  * required size and endianness and handle possible misalignment.
112  */
113 
114 #define CPU_CONVERT(endian, size, type)\
115 static inline type endian ## size ## _to_cpu(type v)\
116 {\
117     return glue(endian, _bswap)(v, size);\
118 }\
119 \
120 static inline type cpu_to_ ## endian ## size(type v)\
121 {\
122     return glue(endian, _bswap)(v, size);\
123 }\
124 \
125 static inline void endian ## size ## _to_cpus(type *p)\
126 {\
127     glue(endian, _bswaps)(p, size);\
128 }\
129 \
130 static inline void cpu_to_ ## endian ## size ## s(type *p)\
131 {\
132     glue(endian, _bswaps)(p, size);\
133 }
134 
135 CPU_CONVERT(be, 16, uint16_t)
136 CPU_CONVERT(be, 32, uint32_t)
137 CPU_CONVERT(be, 64, uint64_t)
138 
139 CPU_CONVERT(le, 16, uint16_t)
140 CPU_CONVERT(le, 32, uint32_t)
141 CPU_CONVERT(le, 64, uint64_t)
142 
143 #undef CPU_CONVERT
144 
145 /*
146  * Same as cpu_to_le{16,32,64}, except that gcc will figure the result is
147  * a compile-time constant if you pass in a constant.  So this can be
148  * used to initialize static variables.
149  */
150 #if HOST_BIG_ENDIAN
151 # define const_le64(_x)                          \
152     ((((_x) & 0x00000000000000ffULL) << 56) |    \
153      (((_x) & 0x000000000000ff00ULL) << 40) |    \
154      (((_x) & 0x0000000000ff0000ULL) << 24) |    \
155      (((_x) & 0x00000000ff000000ULL) <<  8) |    \
156      (((_x) & 0x000000ff00000000ULL) >>  8) |    \
157      (((_x) & 0x0000ff0000000000ULL) >> 24) |    \
158      (((_x) & 0x00ff000000000000ULL) >> 40) |    \
159      (((_x) & 0xff00000000000000ULL) >> 56))
160 # define const_le32(_x)                          \
161     ((((_x) & 0x000000ffU) << 24) |              \
162      (((_x) & 0x0000ff00U) <<  8) |              \
163      (((_x) & 0x00ff0000U) >>  8) |              \
164      (((_x) & 0xff000000U) >> 24))
165 # define const_le16(_x)                          \
166     ((((_x) & 0x00ff) << 8) |                    \
167      (((_x) & 0xff00) >> 8))
168 #else
169 # define const_le64(_x) (_x)
170 # define const_le32(_x) (_x)
171 # define const_le16(_x) (_x)
172 #endif
173 
174 /* unaligned/endian-independent pointer access */
175 
176 /*
177  * the generic syntax is:
178  *
179  * load: ld{type}{sign}{size}_{endian}_p(ptr)
180  *
181  * store: st{type}{size}_{endian}_p(ptr, val)
182  *
183  * Note there are small differences with the softmmu access API!
184  *
185  * type is:
186  * (empty): integer access
187  *   f    : float access
188  *
189  * sign is:
190  * (empty): for 32 or 64 bit sizes (including floats and doubles)
191  *   u    : unsigned
192  *   s    : signed
193  *
194  * size is:
195  *   b: 8 bits
196  *   w: 16 bits
197  *   24: 24 bits
198  *   l: 32 bits
199  *   q: 64 bits
200  *
201  * endian is:
202  *   he   : host endian
203  *   be   : big endian
204  *   le   : little endian
205  *   te   : target endian
206  * (except for byte accesses, which have no endian infix).
207  *
208  * The target endian accessors are obviously only available to source
209  * files which are built per-target; they are defined in cpu-all.h.
210  *
211  * In all cases these functions take a host pointer.
212  * For accessors that take a guest address rather than a
213  * host address, see the cpu_{ld,st}_* accessors defined in
214  * cpu_ldst.h.
215  *
216  * For cases where the size to be used is not fixed at compile time,
217  * there are
218  *  stn_{endian}_p(ptr, sz, val)
219  * which stores @val to @ptr as an @endian-order number @sz bytes in size
220  * and
221  *  ldn_{endian}_p(ptr, sz)
222  * which loads @sz bytes from @ptr as an unsigned @endian-order number
223  * and returns it in a uint64_t.
224  */
225 
ldub_p(const void * ptr)226 static inline int ldub_p(const void *ptr)
227 {
228     return *(uint8_t *)ptr;
229 }
230 
ldsb_p(const void * ptr)231 static inline int ldsb_p(const void *ptr)
232 {
233     return *(int8_t *)ptr;
234 }
235 
stb_p(void * ptr,uint8_t v)236 static inline void stb_p(void *ptr, uint8_t v)
237 {
238     *(uint8_t *)ptr = v;
239 }
240 
241 /*
242  * Any compiler worth its salt will turn these memcpy into native unaligned
243  * operations.  Thus we don't need to play games with packed attributes, or
244  * inline byte-by-byte stores.
245  * Some compilation environments (eg some fortify-source implementations)
246  * may intercept memcpy() in a way that defeats the compiler optimization,
247  * though, so we use __builtin_memcpy() to give ourselves the best chance
248  * of good performance.
249  */
250 
lduw_he_p(const void * ptr)251 static inline int lduw_he_p(const void *ptr)
252 {
253     uint16_t r;
254     __builtin_memcpy(&r, ptr, sizeof(r));
255     return r;
256 }
257 
ldsw_he_p(const void * ptr)258 static inline int ldsw_he_p(const void *ptr)
259 {
260     int16_t r;
261     __builtin_memcpy(&r, ptr, sizeof(r));
262     return r;
263 }
264 
stw_he_p(void * ptr,uint16_t v)265 static inline void stw_he_p(void *ptr, uint16_t v)
266 {
267     __builtin_memcpy(ptr, &v, sizeof(v));
268 }
269 
st24_he_p(void * ptr,uint32_t v)270 static inline void st24_he_p(void *ptr, uint32_t v)
271 {
272     __builtin_memcpy(ptr, &v, 3);
273 }
274 
ldl_he_p(const void * ptr)275 static inline int ldl_he_p(const void *ptr)
276 {
277     int32_t r;
278     __builtin_memcpy(&r, ptr, sizeof(r));
279     return r;
280 }
281 
stl_he_p(void * ptr,uint32_t v)282 static inline void stl_he_p(void *ptr, uint32_t v)
283 {
284     __builtin_memcpy(ptr, &v, sizeof(v));
285 }
286 
ldq_he_p(const void * ptr)287 static inline uint64_t ldq_he_p(const void *ptr)
288 {
289     uint64_t r;
290     __builtin_memcpy(&r, ptr, sizeof(r));
291     return r;
292 }
293 
stq_he_p(void * ptr,uint64_t v)294 static inline void stq_he_p(void *ptr, uint64_t v)
295 {
296     __builtin_memcpy(ptr, &v, sizeof(v));
297 }
298 
lduw_le_p(const void * ptr)299 static inline int lduw_le_p(const void *ptr)
300 {
301     return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
302 }
303 
ldsw_le_p(const void * ptr)304 static inline int ldsw_le_p(const void *ptr)
305 {
306     return (int16_t)le_bswap(lduw_he_p(ptr), 16);
307 }
308 
ldl_le_p(const void * ptr)309 static inline int ldl_le_p(const void *ptr)
310 {
311     return le_bswap(ldl_he_p(ptr), 32);
312 }
313 
ldq_le_p(const void * ptr)314 static inline uint64_t ldq_le_p(const void *ptr)
315 {
316     return le_bswap(ldq_he_p(ptr), 64);
317 }
318 
stw_le_p(void * ptr,uint16_t v)319 static inline void stw_le_p(void *ptr, uint16_t v)
320 {
321     stw_he_p(ptr, le_bswap(v, 16));
322 }
323 
st24_le_p(void * ptr,uint32_t v)324 static inline void st24_le_p(void *ptr, uint32_t v)
325 {
326     st24_he_p(ptr, le_bswap24(v));
327 }
328 
stl_le_p(void * ptr,uint32_t v)329 static inline void stl_le_p(void *ptr, uint32_t v)
330 {
331     stl_he_p(ptr, le_bswap(v, 32));
332 }
333 
stq_le_p(void * ptr,uint64_t v)334 static inline void stq_le_p(void *ptr, uint64_t v)
335 {
336     stq_he_p(ptr, le_bswap(v, 64));
337 }
338 
lduw_be_p(const void * ptr)339 static inline int lduw_be_p(const void *ptr)
340 {
341     return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
342 }
343 
ldsw_be_p(const void * ptr)344 static inline int ldsw_be_p(const void *ptr)
345 {
346     return (int16_t)be_bswap(lduw_he_p(ptr), 16);
347 }
348 
ldl_be_p(const void * ptr)349 static inline int ldl_be_p(const void *ptr)
350 {
351     return be_bswap(ldl_he_p(ptr), 32);
352 }
353 
ldq_be_p(const void * ptr)354 static inline uint64_t ldq_be_p(const void *ptr)
355 {
356     return be_bswap(ldq_he_p(ptr), 64);
357 }
358 
stw_be_p(void * ptr,uint16_t v)359 static inline void stw_be_p(void *ptr, uint16_t v)
360 {
361     stw_he_p(ptr, be_bswap(v, 16));
362 }
363 
st24_be_p(void * ptr,uint32_t v)364 static inline void st24_be_p(void *ptr, uint32_t v)
365 {
366     st24_he_p(ptr, be_bswap24(v));
367 }
368 
stl_be_p(void * ptr,uint32_t v)369 static inline void stl_be_p(void *ptr, uint32_t v)
370 {
371     stl_he_p(ptr, be_bswap(v, 32));
372 }
373 
stq_be_p(void * ptr,uint64_t v)374 static inline void stq_be_p(void *ptr, uint64_t v)
375 {
376     stq_he_p(ptr, be_bswap(v, 64));
377 }
378 
leul_to_cpu(unsigned long v)379 static inline unsigned long leul_to_cpu(unsigned long v)
380 {
381 #if HOST_LONG_BITS == 32
382     return le_bswap(v, 32);
383 #elif HOST_LONG_BITS == 64
384     return le_bswap(v, 64);
385 #else
386 # error Unknown sizeof long
387 #endif
388 }
389 
390 /* Store v to p as a sz byte value in host order */
391 #define DO_STN_LDN_P(END) \
392     static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v)  \
393     {                                                                   \
394         switch (sz) {                                                   \
395         case 1:                                                         \
396             stb_p(ptr, v);                                              \
397             break;                                                      \
398         case 2:                                                         \
399             stw_ ## END ## _p(ptr, v);                                  \
400             break;                                                      \
401         case 4:                                                         \
402             stl_ ## END ## _p(ptr, v);                                  \
403             break;                                                      \
404         case 8:                                                         \
405             stq_ ## END ## _p(ptr, v);                                  \
406             break;                                                      \
407         default:                                                        \
408             g_assert_not_reached();                                     \
409         }                                                               \
410     }                                                                   \
411     static inline uint64_t ldn_## END ## _p(const void *ptr, int sz)    \
412     {                                                                   \
413         switch (sz) {                                                   \
414         case 1:                                                         \
415             return ldub_p(ptr);                                         \
416         case 2:                                                         \
417             return lduw_ ## END ## _p(ptr);                             \
418         case 4:                                                         \
419             return (uint32_t)ldl_ ## END ## _p(ptr);                    \
420         case 8:                                                         \
421             return ldq_ ## END ## _p(ptr);                              \
422         default:                                                        \
423             g_assert_not_reached();                                     \
424         }                                                               \
425     }
426 
427 DO_STN_LDN_P(he)
428 DO_STN_LDN_P(le)
429 DO_STN_LDN_P(be)
430 
431 #undef DO_STN_LDN_P
432 
433 #undef le_bswap
434 #undef be_bswap
435 #undef le_bswaps
436 #undef be_bswaps
437 
438 #endif /* BSWAP_H */
439