199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #ifndef _RTE_BYTEORDER_H_ 699a2dd95SBruce Richardson #define _RTE_BYTEORDER_H_ 799a2dd95SBruce Richardson 899a2dd95SBruce Richardson /** 999a2dd95SBruce Richardson * @file 1099a2dd95SBruce Richardson * 1199a2dd95SBruce Richardson * Byte Swap Operations 1299a2dd95SBruce Richardson * 1399a2dd95SBruce Richardson * This file defines a generic API for byte swap operations. Part of 1499a2dd95SBruce Richardson * the implementation is architecture-specific. 1599a2dd95SBruce Richardson */ 1699a2dd95SBruce Richardson 1799a2dd95SBruce Richardson #include <stdint.h> 1899a2dd95SBruce Richardson #ifdef RTE_EXEC_ENV_FREEBSD 1999a2dd95SBruce Richardson #include <sys/endian.h> 2099a2dd95SBruce Richardson #elif defined RTE_EXEC_ENV_LINUX 2199a2dd95SBruce Richardson #include <endian.h> 2299a2dd95SBruce Richardson #endif 2399a2dd95SBruce Richardson 2499a2dd95SBruce Richardson #include <rte_common.h> 2599a2dd95SBruce Richardson #include <rte_config.h> 2699a2dd95SBruce Richardson 27*719834a6SMattias Rönnblom #ifdef __cplusplus 28*719834a6SMattias Rönnblom extern "C" { 29*719834a6SMattias Rönnblom #endif 30*719834a6SMattias Rönnblom 3199a2dd95SBruce Richardson /* 3299a2dd95SBruce Richardson * Compile-time endianness detection 3399a2dd95SBruce Richardson */ 3499a2dd95SBruce Richardson #define RTE_BIG_ENDIAN 1 3599a2dd95SBruce Richardson #define RTE_LITTLE_ENDIAN 2 3699a2dd95SBruce Richardson #if defined __BYTE_ORDER__ 3799a2dd95SBruce Richardson #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 3899a2dd95SBruce Richardson #define RTE_BYTE_ORDER RTE_BIG_ENDIAN 3999a2dd95SBruce Richardson #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 4099a2dd95SBruce Richardson #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN 4199a2dd95SBruce Richardson #endif /* __BYTE_ORDER__ */ 4299a2dd95SBruce Richardson #elif defined __BYTE_ORDER 4399a2dd95SBruce Richardson #if __BYTE_ORDER == __BIG_ENDIAN 4499a2dd95SBruce Richardson #define RTE_BYTE_ORDER RTE_BIG_ENDIAN 4599a2dd95SBruce Richardson #elif __BYTE_ORDER == __LITTLE_ENDIAN 4699a2dd95SBruce Richardson #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN 4799a2dd95SBruce Richardson #endif /* __BYTE_ORDER */ 4899a2dd95SBruce Richardson #elif defined __BIG_ENDIAN__ 4999a2dd95SBruce Richardson #define RTE_BYTE_ORDER RTE_BIG_ENDIAN 5099a2dd95SBruce Richardson #elif defined __LITTLE_ENDIAN__ 5199a2dd95SBruce Richardson #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN 52af80b4c4STyler Retzlaff #elif defined RTE_TOOLCHAIN_MSVC 53af80b4c4STyler Retzlaff #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN 5499a2dd95SBruce Richardson #endif 5599a2dd95SBruce Richardson #if !defined(RTE_BYTE_ORDER) 5699a2dd95SBruce Richardson #error Unknown endianness. 5799a2dd95SBruce Richardson #endif 5899a2dd95SBruce Richardson 5999a2dd95SBruce Richardson #define RTE_STATIC_BSWAP16(v) \ 6099a2dd95SBruce Richardson ((((uint16_t)(v) & UINT16_C(0x00ff)) << 8) | \ 6199a2dd95SBruce Richardson (((uint16_t)(v) & UINT16_C(0xff00)) >> 8)) 6299a2dd95SBruce Richardson 6399a2dd95SBruce Richardson #define RTE_STATIC_BSWAP32(v) \ 6499a2dd95SBruce Richardson ((((uint32_t)(v) & UINT32_C(0x000000ff)) << 24) | \ 6599a2dd95SBruce Richardson (((uint32_t)(v) & UINT32_C(0x0000ff00)) << 8) | \ 6699a2dd95SBruce Richardson (((uint32_t)(v) & UINT32_C(0x00ff0000)) >> 8) | \ 6799a2dd95SBruce Richardson (((uint32_t)(v) & UINT32_C(0xff000000)) >> 24)) 6899a2dd95SBruce Richardson 6999a2dd95SBruce Richardson #define RTE_STATIC_BSWAP64(v) \ 7099a2dd95SBruce Richardson ((((uint64_t)(v) & UINT64_C(0x00000000000000ff)) << 56) | \ 7199a2dd95SBruce Richardson (((uint64_t)(v) & UINT64_C(0x000000000000ff00)) << 40) | \ 7299a2dd95SBruce Richardson (((uint64_t)(v) & UINT64_C(0x0000000000ff0000)) << 24) | \ 7399a2dd95SBruce Richardson (((uint64_t)(v) & UINT64_C(0x00000000ff000000)) << 8) | \ 7499a2dd95SBruce Richardson (((uint64_t)(v) & UINT64_C(0x000000ff00000000)) >> 8) | \ 7599a2dd95SBruce Richardson (((uint64_t)(v) & UINT64_C(0x0000ff0000000000)) >> 24) | \ 7699a2dd95SBruce Richardson (((uint64_t)(v) & UINT64_C(0x00ff000000000000)) >> 40) | \ 7799a2dd95SBruce Richardson (((uint64_t)(v) & UINT64_C(0xff00000000000000)) >> 56)) 7899a2dd95SBruce Richardson 7999a2dd95SBruce Richardson /* 8099a2dd95SBruce Richardson * These macros are functionally similar to rte_cpu_to_(be|le)(16|32|64)(), 8199a2dd95SBruce Richardson * they take values in host CPU order and return them converted to the 8299a2dd95SBruce Richardson * intended endianness. 8399a2dd95SBruce Richardson * 8499a2dd95SBruce Richardson * They resolve at compilation time to integer constants which can safely be 8599a2dd95SBruce Richardson * used with static initializers, since those cannot involve function calls. 8699a2dd95SBruce Richardson * 8799a2dd95SBruce Richardson * On the other hand, they are not as optimized as their rte_cpu_to_*() 8899a2dd95SBruce Richardson * counterparts, therefore applications should refrain from using them on 8999a2dd95SBruce Richardson * variable values, particularly inside performance-sensitive code. 9099a2dd95SBruce Richardson */ 9199a2dd95SBruce Richardson #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN 9299a2dd95SBruce Richardson #define RTE_BE16(v) (rte_be16_t)(v) 9399a2dd95SBruce Richardson #define RTE_BE32(v) (rte_be32_t)(v) 9499a2dd95SBruce Richardson #define RTE_BE64(v) (rte_be64_t)(v) 9599a2dd95SBruce Richardson #define RTE_LE16(v) (rte_le16_t)(RTE_STATIC_BSWAP16(v)) 9699a2dd95SBruce Richardson #define RTE_LE32(v) (rte_le32_t)(RTE_STATIC_BSWAP32(v)) 9799a2dd95SBruce Richardson #define RTE_LE64(v) (rte_le64_t)(RTE_STATIC_BSWAP64(v)) 9899a2dd95SBruce Richardson #elif RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 9999a2dd95SBruce Richardson #define RTE_BE16(v) (rte_be16_t)(RTE_STATIC_BSWAP16(v)) 10099a2dd95SBruce Richardson #define RTE_BE32(v) (rte_be32_t)(RTE_STATIC_BSWAP32(v)) 10199a2dd95SBruce Richardson #define RTE_BE64(v) (rte_be64_t)(RTE_STATIC_BSWAP64(v)) 10299a2dd95SBruce Richardson #define RTE_LE16(v) (rte_le16_t)(v) 10399a2dd95SBruce Richardson #define RTE_LE32(v) (rte_le32_t)(v) 10499a2dd95SBruce Richardson #define RTE_LE64(v) (rte_le64_t)(v) 10599a2dd95SBruce Richardson #else 10699a2dd95SBruce Richardson #error Unsupported endianness. 10799a2dd95SBruce Richardson #endif 10899a2dd95SBruce Richardson 10999a2dd95SBruce Richardson /* 11099a2dd95SBruce Richardson * The following types should be used when handling values according to a 11199a2dd95SBruce Richardson * specific byte ordering, which may differ from that of the host CPU. 11299a2dd95SBruce Richardson * 11399a2dd95SBruce Richardson * Libraries, public APIs and applications are encouraged to use them for 11499a2dd95SBruce Richardson * documentation purposes. 11599a2dd95SBruce Richardson */ 11699a2dd95SBruce Richardson typedef uint16_t rte_be16_t; /**< 16-bit big-endian value. */ 11799a2dd95SBruce Richardson typedef uint32_t rte_be32_t; /**< 32-bit big-endian value. */ 11899a2dd95SBruce Richardson typedef uint64_t rte_be64_t; /**< 64-bit big-endian value. */ 11999a2dd95SBruce Richardson typedef uint16_t rte_le16_t; /**< 16-bit little-endian value. */ 12099a2dd95SBruce Richardson typedef uint32_t rte_le32_t; /**< 32-bit little-endian value. */ 12199a2dd95SBruce Richardson typedef uint64_t rte_le64_t; /**< 64-bit little-endian value. */ 12299a2dd95SBruce Richardson 12399a2dd95SBruce Richardson /* 12499a2dd95SBruce Richardson * An internal function to swap bytes in a 16-bit value. 12599a2dd95SBruce Richardson * 12699a2dd95SBruce Richardson * It is used by rte_bswap16() when the value is constant. Do not use 12799a2dd95SBruce Richardson * this function directly; rte_bswap16() is preferred. 12899a2dd95SBruce Richardson */ 12999a2dd95SBruce Richardson static inline uint16_t 13099a2dd95SBruce Richardson rte_constant_bswap16(uint16_t x) 13199a2dd95SBruce Richardson { 13299a2dd95SBruce Richardson return (uint16_t)RTE_STATIC_BSWAP16(x); 13399a2dd95SBruce Richardson } 13499a2dd95SBruce Richardson 13599a2dd95SBruce Richardson /* 13699a2dd95SBruce Richardson * An internal function to swap bytes in a 32-bit value. 13799a2dd95SBruce Richardson * 13899a2dd95SBruce Richardson * It is used by rte_bswap32() when the value is constant. Do not use 13999a2dd95SBruce Richardson * this function directly; rte_bswap32() is preferred. 14099a2dd95SBruce Richardson */ 14199a2dd95SBruce Richardson static inline uint32_t 14299a2dd95SBruce Richardson rte_constant_bswap32(uint32_t x) 14399a2dd95SBruce Richardson { 14499a2dd95SBruce Richardson return (uint32_t)RTE_STATIC_BSWAP32(x); 14599a2dd95SBruce Richardson } 14699a2dd95SBruce Richardson 14799a2dd95SBruce Richardson /* 14899a2dd95SBruce Richardson * An internal function to swap bytes of a 64-bit value. 14999a2dd95SBruce Richardson * 15099a2dd95SBruce Richardson * It is used by rte_bswap64() when the value is constant. Do not use 15199a2dd95SBruce Richardson * this function directly; rte_bswap64() is preferred. 15299a2dd95SBruce Richardson */ 15399a2dd95SBruce Richardson static inline uint64_t 15499a2dd95SBruce Richardson rte_constant_bswap64(uint64_t x) 15599a2dd95SBruce Richardson { 15699a2dd95SBruce Richardson return (uint64_t)RTE_STATIC_BSWAP64(x); 15799a2dd95SBruce Richardson } 15899a2dd95SBruce Richardson 15999a2dd95SBruce Richardson 16099a2dd95SBruce Richardson #ifdef __DOXYGEN__ 16199a2dd95SBruce Richardson 16299a2dd95SBruce Richardson /** 16399a2dd95SBruce Richardson * Swap bytes in a 16-bit value. 16499a2dd95SBruce Richardson */ 16599a2dd95SBruce Richardson static uint16_t rte_bswap16(uint16_t _x); 16699a2dd95SBruce Richardson 16799a2dd95SBruce Richardson /** 16899a2dd95SBruce Richardson * Swap bytes in a 32-bit value. 16999a2dd95SBruce Richardson */ 17099a2dd95SBruce Richardson static uint32_t rte_bswap32(uint32_t x); 17199a2dd95SBruce Richardson 17299a2dd95SBruce Richardson /** 17399a2dd95SBruce Richardson * Swap bytes in a 64-bit value. 17499a2dd95SBruce Richardson */ 17599a2dd95SBruce Richardson static uint64_t rte_bswap64(uint64_t x); 17699a2dd95SBruce Richardson 17799a2dd95SBruce Richardson /** 17899a2dd95SBruce Richardson * Convert a 16-bit value from CPU order to little endian. 17999a2dd95SBruce Richardson */ 18099a2dd95SBruce Richardson static rte_le16_t rte_cpu_to_le_16(uint16_t x); 18199a2dd95SBruce Richardson 18299a2dd95SBruce Richardson /** 18399a2dd95SBruce Richardson * Convert a 32-bit value from CPU order to little endian. 18499a2dd95SBruce Richardson */ 18599a2dd95SBruce Richardson static rte_le32_t rte_cpu_to_le_32(uint32_t x); 18699a2dd95SBruce Richardson 18799a2dd95SBruce Richardson /** 18899a2dd95SBruce Richardson * Convert a 64-bit value from CPU order to little endian. 18999a2dd95SBruce Richardson */ 19099a2dd95SBruce Richardson static rte_le64_t rte_cpu_to_le_64(uint64_t x); 19199a2dd95SBruce Richardson 19299a2dd95SBruce Richardson 19399a2dd95SBruce Richardson /** 19499a2dd95SBruce Richardson * Convert a 16-bit value from CPU order to big endian. 19599a2dd95SBruce Richardson */ 19699a2dd95SBruce Richardson static rte_be16_t rte_cpu_to_be_16(uint16_t x); 19799a2dd95SBruce Richardson 19899a2dd95SBruce Richardson /** 19999a2dd95SBruce Richardson * Convert a 32-bit value from CPU order to big endian. 20099a2dd95SBruce Richardson */ 20199a2dd95SBruce Richardson static rte_be32_t rte_cpu_to_be_32(uint32_t x); 20299a2dd95SBruce Richardson 20399a2dd95SBruce Richardson /** 20499a2dd95SBruce Richardson * Convert a 64-bit value from CPU order to big endian. 20599a2dd95SBruce Richardson */ 20699a2dd95SBruce Richardson static rte_be64_t rte_cpu_to_be_64(uint64_t x); 20799a2dd95SBruce Richardson 20899a2dd95SBruce Richardson 20999a2dd95SBruce Richardson /** 21099a2dd95SBruce Richardson * Convert a 16-bit value from little endian to CPU order. 21199a2dd95SBruce Richardson */ 21299a2dd95SBruce Richardson static uint16_t rte_le_to_cpu_16(rte_le16_t x); 21399a2dd95SBruce Richardson 21499a2dd95SBruce Richardson /** 21599a2dd95SBruce Richardson * Convert a 32-bit value from little endian to CPU order. 21699a2dd95SBruce Richardson */ 21799a2dd95SBruce Richardson static uint32_t rte_le_to_cpu_32(rte_le32_t x); 21899a2dd95SBruce Richardson 21999a2dd95SBruce Richardson /** 22099a2dd95SBruce Richardson * Convert a 64-bit value from little endian to CPU order. 22199a2dd95SBruce Richardson */ 22299a2dd95SBruce Richardson static uint64_t rte_le_to_cpu_64(rte_le64_t x); 22399a2dd95SBruce Richardson 22499a2dd95SBruce Richardson 22599a2dd95SBruce Richardson /** 22699a2dd95SBruce Richardson * Convert a 16-bit value from big endian to CPU order. 22799a2dd95SBruce Richardson */ 22899a2dd95SBruce Richardson static uint16_t rte_be_to_cpu_16(rte_be16_t x); 22999a2dd95SBruce Richardson 23099a2dd95SBruce Richardson /** 23199a2dd95SBruce Richardson * Convert a 32-bit value from big endian to CPU order. 23299a2dd95SBruce Richardson */ 23399a2dd95SBruce Richardson static uint32_t rte_be_to_cpu_32(rte_be32_t x); 23499a2dd95SBruce Richardson 23599a2dd95SBruce Richardson /** 23699a2dd95SBruce Richardson * Convert a 64-bit value from big endian to CPU order. 23799a2dd95SBruce Richardson */ 23899a2dd95SBruce Richardson static uint64_t rte_be_to_cpu_64(rte_be64_t x); 23999a2dd95SBruce Richardson 24099a2dd95SBruce Richardson #endif /* __DOXYGEN__ */ 24199a2dd95SBruce Richardson 24299a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS 24316c7206cSTyler Retzlaff #ifndef RTE_TOOLCHAIN_MSVC 24499a2dd95SBruce Richardson #define rte_bswap16(x) __builtin_bswap16(x) 24599a2dd95SBruce Richardson 24699a2dd95SBruce Richardson #define rte_bswap32(x) __builtin_bswap32(x) 24799a2dd95SBruce Richardson 24899a2dd95SBruce Richardson #define rte_bswap64(x) __builtin_bswap64(x) 24916c7206cSTyler Retzlaff #else 25016c7206cSTyler Retzlaff #define rte_bswap16(x) _byteswap_ushort(x) 25199a2dd95SBruce Richardson 25216c7206cSTyler Retzlaff #define rte_bswap32(x) _byteswap_ulong(x) 25316c7206cSTyler Retzlaff 25416c7206cSTyler Retzlaff #define rte_bswap64(x) _byteswap_uint64(x) 25516c7206cSTyler Retzlaff #endif 25699a2dd95SBruce Richardson #endif 25799a2dd95SBruce Richardson 258*719834a6SMattias Rönnblom #ifdef __cplusplus 259*719834a6SMattias Rönnblom } 260*719834a6SMattias Rönnblom #endif 261*719834a6SMattias Rönnblom 26299a2dd95SBruce Richardson #endif /* _RTE_BYTEORDER_H_ */ 263