master
1/* $NetBSD: endian.h,v 1.31.4.1 2024/10/11 19:07:20 martin Exp $ */
2
3/*
4 * Copyright (c) 1987, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)endian.h 8.1 (Berkeley) 6/11/93
32 */
33
34#ifndef _SYS_ENDIAN_H_
35#define _SYS_ENDIAN_H_
36
37#include <sys/featuretest.h>
38
39/*
40 * Definitions for byte order, according to byte significance from low
41 * address to high.
42 */
43#define _LITTLE_ENDIAN 1234 /* LSB first: i386, vax */
44#define _BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */
45#define _PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */
46
47
48#if defined(_XOPEN_SOURCE) || \
49 (_POSIX_C_SOURCE - 0) >= 200112L || \
50 defined(_NETBSD_SOURCE)
51#ifndef _LOCORE
52
53/* C-family endian-ness definitions */
54
55#include <sys/ansi.h>
56#include <sys/cdefs.h>
57#include <sys/stdint.h>
58
59#ifndef in_addr_t
60typedef __in_addr_t in_addr_t;
61#define in_addr_t __in_addr_t
62#endif
63
64#ifndef in_port_t
65typedef __in_port_t in_port_t;
66#define in_port_t __in_port_t
67#endif
68
69__BEGIN_DECLS
70uint32_t htonl(uint32_t) __constfunc;
71uint16_t htons(uint16_t) __constfunc;
72uint32_t ntohl(uint32_t) __constfunc;
73uint16_t ntohs(uint16_t) __constfunc;
74__END_DECLS
75
76#endif /* !_LOCORE */
77#endif /* _XOPEN_SOURCE || _POSIX_C_SOURCE >= 200112L || _NETBSD_SOURCE */
78
79
80#include <machine/endian_machdep.h>
81
82/*
83 * Define the order of 32-bit words in 64-bit words.
84 */
85#if _BYTE_ORDER == _LITTLE_ENDIAN
86#define _QUAD_HIGHWORD 1
87#define _QUAD_LOWWORD 0
88#endif
89
90#if _BYTE_ORDER == _BIG_ENDIAN
91#define _QUAD_HIGHWORD 0
92#define _QUAD_LOWWORD 1
93#endif
94
95
96#if defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE)
97/*
98 * Traditional names for byteorder. These are defined as the numeric
99 * sequences so that third party code can "#define XXX_ENDIAN" and not
100 * cause errors.
101 */
102#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */
103#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */
104#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */
105#define BYTE_ORDER _BYTE_ORDER
106
107#ifndef _LOCORE
108
109#include <machine/bswap.h>
110
111/*
112 * Macros for network/external number representation conversion.
113 */
114#if BYTE_ORDER == BIG_ENDIAN && !defined(__lint__)
115#define ntohl(x) (x)
116#define ntohs(x) (x)
117#define htonl(x) (x)
118#define htons(x) (x)
119
120#define NTOHL(x) (void) (x)
121#define NTOHS(x) (void) (x)
122#define HTONL(x) (void) (x)
123#define HTONS(x) (void) (x)
124
125#else /* LITTLE_ENDIAN || defined(__lint__) */
126
127#define ntohl(x) bswap32(__CAST(uint32_t, (x)))
128#define ntohs(x) bswap16(__CAST(uint16_t, (x)))
129#define htonl(x) bswap32(__CAST(uint32_t, (x)))
130#define htons(x) bswap16(__CAST(uint16_t, (x)))
131
132#define NTOHL(x) (x) = ntohl(__CAST(uint32_t, (x)))
133#define NTOHS(x) (x) = ntohs(__CAST(uint16_t, (x)))
134#define HTONL(x) (x) = htonl(__CAST(uint32_t, (x)))
135#define HTONS(x) (x) = htons(__CAST(uint16_t, (x)))
136#endif /* LITTLE_ENDIAN || defined(__lint__) */
137
138/*
139 * Macros to convert to a specific endianness.
140 */
141
142#if BYTE_ORDER == BIG_ENDIAN
143
144#define htobe16(x) (x)
145#define htobe32(x) (x)
146#define htobe64(x) (x)
147#define htole16(x) bswap16(__CAST(uint16_t, (x)))
148#define htole32(x) bswap32(__CAST(uint32_t, (x)))
149#define htole64(x) bswap64(__CAST(uint64_t, (x)))
150
151#define HTOBE16(x) __CAST(void, (x))
152#define HTOBE32(x) __CAST(void, (x))
153#define HTOBE64(x) __CAST(void, (x))
154#define HTOLE16(x) (x) = bswap16(__CAST(uint16_t, (x)))
155#define HTOLE32(x) (x) = bswap32(__CAST(uint32_t, (x)))
156#define HTOLE64(x) (x) = bswap64(__CAST(uint64_t, (x)))
157
158#else /* LITTLE_ENDIAN */
159
160#define htobe16(x) bswap16(__CAST(uint16_t, (x)))
161#define htobe32(x) bswap32(__CAST(uint32_t, (x)))
162#define htobe64(x) bswap64(__CAST(uint64_t, (x)))
163#define htole16(x) (x)
164#define htole32(x) (x)
165#define htole64(x) (x)
166
167#define HTOBE16(x) (x) = bswap16(__CAST(uint16_t, (x)))
168#define HTOBE32(x) (x) = bswap32(__CAST(uint32_t, (x)))
169#define HTOBE64(x) (x) = bswap64(__CAST(uint64_t, (x)))
170#define HTOLE16(x) __CAST(void, (x))
171#define HTOLE32(x) __CAST(void, (x))
172#define HTOLE64(x) __CAST(void, (x))
173
174#endif /* LITTLE_ENDIAN */
175
176#define be16toh(x) htobe16(x)
177#define be32toh(x) htobe32(x)
178#define be64toh(x) htobe64(x)
179#define le16toh(x) htole16(x)
180#define le32toh(x) htole32(x)
181#define le64toh(x) htole64(x)
182
183#define BE16TOH(x) HTOBE16(x)
184#define BE32TOH(x) HTOBE32(x)
185#define BE64TOH(x) HTOBE64(x)
186#define LE16TOH(x) HTOLE16(x)
187#define LE32TOH(x) HTOLE32(x)
188#define LE64TOH(x) HTOLE64(x)
189
190/*
191 * Routines to encode/decode big- and little-endian multi-octet values
192 * to/from an octet stream.
193 */
194
195#ifdef _NETBSD_SOURCE
196
197#if __GNUC_PREREQ__(2, 95)
198
199#define __GEN_ENDIAN_ENC(bits, endian) \
200static __inline void __unused \
201endian ## bits ## enc(void *dst, uint ## bits ## _t u) \
202{ \
203 u = hto ## endian ## bits (u); \
204 __builtin_memcpy(dst, &u, sizeof(u)); \
205}
206
207__GEN_ENDIAN_ENC(16, be)
208__GEN_ENDIAN_ENC(32, be)
209__GEN_ENDIAN_ENC(64, be)
210__GEN_ENDIAN_ENC(16, le)
211__GEN_ENDIAN_ENC(32, le)
212__GEN_ENDIAN_ENC(64, le)
213#undef __GEN_ENDIAN_ENC
214
215#define __GEN_ENDIAN_DEC(bits, endian) \
216static __inline uint ## bits ## _t __unused \
217endian ## bits ## dec(const void *buf) \
218{ \
219 uint ## bits ## _t u; \
220 __builtin_memcpy(&u, buf, sizeof(u)); \
221 return endian ## bits ## toh (u); \
222}
223
224__GEN_ENDIAN_DEC(16, be)
225__GEN_ENDIAN_DEC(32, be)
226__GEN_ENDIAN_DEC(64, be)
227__GEN_ENDIAN_DEC(16, le)
228__GEN_ENDIAN_DEC(32, le)
229__GEN_ENDIAN_DEC(64, le)
230#undef __GEN_ENDIAN_DEC
231
232#else /* !(GCC >= 2.95) */
233
234static __inline void __unused
235be16enc(void *buf, uint16_t u)
236{
237 uint8_t *p = __CAST(uint8_t *, buf);
238
239 p[0] = __CAST(uint8_t, ((__CAST(unsigned, u) >> 8) & 0xff));
240 p[1] = __CAST(uint8_t, (u & 0xff));
241}
242
243static __inline void __unused
244le16enc(void *buf, uint16_t u)
245{
246 uint8_t *p = __CAST(uint8_t *, buf);
247
248 p[0] = __CAST(uint8_t, (u & 0xff));
249 p[1] = __CAST(uint8_t, ((__CAST(unsigned, u) >> 8) & 0xff));
250}
251
252static __inline uint16_t __unused
253be16dec(const void *buf)
254{
255 const uint8_t *p = __CAST(const uint8_t *, buf);
256
257 return ((__CAST(uint16_t, p[0]) << 8) | p[1]);
258}
259
260static __inline uint16_t __unused
261le16dec(const void *buf)
262{
263 const uint8_t *p = __CAST(const uint8_t *, buf);
264
265 return (p[0] | (__CAST(uint16_t, p[1]) << 8));
266}
267
268static __inline void __unused
269be32enc(void *buf, uint32_t u)
270{
271 uint8_t *p = __CAST(uint8_t *, buf);
272
273 p[0] = __CAST(uint8_t, ((u >> 24) & 0xff));
274 p[1] = __CAST(uint8_t, ((u >> 16) & 0xff));
275 p[2] = __CAST(uint8_t, ((u >> 8) & 0xff));
276 p[3] = __CAST(uint8_t, (u & 0xff));
277}
278
279static __inline void __unused
280le32enc(void *buf, uint32_t u)
281{
282 uint8_t *p = __CAST(uint8_t *, buf);
283
284 p[0] = __CAST(uint8_t, (u & 0xff));
285 p[1] = __CAST(uint8_t, ((u >> 8) & 0xff));
286 p[2] = __CAST(uint8_t, ((u >> 16) & 0xff));
287 p[3] = __CAST(uint8_t, ((u >> 24) & 0xff));
288}
289
290static __inline uint32_t __unused
291be32dec(const void *buf)
292{
293 const uint8_t *p = __CAST(const uint8_t *, buf);
294
295 return ((__CAST(uint32_t, be16dec(p)) << 16) | be16dec(p + 2));
296}
297
298static __inline uint32_t __unused
299le32dec(const void *buf)
300{
301 const uint8_t *p = __CAST(const uint8_t *, buf);
302
303 return (le16dec(p) | (__CAST(uint32_t, le16dec(p + 2)) << 16));
304}
305
306static __inline void __unused
307be64enc(void *buf, uint64_t u)
308{
309 uint8_t *p = __CAST(uint8_t *, buf);
310
311 be32enc(p, __CAST(uint32_t, (u >> 32)));
312 be32enc(p + 4, __CAST(uint32_t, (u & 0xffffffffULL)));
313}
314
315static __inline void __unused
316le64enc(void *buf, uint64_t u)
317{
318 uint8_t *p = __CAST(uint8_t *, buf);
319
320 le32enc(p, __CAST(uint32_t, (u & 0xffffffffULL)));
321 le32enc(p + 4, __CAST(uint32_t, (u >> 32)));
322}
323
324static __inline uint64_t __unused
325be64dec(const void *buf)
326{
327 const uint8_t *p = (const uint8_t *)buf;
328
329 return ((__CAST(uint64_t, be32dec(p)) << 32) | be32dec(p + 4));
330}
331
332static __inline uint64_t __unused
333le64dec(const void *buf)
334{
335 const uint8_t *p = (const uint8_t *)buf;
336
337 return (le32dec(p) | (__CAST(uint64_t, le32dec(p + 4)) << 32));
338}
339
340#endif /* GCC >= 2.95 */
341
342#endif /* _NETBSD_SOURCE */
343
344#endif /* !_LOCORE */
345#endif /* _XOPEN_SOURCE || _NETBSD_SOURCE */
346#endif /* !_SYS_ENDIAN_H_ */