]> git.proxmox.com Git - qemu.git/blame - bswap.h
Version 1.0.1
[qemu.git] / bswap.h
CommitLineData
ab93bbe2
FB
1#ifndef BSWAP_H
2#define BSWAP_H
3
4#include "config-host.h"
5
6#include <inttypes.h>
f44cc485 7#include "softfloat.h"
ab93bbe2 8
5735147e 9#ifdef CONFIG_MACHINE_BSWAP_H
1360677c
BS
10#include <sys/endian.h>
11#include <sys/types.h>
12#include <machine/bswap.h>
13#else
14
936dfb80 15#ifdef CONFIG_BYTESWAP_H
ab93bbe2
FB
16#include <byteswap.h>
17#else
18
19#define bswap_16(x) \
20({ \
21 uint16_t __x = (x); \
22 ((uint16_t)( \
23 (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
24 (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
25})
26
27#define bswap_32(x) \
28({ \
29 uint32_t __x = (x); \
30 ((uint32_t)( \
31 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
32 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
33 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
34 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
35})
36
37#define bswap_64(x) \
38({ \
39 uint64_t __x = (x); \
40 ((uint64_t)( \
41 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
42 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
43 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
44 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
45 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
46 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
47 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
48 (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
49})
50
936dfb80 51#endif /* !CONFIG_BYTESWAP_H */
ab93bbe2 52
ab93bbe2
FB
53static inline uint16_t bswap16(uint16_t x)
54{
55 return bswap_16(x);
56}
57
5fafdf24 58static inline uint32_t bswap32(uint32_t x)
ab93bbe2
FB
59{
60 return bswap_32(x);
61}
62
5fafdf24 63static inline uint64_t bswap64(uint64_t x)
ab93bbe2
FB
64{
65 return bswap_64(x);
66}
67
5735147e 68#endif /* ! CONFIG_MACHINE_BSWAP_H */
1360677c 69
ab93bbe2
FB
70static inline void bswap16s(uint16_t *s)
71{
72 *s = bswap16(*s);
73}
74
75static inline void bswap32s(uint32_t *s)
76{
77 *s = bswap32(*s);
78}
79
80static inline void bswap64s(uint64_t *s)
81{
82 *s = bswap64(*s);
83}
84
e2542fe2 85#if defined(HOST_WORDS_BIGENDIAN)
af8ffdfd
FB
86#define be_bswap(v, size) (v)
87#define le_bswap(v, size) bswap ## size(v)
88#define be_bswaps(v, size)
89#define le_bswaps(p, size) *p = bswap ## size(*p);
90#else
91#define le_bswap(v, size) (v)
92#define be_bswap(v, size) bswap ## size(v)
93#define le_bswaps(v, size)
94#define be_bswaps(p, size) *p = bswap ## size(*p);
95#endif
96
97#define CPU_CONVERT(endian, size, type)\
98static inline type endian ## size ## _to_cpu(type v)\
99{\
100 return endian ## _bswap(v, size);\
101}\
102\
103static inline type cpu_to_ ## endian ## size(type v)\
104{\
105 return endian ## _bswap(v, size);\
106}\
107\
108static inline void endian ## size ## _to_cpus(type *p)\
109{\
110 endian ## _bswaps(p, size)\
111}\
112\
113static inline void cpu_to_ ## endian ## size ## s(type *p)\
114{\
115 endian ## _bswaps(p, size)\
116}\
117\
118static inline type endian ## size ## _to_cpup(const type *p)\
119{\
120 return endian ## size ## _to_cpu(*p);\
121}\
122\
123static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
124{\
125 *p = cpu_to_ ## endian ## size(v);\
126}
127
128CPU_CONVERT(be, 16, uint16_t)
129CPU_CONVERT(be, 32, uint32_t)
130CPU_CONVERT(be, 64, uint64_t)
131
132CPU_CONVERT(le, 16, uint16_t)
133CPU_CONVERT(le, 32, uint32_t)
134CPU_CONVERT(le, 64, uint64_t)
135
136/* unaligned versions (optimized for frequent unaligned accesses)*/
137
e58ffeb3 138#if defined(__i386__) || defined(_ARCH_PPC)
af8ffdfd
FB
139
140#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v)
141#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v)
142#define le16_to_cpupu(p) le16_to_cpup(p)
143#define le32_to_cpupu(p) le32_to_cpup(p)
88738c09 144#define be32_to_cpupu(p) be32_to_cpup(p)
af8ffdfd 145
188d8579
FB
146#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
147#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
102c2976 148#define cpu_to_be64wu(p, v) cpu_to_be64w(p, v)
188d8579 149
af8ffdfd
FB
150#else
151
152static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
153{
154 uint8_t *p1 = (uint8_t *)p;
155
9e622b15 156 p1[0] = v & 0xff;
af8ffdfd
FB
157 p1[1] = v >> 8;
158}
159
160static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
161{
162 uint8_t *p1 = (uint8_t *)p;
163
9e622b15 164 p1[0] = v & 0xff;
af8ffdfd
FB
165 p1[1] = v >> 8;
166 p1[2] = v >> 16;
167 p1[3] = v >> 24;
168}
169
170static inline uint16_t le16_to_cpupu(const uint16_t *p)
171{
172 const uint8_t *p1 = (const uint8_t *)p;
173 return p1[0] | (p1[1] << 8);
174}
175
176static inline uint32_t le32_to_cpupu(const uint32_t *p)
177{
178 const uint8_t *p1 = (const uint8_t *)p;
179 return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
180}
181
88738c09
AJ
182static inline uint32_t be32_to_cpupu(const uint32_t *p)
183{
184 const uint8_t *p1 = (const uint8_t *)p;
185 return p1[3] | (p1[2] << 8) | (p1[1] << 16) | (p1[0] << 24);
186}
187
188d8579
FB
188static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
189{
190 uint8_t *p1 = (uint8_t *)p;
191
192 p1[0] = v >> 8;
9e622b15 193 p1[1] = v & 0xff;
188d8579
FB
194}
195
196static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
197{
198 uint8_t *p1 = (uint8_t *)p;
199
200 p1[0] = v >> 24;
201 p1[1] = v >> 16;
202 p1[2] = v >> 8;
9e622b15 203 p1[3] = v & 0xff;
188d8579
FB
204}
205
102c2976
AJ
206static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
207{
208 uint8_t *p1 = (uint8_t *)p;
209
210 p1[0] = v >> 56;
211 p1[1] = v >> 48;
212 p1[2] = v >> 40;
213 p1[3] = v >> 32;
214 p1[4] = v >> 24;
215 p1[5] = v >> 16;
216 p1[6] = v >> 8;
217 p1[7] = v & 0xff;
218}
219
188d8579
FB
220#endif
221
e2542fe2 222#ifdef HOST_WORDS_BIGENDIAN
188d8579 223#define cpu_to_32wu cpu_to_be32wu
17e6a53f 224#define leul_to_cpu(v) glue(glue(le,HOST_LONG_BITS),_to_cpu)(v)
188d8579
FB
225#else
226#define cpu_to_32wu cpu_to_le32wu
213acd2e 227#define leul_to_cpu(v) (v)
af8ffdfd
FB
228#endif
229
230#undef le_bswap
231#undef be_bswap
232#undef le_bswaps
233#undef be_bswaps
234
e73d6e3a
MT
235/* len must be one of 1, 2, 4 */
236static inline uint32_t qemu_bswap_len(uint32_t value, int len)
237{
238 return bswap32(value) >> (32 - 8 * len);
239}
240
cbbab922
PB
241typedef union {
242 float32 f;
243 uint32_t l;
244} CPU_FloatU;
245
246typedef union {
247 float64 d;
248#if defined(HOST_WORDS_BIGENDIAN)
249 struct {
250 uint32_t upper;
251 uint32_t lower;
252 } l;
253#else
254 struct {
255 uint32_t lower;
256 uint32_t upper;
257 } l;
258#endif
259 uint64_t ll;
260} CPU_DoubleU;
261
262typedef union {
263 floatx80 d;
264 struct {
265 uint64_t lower;
266 uint16_t upper;
267 } l;
268} CPU_LDoubleU;
269
270typedef union {
271 float128 q;
272#if defined(HOST_WORDS_BIGENDIAN)
273 struct {
274 uint32_t upmost;
275 uint32_t upper;
276 uint32_t lower;
277 uint32_t lowest;
278 } l;
279 struct {
280 uint64_t upper;
281 uint64_t lower;
282 } ll;
283#else
284 struct {
285 uint32_t lowest;
286 uint32_t lower;
287 uint32_t upper;
288 uint32_t upmost;
289 } l;
290 struct {
291 uint64_t lower;
292 uint64_t upper;
293 } ll;
294#endif
295} CPU_QuadU;
296
297/* unaligned/endian-independent pointer access */
298
299/*
300 * the generic syntax is:
301 *
302 * load: ld{type}{sign}{size}{endian}_p(ptr)
303 *
304 * store: st{type}{size}{endian}_p(ptr, val)
305 *
306 * Note there are small differences with the softmmu access API!
307 *
308 * type is:
309 * (empty): integer access
310 * f : float access
311 *
312 * sign is:
313 * (empty): for floats or 32 bit size
314 * u : unsigned
315 * s : signed
316 *
317 * size is:
318 * b: 8 bits
319 * w: 16 bits
320 * l: 32 bits
321 * q: 64 bits
322 *
323 * endian is:
324 * (empty): 8 bit access
325 * be : big endian
326 * le : little endian
327 */
328static inline int ldub_p(const void *ptr)
329{
330 return *(uint8_t *)ptr;
331}
332
333static inline int ldsb_p(const void *ptr)
334{
335 return *(int8_t *)ptr;
336}
337
338static inline void stb_p(void *ptr, int v)
339{
340 *(uint8_t *)ptr = v;
341}
342
343/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
344 kernel handles unaligned load/stores may give better results, but
345 it is a system wide setting : bad */
346#if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
347
348/* conservative code for little endian unaligned accesses */
349static inline int lduw_le_p(const void *ptr)
350{
351#ifdef _ARCH_PPC
352 int val;
353 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
354 return val;
355#else
356 const uint8_t *p = ptr;
357 return p[0] | (p[1] << 8);
358#endif
359}
360
361static inline int ldsw_le_p(const void *ptr)
362{
363#ifdef _ARCH_PPC
364 int val;
365 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
366 return (int16_t)val;
367#else
368 const uint8_t *p = ptr;
369 return (int16_t)(p[0] | (p[1] << 8));
370#endif
371}
372
373static inline int ldl_le_p(const void *ptr)
374{
375#ifdef _ARCH_PPC
376 int val;
377 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
378 return val;
379#else
380 const uint8_t *p = ptr;
381 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
382#endif
383}
384
385static inline uint64_t ldq_le_p(const void *ptr)
386{
387 const uint8_t *p = ptr;
388 uint32_t v1, v2;
389 v1 = ldl_le_p(p);
390 v2 = ldl_le_p(p + 4);
391 return v1 | ((uint64_t)v2 << 32);
392}
393
394static inline void stw_le_p(void *ptr, int v)
395{
396#ifdef _ARCH_PPC
397 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
398#else
399 uint8_t *p = ptr;
400 p[0] = v;
401 p[1] = v >> 8;
402#endif
403}
404
405static inline void stl_le_p(void *ptr, int v)
406{
407#ifdef _ARCH_PPC
408 __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
409#else
410 uint8_t *p = ptr;
411 p[0] = v;
412 p[1] = v >> 8;
413 p[2] = v >> 16;
414 p[3] = v >> 24;
415#endif
416}
417
418static inline void stq_le_p(void *ptr, uint64_t v)
419{
420 uint8_t *p = ptr;
421 stl_le_p(p, (uint32_t)v);
422 stl_le_p(p + 4, v >> 32);
423}
424
425/* float access */
426
427static inline float32 ldfl_le_p(const void *ptr)
428{
429 union {
430 float32 f;
431 uint32_t i;
432 } u;
433 u.i = ldl_le_p(ptr);
434 return u.f;
435}
436
437static inline void stfl_le_p(void *ptr, float32 v)
438{
439 union {
440 float32 f;
441 uint32_t i;
442 } u;
443 u.f = v;
444 stl_le_p(ptr, u.i);
445}
446
447static inline float64 ldfq_le_p(const void *ptr)
448{
449 CPU_DoubleU u;
450 u.l.lower = ldl_le_p(ptr);
451 u.l.upper = ldl_le_p(ptr + 4);
452 return u.d;
453}
454
455static inline void stfq_le_p(void *ptr, float64 v)
456{
457 CPU_DoubleU u;
458 u.d = v;
459 stl_le_p(ptr, u.l.lower);
460 stl_le_p(ptr + 4, u.l.upper);
461}
462
463#else
464
465static inline int lduw_le_p(const void *ptr)
466{
467 return *(uint16_t *)ptr;
468}
469
470static inline int ldsw_le_p(const void *ptr)
471{
472 return *(int16_t *)ptr;
473}
474
475static inline int ldl_le_p(const void *ptr)
476{
477 return *(uint32_t *)ptr;
478}
479
480static inline uint64_t ldq_le_p(const void *ptr)
481{
482 return *(uint64_t *)ptr;
483}
484
485static inline void stw_le_p(void *ptr, int v)
486{
487 *(uint16_t *)ptr = v;
488}
489
490static inline void stl_le_p(void *ptr, int v)
491{
492 *(uint32_t *)ptr = v;
493}
494
495static inline void stq_le_p(void *ptr, uint64_t v)
496{
497 *(uint64_t *)ptr = v;
498}
499
500/* float access */
501
502static inline float32 ldfl_le_p(const void *ptr)
503{
504 return *(float32 *)ptr;
505}
506
507static inline float64 ldfq_le_p(const void *ptr)
508{
509 return *(float64 *)ptr;
510}
511
512static inline void stfl_le_p(void *ptr, float32 v)
513{
514 *(float32 *)ptr = v;
515}
516
517static inline void stfq_le_p(void *ptr, float64 v)
518{
519 *(float64 *)ptr = v;
520}
521#endif
522
523#if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
524
525static inline int lduw_be_p(const void *ptr)
526{
527#if defined(__i386__)
528 int val;
529 asm volatile ("movzwl %1, %0\n"
530 "xchgb %b0, %h0\n"
531 : "=q" (val)
532 : "m" (*(uint16_t *)ptr));
533 return val;
534#else
535 const uint8_t *b = ptr;
536 return ((b[0] << 8) | b[1]);
537#endif
538}
539
540static inline int ldsw_be_p(const void *ptr)
541{
542#if defined(__i386__)
543 int val;
544 asm volatile ("movzwl %1, %0\n"
545 "xchgb %b0, %h0\n"
546 : "=q" (val)
547 : "m" (*(uint16_t *)ptr));
548 return (int16_t)val;
549#else
550 const uint8_t *b = ptr;
551 return (int16_t)((b[0] << 8) | b[1]);
552#endif
553}
554
555static inline int ldl_be_p(const void *ptr)
556{
557#if defined(__i386__) || defined(__x86_64__)
558 int val;
559 asm volatile ("movl %1, %0\n"
560 "bswap %0\n"
561 : "=r" (val)
562 : "m" (*(uint32_t *)ptr));
563 return val;
564#else
565 const uint8_t *b = ptr;
566 return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
567#endif
568}
569
570static inline uint64_t ldq_be_p(const void *ptr)
571{
572 uint32_t a,b;
573 a = ldl_be_p(ptr);
574 b = ldl_be_p((uint8_t *)ptr + 4);
575 return (((uint64_t)a<<32)|b);
576}
577
578static inline void stw_be_p(void *ptr, int v)
579{
580#if defined(__i386__)
581 asm volatile ("xchgb %b0, %h0\n"
582 "movw %w0, %1\n"
583 : "=q" (v)
584 : "m" (*(uint16_t *)ptr), "0" (v));
585#else
586 uint8_t *d = (uint8_t *) ptr;
587 d[0] = v >> 8;
588 d[1] = v;
589#endif
590}
591
592static inline void stl_be_p(void *ptr, int v)
593{
594#if defined(__i386__) || defined(__x86_64__)
595 asm volatile ("bswap %0\n"
596 "movl %0, %1\n"
597 : "=r" (v)
598 : "m" (*(uint32_t *)ptr), "0" (v));
599#else
600 uint8_t *d = (uint8_t *) ptr;
601 d[0] = v >> 24;
602 d[1] = v >> 16;
603 d[2] = v >> 8;
604 d[3] = v;
605#endif
606}
607
608static inline void stq_be_p(void *ptr, uint64_t v)
609{
610 stl_be_p(ptr, v >> 32);
611 stl_be_p((uint8_t *)ptr + 4, v);
612}
613
614/* float access */
615
616static inline float32 ldfl_be_p(const void *ptr)
617{
618 union {
619 float32 f;
620 uint32_t i;
621 } u;
622 u.i = ldl_be_p(ptr);
623 return u.f;
624}
625
626static inline void stfl_be_p(void *ptr, float32 v)
627{
628 union {
629 float32 f;
630 uint32_t i;
631 } u;
632 u.f = v;
633 stl_be_p(ptr, u.i);
634}
635
636static inline float64 ldfq_be_p(const void *ptr)
637{
638 CPU_DoubleU u;
639 u.l.upper = ldl_be_p(ptr);
640 u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
641 return u.d;
642}
643
644static inline void stfq_be_p(void *ptr, float64 v)
645{
646 CPU_DoubleU u;
647 u.d = v;
648 stl_be_p(ptr, u.l.upper);
649 stl_be_p((uint8_t *)ptr + 4, u.l.lower);
650}
651
652#else
653
654static inline int lduw_be_p(const void *ptr)
655{
656 return *(uint16_t *)ptr;
657}
658
659static inline int ldsw_be_p(const void *ptr)
660{
661 return *(int16_t *)ptr;
662}
663
664static inline int ldl_be_p(const void *ptr)
665{
666 return *(uint32_t *)ptr;
667}
668
669static inline uint64_t ldq_be_p(const void *ptr)
670{
671 return *(uint64_t *)ptr;
672}
673
674static inline void stw_be_p(void *ptr, int v)
675{
676 *(uint16_t *)ptr = v;
677}
678
679static inline void stl_be_p(void *ptr, int v)
680{
681 *(uint32_t *)ptr = v;
682}
683
684static inline void stq_be_p(void *ptr, uint64_t v)
685{
686 *(uint64_t *)ptr = v;
687}
688
689/* float access */
690
691static inline float32 ldfl_be_p(const void *ptr)
692{
693 return *(float32 *)ptr;
694}
695
696static inline float64 ldfq_be_p(const void *ptr)
697{
698 return *(float64 *)ptr;
699}
700
701static inline void stfl_be_p(void *ptr, float32 v)
702{
703 *(float32 *)ptr = v;
704}
705
706static inline void stfq_be_p(void *ptr, float64 v)
707{
708 *(float64 *)ptr = v;
709}
710
711#endif
712
ab93bbe2 713#endif /* BSWAP_H */