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