4 #include "config-host.h"
9 #ifdef CONFIG_MACHINE_BSWAP_H
10 #include <sys/endian.h>
11 #include <sys/types.h>
12 #include <machine/bswap.h>
15 #ifdef CONFIG_BYTESWAP_H
23 (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
24 (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
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) )); \
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) )); \
51 #endif /* !CONFIG_BYTESWAP_H */
53 static inline uint16_t bswap16(uint16_t x
)
58 static inline uint32_t bswap32(uint32_t x
)
63 static inline uint64_t bswap64(uint64_t x
)
68 #endif /* ! CONFIG_MACHINE_BSWAP_H */
70 static inline void bswap16s(uint16_t *s
)
75 static inline void bswap32s(uint32_t *s
)
80 static inline void bswap64s(uint64_t *s
)
85 #if defined(HOST_WORDS_BIGENDIAN)
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);
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);
97 #define CPU_CONVERT(endian, size, type)\
98 static inline type endian ## size ## _to_cpu(type v)\
100 return endian ## _bswap(v, size);\
103 static inline type cpu_to_ ## endian ## size(type v)\
105 return endian ## _bswap(v, size);\
108 static inline void endian ## size ## _to_cpus(type *p)\
110 endian ## _bswaps(p, size)\
113 static inline void cpu_to_ ## endian ## size ## s(type *p)\
115 endian ## _bswaps(p, size)\
118 static inline type endian ## size ## _to_cpup(const type *p)\
120 return endian ## size ## _to_cpu(*p);\
123 static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
125 *p = cpu_to_ ## endian ## size(v);\
128 CPU_CONVERT(be
, 16, uint16_t)
129 CPU_CONVERT(be
, 32, uint32_t)
130 CPU_CONVERT(be
, 64, uint64_t)
132 CPU_CONVERT(le
, 16, uint16_t)
133 CPU_CONVERT(le
, 32, uint32_t)
134 CPU_CONVERT(le
, 64, uint64_t)
136 /* unaligned versions (optimized for frequent unaligned accesses)*/
138 #if defined(__i386__) || defined(_ARCH_PPC)
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)
144 #define be32_to_cpupu(p) be32_to_cpup(p)
146 #define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
147 #define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
148 #define cpu_to_be64wu(p, v) cpu_to_be64w(p, v)
152 static inline void cpu_to_le16wu(uint16_t *p
, uint16_t v
)
154 uint8_t *p1
= (uint8_t *)p
;
160 static inline void cpu_to_le32wu(uint32_t *p
, uint32_t v
)
162 uint8_t *p1
= (uint8_t *)p
;
170 static inline uint16_t le16_to_cpupu(const uint16_t *p
)
172 const uint8_t *p1
= (const uint8_t *)p
;
173 return p1
[0] | (p1
[1] << 8);
176 static inline uint32_t le32_to_cpupu(const uint32_t *p
)
178 const uint8_t *p1
= (const uint8_t *)p
;
179 return p1
[0] | (p1
[1] << 8) | (p1
[2] << 16) | (p1
[3] << 24);
182 static inline uint32_t be32_to_cpupu(const uint32_t *p
)
184 const uint8_t *p1
= (const uint8_t *)p
;
185 return p1
[3] | (p1
[2] << 8) | (p1
[1] << 16) | (p1
[0] << 24);
188 static inline void cpu_to_be16wu(uint16_t *p
, uint16_t v
)
190 uint8_t *p1
= (uint8_t *)p
;
196 static inline void cpu_to_be32wu(uint32_t *p
, uint32_t v
)
198 uint8_t *p1
= (uint8_t *)p
;
206 static inline void cpu_to_be64wu(uint64_t *p
, uint64_t v
)
208 uint8_t *p1
= (uint8_t *)p
;
222 #ifdef HOST_WORDS_BIGENDIAN
223 #define cpu_to_32wu cpu_to_be32wu
224 #define leul_to_cpu(v) glue(glue(le,HOST_LONG_BITS),_to_cpu)(v)
226 #define cpu_to_32wu cpu_to_le32wu
227 #define leul_to_cpu(v) (v)
235 /* len must be one of 1, 2, 4 */
236 static inline uint32_t qemu_bswap_len(uint32_t value
, int len
)
238 return bswap32(value
) >> (32 - 8 * len
);
248 #if defined(HOST_WORDS_BIGENDIAN)
272 #if defined(HOST_WORDS_BIGENDIAN)
297 /* unaligned/endian-independent pointer access */
300 * the generic syntax is:
302 * load: ld{type}{sign}{size}{endian}_p(ptr)
304 * store: st{type}{size}{endian}_p(ptr, val)
306 * Note there are small differences with the softmmu access API!
309 * (empty): integer access
313 * (empty): for floats or 32 bit size
324 * (empty): 8 bit access
328 static inline int ldub_p(const void *ptr
)
330 return *(uint8_t *)ptr
;
333 static inline int ldsb_p(const void *ptr
)
335 return *(int8_t *)ptr
;
338 static inline void stb_p(void *ptr
, int v
)
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)
348 /* conservative code for little endian unaligned accesses */
349 static inline int lduw_le_p(const void *ptr
)
353 __asm__
__volatile__ ("lhbrx %0,0,%1" : "=r" (val
) : "r" (ptr
));
356 const uint8_t *p
= ptr
;
357 return p
[0] | (p
[1] << 8);
361 static inline int ldsw_le_p(const void *ptr
)
365 __asm__
__volatile__ ("lhbrx %0,0,%1" : "=r" (val
) : "r" (ptr
));
368 const uint8_t *p
= ptr
;
369 return (int16_t)(p
[0] | (p
[1] << 8));
373 static inline int ldl_le_p(const void *ptr
)
377 __asm__
__volatile__ ("lwbrx %0,0,%1" : "=r" (val
) : "r" (ptr
));
380 const uint8_t *p
= ptr
;
381 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
385 static inline uint64_t ldq_le_p(const void *ptr
)
387 const uint8_t *p
= ptr
;
390 v2
= ldl_le_p(p
+ 4);
391 return v1
| ((uint64_t)v2
<< 32);
394 static inline void stw_le_p(void *ptr
, int v
)
397 __asm__
__volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr
) : "r" (v
), "r" (ptr
));
405 static inline void stl_le_p(void *ptr
, int v
)
408 __asm__
__volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr
) : "r" (v
), "r" (ptr
));
418 static inline void stq_le_p(void *ptr
, uint64_t v
)
421 stl_le_p(p
, (uint32_t)v
);
422 stl_le_p(p
+ 4, v
>> 32);
427 static inline float32
ldfl_le_p(const void *ptr
)
437 static inline void stfl_le_p(void *ptr
, float32 v
)
447 static inline float64
ldfq_le_p(const void *ptr
)
450 u
.l
.lower
= ldl_le_p(ptr
);
451 u
.l
.upper
= ldl_le_p(ptr
+ 4);
455 static inline void stfq_le_p(void *ptr
, float64 v
)
459 stl_le_p(ptr
, u
.l
.lower
);
460 stl_le_p(ptr
+ 4, u
.l
.upper
);
465 static inline int lduw_le_p(const void *ptr
)
467 return *(uint16_t *)ptr
;
470 static inline int ldsw_le_p(const void *ptr
)
472 return *(int16_t *)ptr
;
475 static inline int ldl_le_p(const void *ptr
)
477 return *(uint32_t *)ptr
;
480 static inline uint64_t ldq_le_p(const void *ptr
)
482 return *(uint64_t *)ptr
;
485 static inline void stw_le_p(void *ptr
, int v
)
487 *(uint16_t *)ptr
= v
;
490 static inline void stl_le_p(void *ptr
, int v
)
492 *(uint32_t *)ptr
= v
;
495 static inline void stq_le_p(void *ptr
, uint64_t v
)
497 *(uint64_t *)ptr
= v
;
502 static inline float32
ldfl_le_p(const void *ptr
)
504 return *(float32
*)ptr
;
507 static inline float64
ldfq_le_p(const void *ptr
)
509 return *(float64
*)ptr
;
512 static inline void stfl_le_p(void *ptr
, float32 v
)
517 static inline void stfq_le_p(void *ptr
, float64 v
)
523 #if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
525 static inline int lduw_be_p(const void *ptr
)
527 #if defined(__i386__)
529 asm volatile ("movzwl %1, %0\n"
532 : "m" (*(uint16_t *)ptr
));
535 const uint8_t *b
= ptr
;
536 return ((b
[0] << 8) | b
[1]);
540 static inline int ldsw_be_p(const void *ptr
)
542 #if defined(__i386__)
544 asm volatile ("movzwl %1, %0\n"
547 : "m" (*(uint16_t *)ptr
));
550 const uint8_t *b
= ptr
;
551 return (int16_t)((b
[0] << 8) | b
[1]);
555 static inline int ldl_be_p(const void *ptr
)
557 #if defined(__i386__) || defined(__x86_64__)
559 asm volatile ("movl %1, %0\n"
562 : "m" (*(uint32_t *)ptr
));
565 const uint8_t *b
= ptr
;
566 return (b
[0] << 24) | (b
[1] << 16) | (b
[2] << 8) | b
[3];
570 static inline uint64_t ldq_be_p(const void *ptr
)
574 b
= ldl_be_p((uint8_t *)ptr
+ 4);
575 return (((uint64_t)a
<<32)|b
);
578 static inline void stw_be_p(void *ptr
, int v
)
580 #if defined(__i386__)
581 asm volatile ("xchgb %b0, %h0\n"
584 : "m" (*(uint16_t *)ptr
), "0" (v
));
586 uint8_t *d
= (uint8_t *) ptr
;
592 static inline void stl_be_p(void *ptr
, int v
)
594 #if defined(__i386__) || defined(__x86_64__)
595 asm volatile ("bswap %0\n"
598 : "m" (*(uint32_t *)ptr
), "0" (v
));
600 uint8_t *d
= (uint8_t *) ptr
;
608 static inline void stq_be_p(void *ptr
, uint64_t v
)
610 stl_be_p(ptr
, v
>> 32);
611 stl_be_p((uint8_t *)ptr
+ 4, v
);
616 static inline float32
ldfl_be_p(const void *ptr
)
626 static inline void stfl_be_p(void *ptr
, float32 v
)
636 static inline float64
ldfq_be_p(const void *ptr
)
639 u
.l
.upper
= ldl_be_p(ptr
);
640 u
.l
.lower
= ldl_be_p((uint8_t *)ptr
+ 4);
644 static inline void stfq_be_p(void *ptr
, float64 v
)
648 stl_be_p(ptr
, u
.l
.upper
);
649 stl_be_p((uint8_t *)ptr
+ 4, u
.l
.lower
);
654 static inline int lduw_be_p(const void *ptr
)
656 return *(uint16_t *)ptr
;
659 static inline int ldsw_be_p(const void *ptr
)
661 return *(int16_t *)ptr
;
664 static inline int ldl_be_p(const void *ptr
)
666 return *(uint32_t *)ptr
;
669 static inline uint64_t ldq_be_p(const void *ptr
)
671 return *(uint64_t *)ptr
;
674 static inline void stw_be_p(void *ptr
, int v
)
676 *(uint16_t *)ptr
= v
;
679 static inline void stl_be_p(void *ptr
, int v
)
681 *(uint32_t *)ptr
= v
;
684 static inline void stq_be_p(void *ptr
, uint64_t v
)
686 *(uint64_t *)ptr
= v
;
691 static inline float32
ldfl_be_p(const void *ptr
)
693 return *(float32
*)ptr
;
696 static inline float64
ldfq_be_p(const void *ptr
)
698 return *(float64
*)ptr
;
701 static inline void stfl_be_p(void *ptr
, float32 v
)
706 static inline void stfq_be_p(void *ptr
, float64 v
)