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