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