xref: /qemu/include/qemu/bswap.h (revision 5ac034b1)
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}, 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_le32(_x)                          \
134     ((((_x) & 0x000000ffU) << 24) |              \
135      (((_x) & 0x0000ff00U) <<  8) |              \
136      (((_x) & 0x00ff0000U) >>  8) |              \
137      (((_x) & 0xff000000U) >> 24))
138 # define const_le16(_x)                          \
139     ((((_x) & 0x00ff) << 8) |                    \
140      (((_x) & 0xff00) >> 8))
141 #else
142 # define const_le32(_x) (_x)
143 # define const_le16(_x) (_x)
144 #endif
145 
146 /* unaligned/endian-independent pointer access */
147 
148 /*
149  * the generic syntax is:
150  *
151  * load: ld{type}{sign}{size}_{endian}_p(ptr)
152  *
153  * store: st{type}{size}_{endian}_p(ptr, val)
154  *
155  * Note there are small differences with the softmmu access API!
156  *
157  * type is:
158  * (empty): integer access
159  *   f    : float access
160  *
161  * sign is:
162  * (empty): for 32 or 64 bit sizes (including floats and doubles)
163  *   u    : unsigned
164  *   s    : signed
165  *
166  * size is:
167  *   b: 8 bits
168  *   w: 16 bits
169  *   l: 32 bits
170  *   q: 64 bits
171  *
172  * endian is:
173  *   he   : host endian
174  *   be   : big endian
175  *   le   : little endian
176  *   te   : target endian
177  * (except for byte accesses, which have no endian infix).
178  *
179  * The target endian accessors are obviously only available to source
180  * files which are built per-target; they are defined in cpu-all.h.
181  *
182  * In all cases these functions take a host pointer.
183  * For accessors that take a guest address rather than a
184  * host address, see the cpu_{ld,st}_* accessors defined in
185  * cpu_ldst.h.
186  *
187  * For cases where the size to be used is not fixed at compile time,
188  * there are
189  *  stn_{endian}_p(ptr, sz, val)
190  * which stores @val to @ptr as an @endian-order number @sz bytes in size
191  * and
192  *  ldn_{endian}_p(ptr, sz)
193  * which loads @sz bytes from @ptr as an unsigned @endian-order number
194  * and returns it in a uint64_t.
195  */
196 
197 static inline int ldub_p(const void *ptr)
198 {
199     return *(uint8_t *)ptr;
200 }
201 
202 static inline int ldsb_p(const void *ptr)
203 {
204     return *(int8_t *)ptr;
205 }
206 
207 static inline void stb_p(void *ptr, uint8_t v)
208 {
209     *(uint8_t *)ptr = v;
210 }
211 
212 /*
213  * Any compiler worth its salt will turn these memcpy into native unaligned
214  * operations.  Thus we don't need to play games with packed attributes, or
215  * inline byte-by-byte stores.
216  * Some compilation environments (eg some fortify-source implementations)
217  * may intercept memcpy() in a way that defeats the compiler optimization,
218  * though, so we use __builtin_memcpy() to give ourselves the best chance
219  * of good performance.
220  */
221 
222 static inline int lduw_he_p(const void *ptr)
223 {
224     uint16_t r;
225     __builtin_memcpy(&r, ptr, sizeof(r));
226     return r;
227 }
228 
229 static inline int ldsw_he_p(const void *ptr)
230 {
231     int16_t r;
232     __builtin_memcpy(&r, ptr, sizeof(r));
233     return r;
234 }
235 
236 static inline void stw_he_p(void *ptr, uint16_t v)
237 {
238     __builtin_memcpy(ptr, &v, sizeof(v));
239 }
240 
241 static inline int ldl_he_p(const void *ptr)
242 {
243     int32_t r;
244     __builtin_memcpy(&r, ptr, sizeof(r));
245     return r;
246 }
247 
248 static inline void stl_he_p(void *ptr, uint32_t v)
249 {
250     __builtin_memcpy(ptr, &v, sizeof(v));
251 }
252 
253 static inline uint64_t ldq_he_p(const void *ptr)
254 {
255     uint64_t r;
256     __builtin_memcpy(&r, ptr, sizeof(r));
257     return r;
258 }
259 
260 static inline void stq_he_p(void *ptr, uint64_t v)
261 {
262     __builtin_memcpy(ptr, &v, sizeof(v));
263 }
264 
265 static inline int lduw_le_p(const void *ptr)
266 {
267     return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
268 }
269 
270 static inline int ldsw_le_p(const void *ptr)
271 {
272     return (int16_t)le_bswap(lduw_he_p(ptr), 16);
273 }
274 
275 static inline int ldl_le_p(const void *ptr)
276 {
277     return le_bswap(ldl_he_p(ptr), 32);
278 }
279 
280 static inline uint64_t ldq_le_p(const void *ptr)
281 {
282     return le_bswap(ldq_he_p(ptr), 64);
283 }
284 
285 static inline void stw_le_p(void *ptr, uint16_t v)
286 {
287     stw_he_p(ptr, le_bswap(v, 16));
288 }
289 
290 static inline void stl_le_p(void *ptr, uint32_t v)
291 {
292     stl_he_p(ptr, le_bswap(v, 32));
293 }
294 
295 static inline void stq_le_p(void *ptr, uint64_t v)
296 {
297     stq_he_p(ptr, le_bswap(v, 64));
298 }
299 
300 static inline int lduw_be_p(const void *ptr)
301 {
302     return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
303 }
304 
305 static inline int ldsw_be_p(const void *ptr)
306 {
307     return (int16_t)be_bswap(lduw_he_p(ptr), 16);
308 }
309 
310 static inline int ldl_be_p(const void *ptr)
311 {
312     return be_bswap(ldl_he_p(ptr), 32);
313 }
314 
315 static inline uint64_t ldq_be_p(const void *ptr)
316 {
317     return be_bswap(ldq_he_p(ptr), 64);
318 }
319 
320 static inline void stw_be_p(void *ptr, uint16_t v)
321 {
322     stw_he_p(ptr, be_bswap(v, 16));
323 }
324 
325 static inline void stl_be_p(void *ptr, uint32_t v)
326 {
327     stl_he_p(ptr, be_bswap(v, 32));
328 }
329 
330 static inline void stq_be_p(void *ptr, uint64_t v)
331 {
332     stq_he_p(ptr, be_bswap(v, 64));
333 }
334 
335 static inline unsigned long leul_to_cpu(unsigned long v)
336 {
337 #if HOST_LONG_BITS == 32
338     return le_bswap(v, 32);
339 #elif HOST_LONG_BITS == 64
340     return le_bswap(v, 64);
341 #else
342 # error Unknown sizeof long
343 #endif
344 }
345 
346 /* Store v to p as a sz byte value in host order */
347 #define DO_STN_LDN_P(END) \
348     static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v)  \
349     {                                                                   \
350         switch (sz) {                                                   \
351         case 1:                                                         \
352             stb_p(ptr, v);                                              \
353             break;                                                      \
354         case 2:                                                         \
355             stw_ ## END ## _p(ptr, v);                                  \
356             break;                                                      \
357         case 4:                                                         \
358             stl_ ## END ## _p(ptr, v);                                  \
359             break;                                                      \
360         case 8:                                                         \
361             stq_ ## END ## _p(ptr, v);                                  \
362             break;                                                      \
363         default:                                                        \
364             g_assert_not_reached();                                     \
365         }                                                               \
366     }                                                                   \
367     static inline uint64_t ldn_## END ## _p(const void *ptr, int sz)    \
368     {                                                                   \
369         switch (sz) {                                                   \
370         case 1:                                                         \
371             return ldub_p(ptr);                                         \
372         case 2:                                                         \
373             return lduw_ ## END ## _p(ptr);                             \
374         case 4:                                                         \
375             return (uint32_t)ldl_ ## END ## _p(ptr);                    \
376         case 8:                                                         \
377             return ldq_ ## END ## _p(ptr);                              \
378         default:                                                        \
379             g_assert_not_reached();                                     \
380         }                                                               \
381     }
382 
383 DO_STN_LDN_P(he)
384 DO_STN_LDN_P(le)
385 DO_STN_LDN_P(be)
386 
387 #undef DO_STN_LDN_P
388 
389 #undef le_bswap
390 #undef be_bswap
391 #undef le_bswaps
392 #undef be_bswaps
393 
394 #endif /* BSWAP_H */
395