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