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_ */