X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fbyteorder.h;h=37d7a84167d97b24d3da9e150f878f461f207b97;hb=e8b0472be10fba4ca6baa62d8d483db90e28c06e;hp=f2d402df20682db906f587786231288015753f36;hpb=747b943bfd16b0d5eb20bc31c125ab12bafe65de;p=bertos.git diff --git a/bertos/cpu/byteorder.h b/bertos/cpu/byteorder.h index f2d402df..37d7a841 100644 --- a/bertos/cpu/byteorder.h +++ b/bertos/cpu/byteorder.h @@ -40,25 +40,37 @@ #include #include +#include +#include +#include /** * Swap upper and lower bytes in a 16-bit value. */ -#define swab16(x) ((uint16_t)(ROTR(x, 8))) +#define SWAB16(x) ((uint16_t)(ROTR((x), 8) + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t)))) -#if GNUC_PREREQ(4, 3) -#define SWAB32(x) __builtin_bswap32(x) -#define SWAB64(x) __builtin_bswap64(x) +/* + * On Cortex-M3, GCC 4.4 builtin implementation is slower than our own + * rot-based implementation. + */ +#if GNUC_PREREQ(4, 3) && !CPU_CM3 +#define SWAB32(x) ((uint32_t)(__builtin_bswap32((x) + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t))))) #else /** * Reverse bytes in a 32-bit value (e.g.: 0x12345678 -> 0x78563412). */ -#define SWAB32(x) ((uint32_t)( \ - (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \ - (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \ - (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \ - (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24))) +#define SWAB32(x) ((uint32_t)(( \ + (ROTR(x, 8) & 0xFF00FF00) | \ + (ROTL(x, 8) & 0x00FF00FF))) + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t))) +#endif +#if GNUC_PREREQ(4, 3) +#define SWAB64(x) ((uint64_t)(__builtin_bswap64((x) + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t))))) +#else /** * Reverse bytes in a 64-bit value. */ @@ -70,35 +82,30 @@ (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ - (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56))) + (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t)))) #endif #if CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN -#define cpu_to_le16(x) \ - (x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t))) -#define cpu_to_le32(x) \ - (x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t))) -#define cpu_to_le64(x) \ - (x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t))) -#define cpu_to_be16(x) \ - SWAB16(x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t))) -#define cpu_to_be32(x) \ - SWAB32(x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t))) -#define cpu_to_be64(x) \ - SWAB64(x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t))) +#define cpu_to_le16(x) ((uint16_t)(x + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t)))) +#define cpu_to_le32(x) ((uint32_t)(x + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t)))) +#define cpu_to_le64(x) ((uint64_t)(x + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t)))) +#define cpu_to_be16(x) SWAB16(x) +#define cpu_to_be32(x) SWAB32(x) +#define cpu_to_be64(x) SWAB64(x) #elif CPU_BYTE_ORDER == CPU_BIG_ENDIAN -#define cpu_to_le16(x) \ - SWAB16(x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t))) -#define cpu_to_le32(x) \ - SWAB32(x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t))) -#define cpu_to_le64(x) \ - SWAB64(x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t))) -#define cpu_to_be16(x) \ - (x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t))) -#define cpu_to_be32(x) \ - (x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t))) -#define cpu_to_be64(x) \ - (x + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t))) +#define cpu_to_le16(x) SWAB16(x) +#define cpu_to_le32(x) SWAB32(x) +#define cpu_to_le64(x) SWAB64(x) +#define cpu_to_be16(x) ((uint16_t)(x + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t)))) +#define cpu_to_be32(x) ((uint32_t)(x + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t)))) +#define cpu_to_be64(x) ((uint64_t)(x + \ + STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t)))) #else #error "unrecognized CPU endianness" #endif @@ -125,7 +132,7 @@ INLINE float swab_float(float x) /* Avoid breaking strict aliasing rules. */ char *cx = (char *)(&x); STATIC_ASSERT(sizeof(float) == 4); - #define BYTEORDER_SWAP(a, b) ((a) ^= (b) ^= (a) ^= (b)) + #define BYTEORDER_SWAP(a, b) do { (a) ^= (b); (b) ^= (a); (a) ^= (b); } while(0) BYTEORDER_SWAP(cx[0], cx[3]); BYTEORDER_SWAP(cx[1], cx[2]); #undef BYTEORDER_SWAP @@ -162,18 +169,49 @@ INLINE float net_to_host_float(float x) return be_float_to_cpu(x); } +#if CPU_ARM +INLINE cpu_atomic_t +cpu_atomic_xchg(volatile cpu_atomic_t *ptr, cpu_atomic_t val) +{ + cpu_atomic_t ret; + + asm volatile( + "swp %0, %1, [%2]" + + : "=&r" (ret) + : "r" (val), "r" (ptr) + : "memory", "cc"); + + return ret; +} +#else /* CPU_ARM */ +#include + +INLINE cpu_atomic_t +cpu_atomic_xchg(volatile cpu_atomic_t *ptr, cpu_atomic_t val) +{ + cpu_atomic_t ret; + + ATOMIC( + ret = *ptr; + *ptr = val; + ); + return ret; +} +#endif /* CPU_ARM */ + #ifdef __cplusplus /// Type generic byte swapping. template INLINE T swab(T x); -template<> INLINE uint16_t swab(uint16_t x) { return swab16(x); } -template<> INLINE uint32_t swab(uint32_t x) { return swab32(x); } -template<> INLINE uint64_t swab(uint64_t x) { return swab64(x); } -template<> INLINE int16_t swab(int16_t x) { return static_cast(swab16(static_cast(x))); } -template<> INLINE int32_t swab(int32_t x) { return static_cast(swab32(static_cast(x))); } -template<> INLINE int64_t swab(int64_t x) { return static_cast(swab64(static_cast(x))); } +template<> INLINE uint16_t swab(uint16_t x) { return SWAB16(x); } +template<> INLINE uint32_t swab(uint32_t x) { return SWAB32(x); } +template<> INLINE uint64_t swab(uint64_t x) { return SWAB64(x); } +template<> INLINE int16_t swab(int16_t x) { return static_cast(SWAB16(static_cast(x))); } +template<> INLINE int32_t swab(int32_t x) { return static_cast(SWAB32(static_cast(x))); } +template<> INLINE int64_t swab(int64_t x) { return static_cast(SWAB64(static_cast(x))); } template<> INLINE float swab(float x) { return swab_float(x); } /// Type generic conversion from CPU byte order to big-endian byte order.