]> git.proxmox.com Git - qemu.git/blame - include/qemu/bswap.h
bswap.h: Remove le16_to_cpupu()
[qemu.git] / include / qemu / bswap.h
CommitLineData
ab93bbe2
FB
1#ifndef BSWAP_H
2#define BSWAP_H
3
4#include "config-host.h"
ab93bbe2 5#include <inttypes.h>
91107fdf 6#include <limits.h>
ea44910e 7#include <string.h>
6b4c305c 8#include "fpu/softfloat.h"
ab93bbe2 9
5735147e 10#ifdef CONFIG_MACHINE_BSWAP_H
cdfe2851
RH
11# include <sys/endian.h>
12# include <sys/types.h>
13# include <machine/bswap.h>
14#elif defined(CONFIG_BYTESWAP_H)
15# include <byteswap.h>
ab93bbe2 16
ab93bbe2
FB
17static inline uint16_t bswap16(uint16_t x)
18{
19 return bswap_16(x);
20}
21
5fafdf24 22static inline uint32_t bswap32(uint32_t x)
ab93bbe2
FB
23{
24 return bswap_32(x);
25}
26
5fafdf24 27static inline uint64_t bswap64(uint64_t x)
ab93bbe2
FB
28{
29 return bswap_64(x);
30}
cdfe2851
RH
31# else
32static inline uint16_t bswap16(uint16_t x)
33{
34 return (((x & 0x00ff) << 8) |
35 ((x & 0xff00) >> 8));
36}
ab93bbe2 37
cdfe2851
RH
38static inline uint32_t bswap32(uint32_t x)
39{
40 return (((x & 0x000000ffU) << 24) |
41 ((x & 0x0000ff00U) << 8) |
42 ((x & 0x00ff0000U) >> 8) |
43 ((x & 0xff000000U) >> 24));
44}
45
46static inline uint64_t bswap64(uint64_t x)
47{
48 return (((x & 0x00000000000000ffULL) << 56) |
49 ((x & 0x000000000000ff00ULL) << 40) |
50 ((x & 0x0000000000ff0000ULL) << 24) |
51 ((x & 0x00000000ff000000ULL) << 8) |
52 ((x & 0x000000ff00000000ULL) >> 8) |
53 ((x & 0x0000ff0000000000ULL) >> 24) |
54 ((x & 0x00ff000000000000ULL) >> 40) |
55 ((x & 0xff00000000000000ULL) >> 56));
56}
5735147e 57#endif /* ! CONFIG_MACHINE_BSWAP_H */
1360677c 58
ab93bbe2
FB
59static inline void bswap16s(uint16_t *s)
60{
61 *s = bswap16(*s);
62}
63
64static inline void bswap32s(uint32_t *s)
65{
66 *s = bswap32(*s);
67}
68
69static inline void bswap64s(uint64_t *s)
70{
71 *s = bswap64(*s);
72}
73
e2542fe2 74#if defined(HOST_WORDS_BIGENDIAN)
af8ffdfd 75#define be_bswap(v, size) (v)
a4cbfe24 76#define le_bswap(v, size) glue(bswap, size)(v)
af8ffdfd 77#define be_bswaps(v, size)
a4cbfe24 78#define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
af8ffdfd
FB
79#else
80#define le_bswap(v, size) (v)
a4cbfe24 81#define be_bswap(v, size) glue(bswap, size)(v)
af8ffdfd 82#define le_bswaps(v, size)
a4cbfe24 83#define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
af8ffdfd
FB
84#endif
85
86#define CPU_CONVERT(endian, size, type)\
87static inline type endian ## size ## _to_cpu(type v)\
88{\
a4cbfe24 89 return glue(endian, _bswap)(v, size);\
af8ffdfd
FB
90}\
91\
92static inline type cpu_to_ ## endian ## size(type v)\
93{\
a4cbfe24 94 return glue(endian, _bswap)(v, size);\
af8ffdfd
FB
95}\
96\
97static inline void endian ## size ## _to_cpus(type *p)\
98{\
a4cbfe24 99 glue(endian, _bswaps)(p, size);\
af8ffdfd
FB
100}\
101\
102static inline void cpu_to_ ## endian ## size ## s(type *p)\
103{\
a4cbfe24 104 glue(endian, _bswaps)(p, size);\
af8ffdfd
FB
105}\
106\
107static inline type endian ## size ## _to_cpup(const type *p)\
108{\
a4cbfe24 109 return glue(glue(endian, size), _to_cpu)(*p);\
af8ffdfd
FB
110}\
111\
112static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
113{\
a4cbfe24 114 *p = glue(glue(cpu_to_, endian), size)(v);\
af8ffdfd
FB
115}
116
117CPU_CONVERT(be, 16, uint16_t)
118CPU_CONVERT(be, 32, uint32_t)
119CPU_CONVERT(be, 64, uint64_t)
120
121CPU_CONVERT(le, 16, uint16_t)
122CPU_CONVERT(le, 32, uint32_t)
123CPU_CONVERT(le, 64, uint64_t)
124
e73d6e3a
MT
125/* len must be one of 1, 2, 4 */
126static inline uint32_t qemu_bswap_len(uint32_t value, int len)
127{
128 return bswap32(value) >> (32 - 8 * len);
129}
130
7db2145a
RH
131/* Unions for reinterpreting between floats and integers. */
132
cbbab922
PB
133typedef union {
134 float32 f;
135 uint32_t l;
136} CPU_FloatU;
137
138typedef union {
139 float64 d;
140#if defined(HOST_WORDS_BIGENDIAN)
141 struct {
142 uint32_t upper;
143 uint32_t lower;
144 } l;
145#else
146 struct {
147 uint32_t lower;
148 uint32_t upper;
149 } l;
150#endif
151 uint64_t ll;
152} CPU_DoubleU;
153
154typedef union {
155 floatx80 d;
156 struct {
157 uint64_t lower;
158 uint16_t upper;
159 } l;
160} CPU_LDoubleU;
161
162typedef union {
163 float128 q;
164#if defined(HOST_WORDS_BIGENDIAN)
165 struct {
166 uint32_t upmost;
167 uint32_t upper;
168 uint32_t lower;
169 uint32_t lowest;
170 } l;
171 struct {
172 uint64_t upper;
173 uint64_t lower;
174 } ll;
175#else
176 struct {
177 uint32_t lowest;
178 uint32_t lower;
179 uint32_t upper;
180 uint32_t upmost;
181 } l;
182 struct {
183 uint64_t lower;
184 uint64_t upper;
185 } ll;
186#endif
187} CPU_QuadU;
188
189/* unaligned/endian-independent pointer access */
190
191/*
192 * the generic syntax is:
193 *
194 * load: ld{type}{sign}{size}{endian}_p(ptr)
195 *
196 * store: st{type}{size}{endian}_p(ptr, val)
197 *
198 * Note there are small differences with the softmmu access API!
199 *
200 * type is:
201 * (empty): integer access
202 * f : float access
203 *
204 * sign is:
205 * (empty): for floats or 32 bit size
206 * u : unsigned
207 * s : signed
208 *
209 * size is:
210 * b: 8 bits
211 * w: 16 bits
212 * l: 32 bits
213 * q: 64 bits
214 *
215 * endian is:
7db2145a 216 * (empty): host endian
cbbab922
PB
217 * be : big endian
218 * le : little endian
219 */
c732a52d 220
cbbab922
PB
221static inline int ldub_p(const void *ptr)
222{
223 return *(uint8_t *)ptr;
224}
225
226static inline int ldsb_p(const void *ptr)
227{
228 return *(int8_t *)ptr;
229}
230
231static inline void stb_p(void *ptr, int v)
232{
233 *(uint8_t *)ptr = v;
234}
235
7db2145a
RH
236/* Any compiler worth its salt will turn these memcpy into native unaligned
237 operations. Thus we don't need to play games with packed attributes, or
238 inline byte-by-byte stores. */
239
240static inline int lduw_p(const void *ptr)
241{
242 uint16_t r;
243 memcpy(&r, ptr, sizeof(r));
244 return r;
245}
246
247static inline int ldsw_p(const void *ptr)
248{
249 int16_t r;
250 memcpy(&r, ptr, sizeof(r));
251 return r;
252}
253
254static inline void stw_p(void *ptr, uint16_t v)
255{
256 memcpy(ptr, &v, sizeof(v));
257}
258
259static inline int ldl_p(const void *ptr)
260{
261 int32_t r;
262 memcpy(&r, ptr, sizeof(r));
263 return r;
264}
265
266static inline void stl_p(void *ptr, uint32_t v)
267{
268 memcpy(ptr, &v, sizeof(v));
269}
270
271static inline uint64_t ldq_p(const void *ptr)
272{
273 uint64_t r;
274 memcpy(&r, ptr, sizeof(r));
275 return r;
276}
277
278static inline void stq_p(void *ptr, uint64_t v)
279{
280 memcpy(ptr, &v, sizeof(v));
281}
282
cbbab922
PB
283static inline int lduw_le_p(const void *ptr)
284{
612d590e 285 return (uint16_t)le_bswap(lduw_p(ptr), 16);
cbbab922
PB
286}
287
288static inline int ldsw_le_p(const void *ptr)
289{
612d590e 290 return (int16_t)le_bswap(lduw_p(ptr), 16);
cbbab922
PB
291}
292
293static inline int ldl_le_p(const void *ptr)
294{
612d590e 295 return le_bswap(ldl_p(ptr), 32);
cbbab922
PB
296}
297
298static inline uint64_t ldq_le_p(const void *ptr)
299{
612d590e 300 return le_bswap(ldq_p(ptr), 64);
cbbab922
PB
301}
302
303static inline void stw_le_p(void *ptr, int v)
304{
612d590e 305 stw_p(ptr, le_bswap(v, 16));
cbbab922
PB
306}
307
308static inline void stl_le_p(void *ptr, int v)
309{
612d590e 310 stl_p(ptr, le_bswap(v, 32));
cbbab922
PB
311}
312
313static inline void stq_le_p(void *ptr, uint64_t v)
314{
612d590e 315 stq_p(ptr, le_bswap(v, 64));
cbbab922
PB
316}
317
318/* float access */
319
320static inline float32 ldfl_le_p(const void *ptr)
321{
612d590e
RH
322 CPU_FloatU u;
323 u.l = ldl_le_p(ptr);
cbbab922
PB
324 return u.f;
325}
326
327static inline void stfl_le_p(void *ptr, float32 v)
328{
612d590e 329 CPU_FloatU u;
cbbab922 330 u.f = v;
612d590e 331 stl_le_p(ptr, u.l);
cbbab922
PB
332}
333
334static inline float64 ldfq_le_p(const void *ptr)
335{
336 CPU_DoubleU u;
612d590e 337 u.ll = ldq_le_p(ptr);
cbbab922
PB
338 return u.d;
339}
340
341static inline void stfq_le_p(void *ptr, float64 v)
342{
343 CPU_DoubleU u;
344 u.d = v;
612d590e 345 stq_le_p(ptr, u.ll);
cbbab922
PB
346}
347
cbbab922
PB
348static inline int lduw_be_p(const void *ptr)
349{
612d590e 350 return (uint16_t)be_bswap(lduw_p(ptr), 16);
cbbab922
PB
351}
352
353static inline int ldsw_be_p(const void *ptr)
354{
612d590e 355 return (int16_t)be_bswap(lduw_p(ptr), 16);
cbbab922
PB
356}
357
358static inline int ldl_be_p(const void *ptr)
359{
612d590e 360 return be_bswap(ldl_p(ptr), 32);
cbbab922
PB
361}
362
363static inline uint64_t ldq_be_p(const void *ptr)
364{
612d590e 365 return be_bswap(ldq_p(ptr), 64);
cbbab922
PB
366}
367
368static inline void stw_be_p(void *ptr, int v)
369{
612d590e 370 stw_p(ptr, be_bswap(v, 16));
cbbab922
PB
371}
372
373static inline void stl_be_p(void *ptr, int v)
374{
612d590e 375 stl_p(ptr, be_bswap(v, 32));
cbbab922
PB
376}
377
378static inline void stq_be_p(void *ptr, uint64_t v)
379{
612d590e 380 stq_p(ptr, be_bswap(v, 64));
cbbab922
PB
381}
382
383/* float access */
384
385static inline float32 ldfl_be_p(const void *ptr)
386{
612d590e
RH
387 CPU_FloatU u;
388 u.l = ldl_be_p(ptr);
cbbab922
PB
389 return u.f;
390}
391
392static inline void stfl_be_p(void *ptr, float32 v)
393{
612d590e 394 CPU_FloatU u;
cbbab922 395 u.f = v;
612d590e 396 stl_be_p(ptr, u.l);
cbbab922
PB
397}
398
399static inline float64 ldfq_be_p(const void *ptr)
400{
401 CPU_DoubleU u;
612d590e 402 u.ll = ldq_be_p(ptr);
cbbab922
PB
403 return u.d;
404}
405
406static inline void stfq_be_p(void *ptr, float64 v)
407{
408 CPU_DoubleU u;
409 u.d = v;
612d590e 410 stq_be_p(ptr, u.ll);
cbbab922
PB
411}
412
c732a52d
RH
413/* Legacy unaligned versions. Note that we never had a complete set. */
414
c732a52d
RH
415static inline uint32_t le32_to_cpupu(const uint32_t *p)
416{
417 return ldl_le_p(p);
418}
419
420static inline uint32_t be32_to_cpupu(const uint32_t *p)
421{
422 return ldl_be_p(p);
423}
424
425static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
426{
427 stw_be_p(p, v);
428}
429
430static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
431{
432 stl_be_p(p, v);
433}
434
435static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
436{
437 stq_be_p(p, v);
438}
439
440static inline void cpu_to_32wu(uint32_t *p, uint32_t v)
441{
442 stl_p(p, v);
443}
444
445static inline unsigned long leul_to_cpu(unsigned long v)
446{
91107fdf
RH
447 /* In order to break an include loop between here and
448 qemu-common.h, don't rely on HOST_LONG_BITS. */
449#if ULONG_MAX == UINT32_MAX
450 return le_bswap(v, 32);
451#elif ULONG_MAX == UINT64_MAX
452 return le_bswap(v, 64);
453#else
454# error Unknown sizeof long
455#endif
c732a52d
RH
456}
457
612d590e
RH
458#undef le_bswap
459#undef be_bswap
460#undef le_bswaps
461#undef be_bswaps
cbbab922 462
ab93bbe2 463#endif /* BSWAP_H */