1/* $NetBSD: bswap.h,v 1.19.56.1 2025/11/28 10:58:02 martin Exp $ */
2
3/* Written by Manuel Bouyer. Public domain */
4
5#ifndef _SYS_BSWAP_H_
6#define _SYS_BSWAP_H_
7
8#ifndef _LOCORE
9#include <sys/stdint.h>
10
11#include <machine/bswap.h>
12
13__BEGIN_DECLS
14/* Always declare the functions in case their address is taken (etc) */
15#if defined(_KERNEL) || defined(_STANDALONE) || !defined(__BSWAP_RENAME)
16uint16_t bswap16(uint16_t) __constfunc;
17uint32_t bswap32(uint32_t) __constfunc;
18#else
19uint16_t bswap16(uint16_t) __RENAME(__bswap16) __constfunc;
20uint32_t bswap32(uint32_t) __RENAME(__bswap32) __constfunc;
21#endif
22uint64_t bswap64(uint64_t) __constfunc;
23__END_DECLS
24
25#if defined(__GNUC__) && !defined(__lint__)
26
27#define __byte_swap_u64_constexpr(x) \
28 (__CAST(uint64_t, \
29 ((((x) & 0xff00000000000000ull) >> 56) | \
30 (((x) & 0x00ff000000000000ull) >> 40) | \
31 (((x) & 0x0000ff0000000000ull) >> 24) | \
32 (((x) & 0x000000ff00000000ull) >> 8) | \
33 (((x) & 0x00000000ff000000ull) << 8) | \
34 (((x) & 0x0000000000ff0000ull) << 24) | \
35 (((x) & 0x000000000000ff00ull) << 40) | \
36 (((x) & 0x00000000000000ffull) << 56))))
37
38#define __byte_swap_u32_constexpr(x) \
39 (__CAST(uint32_t, \
40 ((((x) & 0xff000000) >> 24) | \
41 (((x) & 0x00ff0000) >> 8) | \
42 (((x) & 0x0000ff00) << 8) | \
43 (((x) & 0x000000ff) << 24))))
44
45#define __byte_swap_u16_constexpr(x) \
46 (__CAST(uint16_t, \
47 ((((x) & 0xff00) >> 8) | \
48 (((x) & 0x00ff) << 8))))
49
50/*
51 * The compiler always generates an expensive function call to bswap
52 * on some architectures, we want the inline versions there.
53 */
54#ifdef __HAVE_SLOW_BSWAP_BUILTIN
55
56static __inline uint64_t __byte_swap_u64_inline(uint64_t x) {
57 return __byte_swap_u64_constexpr(x);
58}
59
60static __inline uint32_t __byte_swap_u32_inline(uint32_t x) {
61 return __byte_swap_u32_constexpr(x);
62}
63
64static __inline uint16_t __byte_swap_u16_inline(uint16_t x) {
65 return __byte_swap_u16_constexpr(x);
66}
67
68#define __BYTE_SWAP_U64_VARIABLE __byte_swap_u64_inline
69#define __BYTE_SWAP_U32_VARIABLE __byte_swap_u32_inline
70#define __BYTE_SWAP_U16_VARIABLE __byte_swap_u16_inline
71
72#else /* !__HAVE_SLOW_BSWAP_BUILTIN */
73
74/* allow machine/bswap.h to override these with inline versions */
75#ifndef __BYTE_SWAP_U64_VARIABLE
76#define __BYTE_SWAP_U64_VARIABLE bswap64
77#endif
78
79#ifndef __BYTE_SWAP_U32_VARIABLE
80#define __BYTE_SWAP_U32_VARIABLE bswap32
81#endif
82
83#ifndef __BYTE_SWAP_U16_VARIABLE
84#define __BYTE_SWAP_U16_VARIABLE bswap16
85#endif
86
87#endif /* __HAVE_SLOW_BSWAP_BUILTIN */
88
89#define bswap64(x) \
90 __CAST(uint64_t, __builtin_constant_p((x)) ? \
91 __byte_swap_u64_constexpr(x) : __BYTE_SWAP_U64_VARIABLE(x))
92
93#define bswap32(x) \
94 __CAST(uint32_t, __builtin_constant_p((x)) ? \
95 __byte_swap_u32_constexpr(x) : __BYTE_SWAP_U32_VARIABLE(x))
96
97#define bswap16(x) \
98 __CAST(uint16_t, __builtin_constant_p((x)) ? \
99 __byte_swap_u16_constexpr(x) : __BYTE_SWAP_U16_VARIABLE(x))
100
101#endif /* __GNUC__ && !__lint__ */
102#endif /* !_LOCORE */
103
104#endif /* !_SYS_BSWAP_H_ */