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