#ifndef BSWAP_H
#define BSWAP_H
-#include "fpu/softfloat-types.h"
-
#ifdef CONFIG_MACHINE_BSWAP_H
# include <sys/endian.h>
# include <machine/bswap.h>
#elif defined(__FreeBSD__)
# include <sys/endian.h>
+#elif defined(__HAIKU__)
+# include <endian.h>
#elif defined(CONFIG_BYTESWAP_H)
# include <byteswap.h>
+#define BSWAP_FROM_BYTESWAP
+# else
+#define BSWAP_FROM_FALLBACKS
+#endif /* ! CONFIG_MACHINE_BSWAP_H */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef BSWAP_FROM_BYTESWAP
static inline uint16_t bswap16(uint16_t x)
{
return bswap_16(x);
{
return bswap_64(x);
}
-# else
+#endif
+
+#ifdef BSWAP_FROM_FALLBACKS
static inline uint16_t bswap16(uint16_t x)
{
return (((x & 0x00ff) << 8) |
((x & 0x00ff000000000000ULL) >> 40) |
((x & 0xff00000000000000ULL) >> 56));
}
-#endif /* ! CONFIG_MACHINE_BSWAP_H */
+#endif
+
+#undef BSWAP_FROM_BYTESWAP
+#undef BSWAP_FROM_FALLBACKS
static inline void bswap16s(uint16_t *s)
{
*s = bswap64(*s);
}
-#if defined(HOST_WORDS_BIGENDIAN)
+#if HOST_BIG_ENDIAN
#define be_bswap(v, size) (v)
#define le_bswap(v, size) glue(bswap, size)(v)
#define be_bswaps(v, size)
CPU_CONVERT(le, 32, uint32_t)
CPU_CONVERT(le, 64, uint64_t)
-/* len must be one of 1, 2, 4 */
-static inline uint32_t qemu_bswap_len(uint32_t value, int len)
-{
- return bswap32(value) >> (32 - 8 * len);
-}
-
/*
* Same as cpu_to_le{16,32}, except that gcc will figure the result is
* a compile-time constant if you pass in a constant. So this can be
* used to initialize static variables.
*/
-#if defined(HOST_WORDS_BIGENDIAN)
+#if HOST_BIG_ENDIAN
# define const_le32(_x) \
((((_x) & 0x000000ffU) << 24) | \
(((_x) & 0x0000ff00U) << 8) | \
# define const_le16(_x) (_x)
#endif
-/* Unions for reinterpreting between floats and integers. */
-
-typedef union {
- float32 f;
- uint32_t l;
-} CPU_FloatU;
-
-typedef union {
- float64 d;
-#if defined(HOST_WORDS_BIGENDIAN)
- struct {
- uint32_t upper;
- uint32_t lower;
- } l;
-#else
- struct {
- uint32_t lower;
- uint32_t upper;
- } l;
-#endif
- uint64_t ll;
-} CPU_DoubleU;
-
-typedef union {
- floatx80 d;
- struct {
- uint64_t lower;
- uint16_t upper;
- } l;
-} CPU_LDoubleU;
-
-typedef union {
- float128 q;
-#if defined(HOST_WORDS_BIGENDIAN)
- struct {
- uint32_t upmost;
- uint32_t upper;
- uint32_t lower;
- uint32_t lowest;
- } l;
- struct {
- uint64_t upper;
- uint64_t lower;
- } ll;
-#else
- struct {
- uint32_t lowest;
- uint32_t lower;
- uint32_t upper;
- uint32_t upmost;
- } l;
- struct {
- uint64_t lower;
- uint64_t upper;
- } ll;
-#endif
-} CPU_QuadU;
-
/* unaligned/endian-independent pointer access */
/*
*(uint8_t *)ptr = v;
}
-/* Any compiler worth its salt will turn these memcpy into native unaligned
- operations. Thus we don't need to play games with packed attributes, or
- inline byte-by-byte stores. */
+/*
+ * Any compiler worth its salt will turn these memcpy into native unaligned
+ * operations. Thus we don't need to play games with packed attributes, or
+ * inline byte-by-byte stores.
+ * Some compilation environments (eg some fortify-source implementations)
+ * may intercept memcpy() in a way that defeats the compiler optimization,
+ * though, so we use __builtin_memcpy() to give ourselves the best chance
+ * of good performance.
+ */
static inline int lduw_he_p(const void *ptr)
{
uint16_t r;
- memcpy(&r, ptr, sizeof(r));
+ __builtin_memcpy(&r, ptr, sizeof(r));
return r;
}
static inline int ldsw_he_p(const void *ptr)
{
int16_t r;
- memcpy(&r, ptr, sizeof(r));
+ __builtin_memcpy(&r, ptr, sizeof(r));
return r;
}
static inline void stw_he_p(void *ptr, uint16_t v)
{
- memcpy(ptr, &v, sizeof(v));
+ __builtin_memcpy(ptr, &v, sizeof(v));
}
static inline int ldl_he_p(const void *ptr)
{
int32_t r;
- memcpy(&r, ptr, sizeof(r));
+ __builtin_memcpy(&r, ptr, sizeof(r));
return r;
}
static inline void stl_he_p(void *ptr, uint32_t v)
{
- memcpy(ptr, &v, sizeof(v));
+ __builtin_memcpy(ptr, &v, sizeof(v));
}
static inline uint64_t ldq_he_p(const void *ptr)
{
uint64_t r;
- memcpy(&r, ptr, sizeof(r));
+ __builtin_memcpy(&r, ptr, sizeof(r));
return r;
}
static inline void stq_he_p(void *ptr, uint64_t v)
{
- memcpy(ptr, &v, sizeof(v));
+ __builtin_memcpy(ptr, &v, sizeof(v));
}
static inline int lduw_le_p(const void *ptr)
stq_he_p(ptr, le_bswap(v, 64));
}
-/* float access */
-
-static inline float32 ldfl_le_p(const void *ptr)
-{
- CPU_FloatU u;
- u.l = ldl_le_p(ptr);
- return u.f;
-}
-
-static inline void stfl_le_p(void *ptr, float32 v)
-{
- CPU_FloatU u;
- u.f = v;
- stl_le_p(ptr, u.l);
-}
-
-static inline float64 ldfq_le_p(const void *ptr)
-{
- CPU_DoubleU u;
- u.ll = ldq_le_p(ptr);
- return u.d;
-}
-
-static inline void stfq_le_p(void *ptr, float64 v)
-{
- CPU_DoubleU u;
- u.d = v;
- stq_le_p(ptr, u.ll);
-}
-
static inline int lduw_be_p(const void *ptr)
{
return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
stq_he_p(ptr, be_bswap(v, 64));
}
-/* float access */
-
-static inline float32 ldfl_be_p(const void *ptr)
-{
- CPU_FloatU u;
- u.l = ldl_be_p(ptr);
- return u.f;
-}
-
-static inline void stfl_be_p(void *ptr, float32 v)
-{
- CPU_FloatU u;
- u.f = v;
- stl_be_p(ptr, u.l);
-}
-
-static inline float64 ldfq_be_p(const void *ptr)
-{
- CPU_DoubleU u;
- u.ll = ldq_be_p(ptr);
- return u.d;
-}
-
-static inline void stfq_be_p(void *ptr, float64 v)
-{
- CPU_DoubleU u;
- u.d = v;
- stq_be_p(ptr, u.ll);
-}
-
static inline unsigned long leul_to_cpu(unsigned long v)
{
#if HOST_LONG_BITS == 32
#undef le_bswaps
#undef be_bswaps
+#ifdef __cplusplus
+}
+#endif
+
#endif /* BSWAP_H */