xref: /qemu/include/qemu/bswap.h (revision fc524567087c2537b5103cdfc1d41e4f442892b6)
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  * In all cases these functions take a host pointer.
209  * For accessors that take a guest address rather than a
210  * host address, see the cpu_{ld,st}_* accessors defined in
211  * cpu_ldst.h.
212  *
213  * For cases where the size to be used is not fixed at compile time,
214  * there are
215  *  stn_{endian}_p(ptr, sz, val)
216  * which stores @val to @ptr as an @endian-order number @sz bytes in size
217  * and
218  *  ldn_{endian}_p(ptr, sz)
219  * which loads @sz bytes from @ptr as an unsigned @endian-order number
220  * and returns it in a uint64_t.
221  */
222 
ldub_p(const void * ptr)223 static inline int ldub_p(const void *ptr)
224 {
225     return *(uint8_t *)ptr;
226 }
227 
ldsb_p(const void * ptr)228 static inline int ldsb_p(const void *ptr)
229 {
230     return *(int8_t *)ptr;
231 }
232 
stb_p(void * ptr,uint8_t v)233 static inline void stb_p(void *ptr, uint8_t v)
234 {
235     *(uint8_t *)ptr = v;
236 }
237 
238 /*
239  * Any compiler worth its salt will turn these memcpy into native unaligned
240  * operations.  Thus we don't need to play games with packed attributes, or
241  * inline byte-by-byte stores.
242  * Some compilation environments (eg some fortify-source implementations)
243  * may intercept memcpy() in a way that defeats the compiler optimization,
244  * though, so we use __builtin_memcpy() to give ourselves the best chance
245  * of good performance.
246  */
247 
lduw_he_p(const void * ptr)248 static inline int lduw_he_p(const void *ptr)
249 {
250     uint16_t r;
251     __builtin_memcpy(&r, ptr, sizeof(r));
252     return r;
253 }
254 
ldsw_he_p(const void * ptr)255 static inline int ldsw_he_p(const void *ptr)
256 {
257     int16_t r;
258     __builtin_memcpy(&r, ptr, sizeof(r));
259     return r;
260 }
261 
stw_he_p(void * ptr,uint16_t v)262 static inline void stw_he_p(void *ptr, uint16_t v)
263 {
264     __builtin_memcpy(ptr, &v, sizeof(v));
265 }
266 
st24_he_p(void * ptr,uint32_t v)267 static inline void st24_he_p(void *ptr, uint32_t v)
268 {
269     __builtin_memcpy(ptr, &v, 3);
270 }
271 
ldl_he_p(const void * ptr)272 static inline int ldl_he_p(const void *ptr)
273 {
274     int32_t r;
275     __builtin_memcpy(&r, ptr, sizeof(r));
276     return r;
277 }
278 
stl_he_p(void * ptr,uint32_t v)279 static inline void stl_he_p(void *ptr, uint32_t v)
280 {
281     __builtin_memcpy(ptr, &v, sizeof(v));
282 }
283 
ldq_he_p(const void * ptr)284 static inline uint64_t ldq_he_p(const void *ptr)
285 {
286     uint64_t r;
287     __builtin_memcpy(&r, ptr, sizeof(r));
288     return r;
289 }
290 
stq_he_p(void * ptr,uint64_t v)291 static inline void stq_he_p(void *ptr, uint64_t v)
292 {
293     __builtin_memcpy(ptr, &v, sizeof(v));
294 }
295 
lduw_le_p(const void * ptr)296 static inline int lduw_le_p(const void *ptr)
297 {
298     return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
299 }
300 
ldsw_le_p(const void * ptr)301 static inline int ldsw_le_p(const void *ptr)
302 {
303     return (int16_t)le_bswap(lduw_he_p(ptr), 16);
304 }
305 
ldl_le_p(const void * ptr)306 static inline int ldl_le_p(const void *ptr)
307 {
308     return le_bswap(ldl_he_p(ptr), 32);
309 }
310 
ldq_le_p(const void * ptr)311 static inline uint64_t ldq_le_p(const void *ptr)
312 {
313     return le_bswap(ldq_he_p(ptr), 64);
314 }
315 
stw_le_p(void * ptr,uint16_t v)316 static inline void stw_le_p(void *ptr, uint16_t v)
317 {
318     stw_he_p(ptr, le_bswap(v, 16));
319 }
320 
st24_le_p(void * ptr,uint32_t v)321 static inline void st24_le_p(void *ptr, uint32_t v)
322 {
323     st24_he_p(ptr, le_bswap24(v));
324 }
325 
stl_le_p(void * ptr,uint32_t v)326 static inline void stl_le_p(void *ptr, uint32_t v)
327 {
328     stl_he_p(ptr, le_bswap(v, 32));
329 }
330 
stq_le_p(void * ptr,uint64_t v)331 static inline void stq_le_p(void *ptr, uint64_t v)
332 {
333     stq_he_p(ptr, le_bswap(v, 64));
334 }
335 
lduw_be_p(const void * ptr)336 static inline int lduw_be_p(const void *ptr)
337 {
338     return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
339 }
340 
ldsw_be_p(const void * ptr)341 static inline int ldsw_be_p(const void *ptr)
342 {
343     return (int16_t)be_bswap(lduw_he_p(ptr), 16);
344 }
345 
ldl_be_p(const void * ptr)346 static inline int ldl_be_p(const void *ptr)
347 {
348     return be_bswap(ldl_he_p(ptr), 32);
349 }
350 
ldq_be_p(const void * ptr)351 static inline uint64_t ldq_be_p(const void *ptr)
352 {
353     return be_bswap(ldq_he_p(ptr), 64);
354 }
355 
stw_be_p(void * ptr,uint16_t v)356 static inline void stw_be_p(void *ptr, uint16_t v)
357 {
358     stw_he_p(ptr, be_bswap(v, 16));
359 }
360 
st24_be_p(void * ptr,uint32_t v)361 static inline void st24_be_p(void *ptr, uint32_t v)
362 {
363     st24_he_p(ptr, be_bswap24(v));
364 }
365 
stl_be_p(void * ptr,uint32_t v)366 static inline void stl_be_p(void *ptr, uint32_t v)
367 {
368     stl_he_p(ptr, be_bswap(v, 32));
369 }
370 
stq_be_p(void * ptr,uint64_t v)371 static inline void stq_be_p(void *ptr, uint64_t v)
372 {
373     stq_he_p(ptr, be_bswap(v, 64));
374 }
375 
leul_to_cpu(unsigned long v)376 static inline unsigned long leul_to_cpu(unsigned long v)
377 {
378 #if HOST_LONG_BITS == 32
379     return le_bswap(v, 32);
380 #elif HOST_LONG_BITS == 64
381     return le_bswap(v, 64);
382 #else
383 # error Unknown sizeof long
384 #endif
385 }
386 
387 /* Store v to p as a sz byte value in host order */
388 #define DO_STN_LDN_P(END) \
389     static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v)  \
390     {                                                                   \
391         switch (sz) {                                                   \
392         case 1:                                                         \
393             stb_p(ptr, v);                                              \
394             break;                                                      \
395         case 2:                                                         \
396             stw_ ## END ## _p(ptr, v);                                  \
397             break;                                                      \
398         case 4:                                                         \
399             stl_ ## END ## _p(ptr, v);                                  \
400             break;                                                      \
401         case 8:                                                         \
402             stq_ ## END ## _p(ptr, v);                                  \
403             break;                                                      \
404         default:                                                        \
405             g_assert_not_reached();                                     \
406         }                                                               \
407     }                                                                   \
408     static inline uint64_t ldn_## END ## _p(const void *ptr, int sz)    \
409     {                                                                   \
410         switch (sz) {                                                   \
411         case 1:                                                         \
412             return ldub_p(ptr);                                         \
413         case 2:                                                         \
414             return lduw_ ## END ## _p(ptr);                             \
415         case 4:                                                         \
416             return (uint32_t)ldl_ ## END ## _p(ptr);                    \
417         case 8:                                                         \
418             return ldq_ ## END ## _p(ptr);                              \
419         default:                                                        \
420             g_assert_not_reached();                                     \
421         }                                                               \
422     }
423 
424 DO_STN_LDN_P(he)
425 DO_STN_LDN_P(le)
426 DO_STN_LDN_P(be)
427 
428 #undef DO_STN_LDN_P
429 
430 #undef le_bswap
431 #undef be_bswap
432 #undef le_bswaps
433 #undef be_bswaps
434 
435 #endif /* BSWAP_H */
436