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)