xref: /dpdk/lib/eal/include/generic/rte_byteorder.h (revision 719834a6849e1daf4a70ff7742bbcc3ae7e25607)
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