BeRTOS
cpu/byteorder.h
Go to the documentation of this file.
00001 
00038 #ifndef MWARE_BYTEORDER_H
00039 #define MWARE_BYTEORDER_H
00040 
00041 #include <cfg/compiler.h>
00042 #include <cpu/attr.h>
00043 #include <cpu/detect.h>
00044 #include <cpu/types.h>
00045 #include <cfg/macros.h>
00046 
00050 #define SWAB16(x) ((uint16_t)(ROTR((x), 8) + \
00051         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t))))
00052 
00053 /*
00054  * On Cortex-M3, GCC 4.4 builtin implementation is slower than our own
00055  * rot-based implementation.
00056  */
00057 #if GNUC_PREREQ(4, 3) && !CPU_CM3
00058 #define SWAB32(x) ((uint32_t)(__builtin_bswap32((x) + \
00059         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t)))))
00060 #else
00061 
00064 #define SWAB32(x) ((uint32_t)(( \
00065     (ROTR(x, 8) & 0xFF00FF00) | \
00066     (ROTL(x, 8) & 0x00FF00FF))) + \
00067         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t)))
00068 #endif
00069 
00070 #if GNUC_PREREQ(4, 3)
00071 #define SWAB64(x) ((uint64_t)(__builtin_bswap64((x) + \
00072         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t)))))
00073 #else
00074 
00077 #define SWAB64(x) ((uint64_t)(                      \
00078     (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
00079     (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
00080     (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
00081     (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) <<  8) | \
00082     (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >>  8) | \
00083     (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
00084     (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
00085     (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) + \
00086         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t))))
00087 #endif
00088 
00089 #if CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN
00090 #define cpu_to_le16(x) ((uint16_t)(x + \
00091         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t))))
00092 #define cpu_to_le32(x) ((uint32_t)(x + \
00093         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t))))
00094 #define cpu_to_le64(x) ((uint64_t)(x + \
00095         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t))))
00096 #define cpu_to_be16(x) SWAB16(x)
00097 #define cpu_to_be32(x) SWAB32(x)
00098 #define cpu_to_be64(x) SWAB64(x)
00099 #elif CPU_BYTE_ORDER == CPU_BIG_ENDIAN
00100 #define cpu_to_le16(x) SWAB16(x)
00101 #define cpu_to_le32(x) SWAB32(x)
00102 #define cpu_to_le64(x) SWAB64(x)
00103 #define cpu_to_be16(x) ((uint16_t)(x + \
00104         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint16_t))))
00105 #define cpu_to_be32(x) ((uint32_t)(x + \
00106         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint32_t))))
00107 #define cpu_to_be64(x) ((uint64_t)(x + \
00108         STATIC_ASSERT_EXPR(sizeof(x) == sizeof(uint64_t))))
00109 #else
00110 #error "unrecognized CPU endianness"
00111 #endif
00112 
00113 #define be16_to_cpu(x)      cpu_to_be16(x)
00114 #define le16_to_cpu(x)      cpu_to_le16(x)
00115 #define be32_to_cpu(x)      cpu_to_be32(x)
00116 #define le32_to_cpu(x)      cpu_to_le32(x)
00117 #define be64_to_cpu(x)      cpu_to_be64(x)
00118 #define le64_to_cpu(x)      cpu_to_le64(x)
00119 
00120 #define host_to_net16(x)    cpu_to_be16(x)
00121 #define net_to_host16(x)    be16_to_cpu(x)
00122 #define host_to_net32(x)    cpu_to_be32(x)
00123 #define net_to_host32(x)    be32_to_cpu(x)
00124 #define host_to_net64(x)    cpu_to_be64(x)
00125 #define net_to_host64(x)    be64_to_cpu(x)
00126 
00130 INLINE float swab_float(float x)
00131 {
00132     /* Avoid breaking strict aliasing rules.  */
00133     char *cx = (char *)(&x);
00134     STATIC_ASSERT(sizeof(float) == 4);
00135     #define BYTEORDER_SWAP(a, b) do { (a) ^= (b); (b) ^= (a); (a) ^= (b); } while(0)
00136     BYTEORDER_SWAP(cx[0], cx[3]);
00137     BYTEORDER_SWAP(cx[1], cx[2]);
00138     #undef BYTEORDER_SWAP
00139     return x;
00140 }
00141 
00142 INLINE float cpu_to_be_float(float x)
00143 {
00144     return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab_float(x) : x;
00145 }
00146 
00147 INLINE float cpu_to_le_float(float x)
00148 {
00149     return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab_float(x) : x;
00150 }
00151 
00152 INLINE float be_float_to_cpu(float x)
00153 {
00154     return cpu_to_be_float(x);
00155 }
00156 
00157 INLINE float le_float_to_cpu(float x)
00158 {
00159     return cpu_to_le_float(x);
00160 }
00161 
00162 INLINE float host_to_net_float(float x)
00163 {
00164     return cpu_to_be_float(x);
00165 }
00166 
00167 INLINE float net_to_host_float(float x)
00168 {
00169     return be_float_to_cpu(x);
00170 }
00171 
00172 #if CPU_ARM
00173 INLINE cpu_atomic_t
00174 cpu_atomic_xchg(volatile cpu_atomic_t *ptr, cpu_atomic_t val)
00175 {
00176     cpu_atomic_t ret;
00177 
00178     asm volatile(
00179         "swp     %0, %1, [%2]"
00180 
00181         : "=&r" (ret)
00182         : "r" (val), "r" (ptr)
00183         : "memory", "cc");
00184 
00185     return ret;
00186 }
00187 #else /* CPU_ARM */
00188 #include <cpu/irq.h>
00189 
00190 INLINE cpu_atomic_t
00191 cpu_atomic_xchg(volatile cpu_atomic_t *ptr, cpu_atomic_t val)
00192 {
00193     cpu_atomic_t ret;
00194 
00195     ATOMIC(
00196         ret = *ptr;
00197         *ptr = val;
00198     );
00199     return ret;
00200 }
00201 #endif /* CPU_ARM */
00202 
00203 #ifdef __cplusplus
00204 
00206 template<typename T>
00207 INLINE T swab(T x);
00208 
00209 template<> INLINE uint16_t swab(uint16_t x) { return SWAB16(x); }
00210 template<> INLINE uint32_t swab(uint32_t x) { return SWAB32(x); }
00211 template<> INLINE uint64_t swab(uint64_t x) { return SWAB64(x); }
00212 template<> INLINE int16_t  swab(int16_t x)  { return static_cast<int16_t>(SWAB16(static_cast<uint16_t>(x))); }
00213 template<> INLINE int32_t  swab(int32_t x)  { return static_cast<int32_t>(SWAB32(static_cast<uint32_t>(x))); }
00214 template<> INLINE int64_t  swab(int64_t x)  { return static_cast<int64_t>(SWAB64(static_cast<uint64_t>(x))); }
00215 template<> INLINE float    swab(float x)    { return swab_float(x); }
00216 
00218 template<typename T>
00219 INLINE T cpu_to_be(T x)
00220 {
00221     return (CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN) ? swab(x) : x;
00222 }
00223 
00225 template<typename T>
00226 INLINE T cpu_to_le(T x)
00227 {
00228     return (CPU_BYTE_ORDER == CPU_BIG_ENDIAN) ? swab(x) : x;
00229 }
00230 
00232 template<typename T>
00233 INLINE T be_to_cpu(T x)
00234 {
00235     return cpu_to_be(x);
00236 }
00237 
00239 template<typename T>
00240 INLINE T le_to_cpu(T x)
00241 {
00242     return cpu_to_le(x);
00243 }
00244 
00246 template<typename T>
00247 INLINE T net_to_host(T x)
00248 {
00249     return be_to_cpu(x);
00250 }
00251 
00253 template<typename T>
00254 INLINE T host_to_net(T x)
00255 {
00256     return net_to_host(x);
00257 }
00258 
00259 #endif /* __cplusplus */
00260 
00261 #endif /* MWARE_BYTEORDER_H */