BeRTOS
|
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 */