1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #ifndef _RTE_BYTEORDER_H_ 6 #define _RTE_BYTEORDER_H_ 7 8 /** 9 * @file 10 * 11 * Byte Swap Operations 12 * 13 * This file defines a generic API for byte swap operations. Part of 14 * the implementation is architecture-specific. 15 */ 16 17 #include <stdint.h> 18 #ifdef RTE_EXEC_ENV_FREEBSD 19 #include <sys/endian.h> 20 #elif defined RTE_EXEC_ENV_LINUX 21 #include <endian.h> 22 #endif 23 24 #include <rte_common.h> 25 #include <rte_config.h> 26 27 #ifdef __cplusplus 28 extern "C" { 29 #endif 30 31 /* 32 * Compile-time endianness detection 33 */ 34 #define RTE_BIG_ENDIAN 1 35 #define RTE_LITTLE_ENDIAN 2 36 #if defined __BYTE_ORDER__ 37 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 38 #define RTE_BYTE_ORDER RTE_BIG_ENDIAN 39 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 40 #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN 41 #endif /* __BYTE_ORDER__ */ 42 #elif defined __BYTE_ORDER 43 #if __BYTE_ORDER == __BIG_ENDIAN 44 #define RTE_BYTE_ORDER RTE_BIG_ENDIAN 45 #elif __BYTE_ORDER == __LITTLE_ENDIAN 46 #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN 47 #endif /* __BYTE_ORDER */ 48 #elif defined __BIG_ENDIAN__ 49 #define RTE_BYTE_ORDER RTE_BIG_ENDIAN 50 #elif defined __LITTLE_ENDIAN__ 51 #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN 52 #elif defined RTE_TOOLCHAIN_MSVC 53 #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN 54 #endif 55 #if !defined(RTE_BYTE_ORDER) 56 #error Unknown endianness. 57 #endif 58 59 #define RTE_STATIC_BSWAP16(v) \ 60 ((((uint16_t)(v) & UINT16_C(0x00ff)) << 8) | \ 61 (((uint16_t)(v) & UINT16_C(0xff00)) >> 8)) 62 63 #define RTE_STATIC_BSWAP32(v) \ 64 ((((uint32_t)(v) & UINT32_C(0x000000ff)) << 24) | \ 65 (((uint32_t)(v) & UINT32_C(0x0000ff00)) << 8) | \ 66 (((uint32_t)(v) & UINT32_C(0x00ff0000)) >> 8) | \ 67 (((uint32_t)(v) & UINT32_C(0xff000000)) >> 24)) 68 69 #define RTE_STATIC_BSWAP64(v) \ 70 ((((uint64_t)(v) & UINT64_C(0x00000000000000ff)) << 56) | \ 71 (((uint64_t)(v) & UINT64_C(0x000000000000ff00)) << 40) | \ 72 (((uint64_t)(v) & UINT64_C(0x0000000000ff0000)) << 24) | \ 73 (((uint64_t)(v) & UINT64_C(0x00000000ff000000)) << 8) | \ 74 (((uint64_t)(v) & UINT64_C(0x000000ff00000000)) >> 8) | \ 75 (((uint64_t)(v) & UINT64_C(0x0000ff0000000000)) >> 24) | \ 76 (((uint64_t)(v) & UINT64_C(0x00ff000000000000)) >> 40) | \ 77 (((uint64_t)(v) & UINT64_C(0xff00000000000000)) >> 56)) 78 79 /* 80 * These macros are functionally similar to rte_cpu_to_(be|le)(16|32|64)(), 81 * they take values in host CPU order and return them converted to the 82 * intended endianness. 83 * 84 * They resolve at compilation time to integer constants which can safely be 85 * used with static initializers, since those cannot involve function calls. 86 * 87 * On the other hand, they are not as optimized as their rte_cpu_to_*() 88 * counterparts, therefore applications should refrain from using them on 89 * variable values, particularly inside performance-sensitive code. 90 */ 91 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN 92 #define RTE_BE16(v) (rte_be16_t)(v) 93 #define RTE_BE32(v) (rte_be32_t)(v) 94 #define RTE_BE64(v) (rte_be64_t)(v) 95 #define RTE_LE16(v) (rte_le16_t)(RTE_STATIC_BSWAP16(v)) 96 #define RTE_LE32(v) (rte_le32_t)(RTE_STATIC_BSWAP32(v)) 97 #define RTE_LE64(v) (rte_le64_t)(RTE_STATIC_BSWAP64(v)) 98 #elif RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 99 #define RTE_BE16(v) (rte_be16_t)(RTE_STATIC_BSWAP16(v)) 100 #define RTE_BE32(v) (rte_be32_t)(RTE_STATIC_BSWAP32(v)) 101 #define RTE_BE64(v) (rte_be64_t)(RTE_STATIC_BSWAP64(v)) 102 #define RTE_LE16(v) (rte_le16_t)(v) 103 #define RTE_LE32(v) (rte_le32_t)(v) 104 #define RTE_LE64(v) (rte_le64_t)(v) 105 #else 106 #error Unsupported endianness. 107 #endif 108 109 /* 110 * The following types should be used when handling values according to a 111 * specific byte ordering, which may differ from that of the host CPU. 112 * 113 * Libraries, public APIs and applications are encouraged to use them for 114 * documentation purposes. 115 */ 116 typedef uint16_t rte_be16_t; /**< 16-bit big-endian value. */ 117 typedef uint32_t rte_be32_t; /**< 32-bit big-endian value. */ 118 typedef uint64_t rte_be64_t; /**< 64-bit big-endian value. */ 119 typedef uint16_t rte_le16_t; /**< 16-bit little-endian value. */ 120 typedef uint32_t rte_le32_t; /**< 32-bit little-endian value. */ 121 typedef uint64_t rte_le64_t; /**< 64-bit little-endian value. */ 122 123 /* 124 * An internal function to swap bytes in a 16-bit value. 125 * 126 * It is used by rte_bswap16() when the value is constant. Do not use 127 * this function directly; rte_bswap16() is preferred. 128 */ 129 static inline uint16_t 130 rte_constant_bswap16(uint16_t x) 131 { 132 return (uint16_t)RTE_STATIC_BSWAP16(x); 133 } 134 135 /* 136 * An internal function to swap bytes in a 32-bit value. 137 * 138 * It is used by rte_bswap32() when the value is constant. Do not use 139 * this function directly; rte_bswap32() is preferred. 140 */ 141 static inline uint32_t 142 rte_constant_bswap32(uint32_t x) 143 { 144 return (uint32_t)RTE_STATIC_BSWAP32(x); 145 } 146 147 /* 148 * An internal function to swap bytes of a 64-bit value. 149 * 150 * It is used by rte_bswap64() when the value is constant. Do not use 151 * this function directly; rte_bswap64() is preferred. 152 */ 153 static inline uint64_t 154 rte_constant_bswap64(uint64_t x) 155 { 156 return (uint64_t)RTE_STATIC_BSWAP64(x); 157 } 158 159 160 #ifdef __DOXYGEN__ 161 162 /** 163 * Swap bytes in a 16-bit value. 164 */ 165 static uint16_t rte_bswap16(uint16_t _x); 166 167 /** 168 * Swap bytes in a 32-bit value. 169 */ 170 static uint32_t rte_bswap32(uint32_t x); 171 172 /** 173 * Swap bytes in a 64-bit value. 174 */ 175 static uint64_t rte_bswap64(uint64_t x); 176 177 /** 178 * Convert a 16-bit value from CPU order to little endian. 179 */ 180 static rte_le16_t rte_cpu_to_le_16(uint16_t x); 181 182 /** 183 * Convert a 32-bit value from CPU order to little endian. 184 */ 185 static rte_le32_t rte_cpu_to_le_32(uint32_t x); 186 187 /** 188 * Convert a 64-bit value from CPU order to little endian. 189 */ 190 static rte_le64_t rte_cpu_to_le_64(uint64_t x); 191 192 193 /** 194 * Convert a 16-bit value from CPU order to big endian. 195 */ 196 static rte_be16_t rte_cpu_to_be_16(uint16_t x); 197 198 /** 199 * Convert a 32-bit value from CPU order to big endian. 200 */ 201 static rte_be32_t rte_cpu_to_be_32(uint32_t x); 202 203 /** 204 * Convert a 64-bit value from CPU order to big endian. 205 */ 206 static rte_be64_t rte_cpu_to_be_64(uint64_t x); 207 208 209 /** 210 * Convert a 16-bit value from little endian to CPU order. 211 */ 212 static uint16_t rte_le_to_cpu_16(rte_le16_t x); 213 214 /** 215 * Convert a 32-bit value from little endian to CPU order. 216 */ 217 static uint32_t rte_le_to_cpu_32(rte_le32_t x); 218 219 /** 220 * Convert a 64-bit value from little endian to CPU order. 221 */ 222 static uint64_t rte_le_to_cpu_64(rte_le64_t x); 223 224 225 /** 226 * Convert a 16-bit value from big endian to CPU order. 227 */ 228 static uint16_t rte_be_to_cpu_16(rte_be16_t x); 229 230 /** 231 * Convert a 32-bit value from big endian to CPU order. 232 */ 233 static uint32_t rte_be_to_cpu_32(rte_be32_t x); 234 235 /** 236 * Convert a 64-bit value from big endian to CPU order. 237 */ 238 static uint64_t rte_be_to_cpu_64(rte_be64_t x); 239 240 #endif /* __DOXYGEN__ */ 241 242 #ifdef RTE_FORCE_INTRINSICS 243 #ifndef RTE_TOOLCHAIN_MSVC 244 #define rte_bswap16(x) __builtin_bswap16(x) 245 246 #define rte_bswap32(x) __builtin_bswap32(x) 247 248 #define rte_bswap64(x) __builtin_bswap64(x) 249 #else 250 #define rte_bswap16(x) _byteswap_ushort(x) 251 252 #define rte_bswap32(x) _byteswap_ulong(x) 253 254 #define rte_bswap64(x) _byteswap_uint64(x) 255 #endif 256 #endif 257 258 #ifdef __cplusplus 259 } 260 #endif 261 262 #endif /* _RTE_BYTEORDER_H_ */ 263