X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fbyteorder.h;h=37d7a84167d97b24d3da9e150f878f461f207b97;hb=e8b0472be10fba4ca6baa62d8d483db90e28c06e;hp=b560559c4342f95cfe49c3c3bda698f19459c1cb;hpb=5117c025ff3e6cee6e0b934ff4cde205ccb34685;p=bertos.git diff --git a/bertos/cpu/byteorder.h b/bertos/cpu/byteorder.h index b560559c..37d7a841 100644 --- a/bertos/cpu/byteorder.h +++ b/bertos/cpu/byteorder.h @@ -40,6 +40,9 @@ #include #include +#include +#include +#include /** * Swap upper and lower bytes in a 16-bit value. @@ -47,22 +50,27 @@ #define SWAB16(x) ((uint16_t)(ROTR((x), 8) + \ STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t)))) -#if GNUC_PREREQ(4, 3) +/* + * 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))))) -#define SWAB64(x) ((uint64_t)(__builtin_bswap64((x) + \ - STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_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) + \ - STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t)))) +#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. */ @@ -124,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 @@ -161,6 +169,37 @@ 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.