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