1 /**	$MirOS: src/sys/sys/endian.h,v 1.4 2008/11/08 23:04:24 tg Exp $ */
2 /*	$OpenBSD: endian.h,v 1.14 2004/01/11 19:17:31 brad Exp $	*/
3 
4 /*-
5  * Copyright (c) 2004, 2006
6  *	Thorsten "mirabilos" Glaser <tg@mirbsd.org>
7  * Copyright (c) 1997 Niklas Hallqvist.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * Generic definitions for little- and big-endian systems.  Other endianesses
32  * has to be dealt with in the specific machine/endian.h file for that port.
33  *
34  * This file is meant to be included from a little- or big-endian port's
35  * machine/endian.h after setting BYTE_ORDER to either 1234 for little endian
36  * or 4321 for big..
37  */
38 
39 #ifndef _SYS_ENDIAN_H_
40 #define _SYS_ENDIAN_H_
41 
42 #ifndef _POSIX_SOURCE
43 
44 #include <sys/cdefs.h>
45 
46 #define LITTLE_ENDIAN	1234
47 #define BIG_ENDIAN	4321
48 #define PDP_ENDIAN	3412
49 
50 #ifdef __GNUC__
51 
52 #define __swap16gen(x) __extension__({					\
53 	u_int16_t __swap16gen_x = (x);					\
54 									\
55 	(u_int16_t)((__swap16gen_x & 0xff) << 8 |			\
56 	    (__swap16gen_x & 0xff00) >> 8);				\
57 })
58 
59 #define __swap32gen(x) __extension__({					\
60 	u_int32_t __swap32gen_x = (x);					\
61 									\
62 	(u_int32_t)((__swap32gen_x & 0xff) << 24 |			\
63 	    (__swap32gen_x & 0xff00) << 8 |				\
64 	    (__swap32gen_x & 0xff0000) >> 8 |				\
65 	    (__swap32gen_x & 0xff000000) >> 24);			\
66 })
67 
68 #define __swap64gen(x) __extension__({					\
69 	u_int64_t __swap64gen_x = (x);					\
70 									\
71 	(u_int64_t)((__swap64gen_x & 0xff) << 56 |			\
72 	    (__swap64gen_x & 0xff00ULL) << 40 |				\
73 	    (__swap64gen_x & 0xff0000ULL) << 24 |			\
74 	    (__swap64gen_x & 0xff000000ULL) << 8 |			\
75 	    (__swap64gen_x & 0xff00000000ULL) >> 8 |			\
76 	    (__swap64gen_x & 0xff0000000000ULL) >> 24 |			\
77 	    (__swap64gen_x & 0xff000000000000ULL) >> 40 |		\
78 	    (__swap64gen_x & 0xff00000000000000ULL) >> 56);		\
79 })
80 
81 #else /* __GNUC__ */
82 
83 /* Note that these macros evaluate their arguments several times.  */
84 #define __swap16gen(x)							\
85     (u_int16_t)(((u_int16_t)(x) & 0xff) << 8 | ((u_int16_t)(x) & 0xff00) >> 8)
86 
87 #define __swap32gen(x)							\
88     (u_int32_t)(((u_int32_t)(x) & 0xff) << 24 |				\
89     ((u_int32_t)(x) & 0xff00) << 8 | ((u_int32_t)(x) & 0xff0000) >> 8 |	\
90     ((u_int32_t)(x) & 0xff000000) >> 24)
91 
92 #define __swap64gen(x)							\
93 	(u_int64_t)((((u_int64_t)(x) & 0xff) << 56) |			\
94 	    ((u_int64_t)(x) & 0xff00ULL) << 40 |			\
95 	    ((u_int64_t)(x) & 0xff0000ULL) << 24 |			\
96 	    ((u_int64_t)(x) & 0xff000000ULL) << 8 |			\
97 	    ((u_int64_t)(x) & 0xff00000000ULL) >> 8 |			\
98 	    ((u_int64_t)(x) & 0xff0000000000ULL) >> 24 |		\
99 	    ((u_int64_t)(x) & 0xff000000000000ULL) >> 40 |		\
100 	    ((u_int64_t)(x) & 0xff00000000000000ULL) >> 56)
101 
102 #endif /* __GNUC__ */
103 
104 /*
105  * Define MD_SWAP if you provide swap{16,32}md functions/macros that are
106  * optimized for your architecture,  These will be used for swap{16,32}
107  * unless the argument is a constant and we are using GCC, where we can
108  * take advantage of the CSE phase much better by using the generic version.
109  */
110 #ifdef MD_SWAP
111 #if __GNUC__
112 
113 #define swap16(x) __extension__({					\
114 	u_int16_t __swap16_x = (x);					\
115 									\
116 	__builtin_constant_p(x) ? __swap16gen(__swap16_x) :		\
117 	    __swap16md(__swap16_x);					\
118 })
119 
120 #define swap32(x) __extension__({					\
121 	u_int32_t __swap32_x = (x);					\
122 									\
123 	__builtin_constant_p(x) ? __swap32gen(__swap32_x) :		\
124 	    __swap32md(__swap32_x);					\
125 })
126 
127 #define swap64(x) __extension__({					\
128 	u_int64_t __swap64_x = (x);					\
129 									\
130 	__builtin_constant_p(x) ? __swap64gen(__swap64_x) :		\
131 	    __swap64md(__swap64_x);					\
132 })
133 
134 #endif /* __GNUC__ */
135 
136 #else /* MD_SWAP */
137 #define swap16 __swap16gen
138 #define swap32 __swap32gen
139 #define swap64 __swap64gen
140 #endif /* MD_SWAP */
141 
142 #define swap16_multi(v, n) do {						\
143 	size_t __swap16_multi_n = (n);					\
144 	u_int16_t *__swap16_multi_v = (v);				\
145 									\
146 	while (__swap16_multi_n) {					\
147 		*__swap16_multi_v = swap16(*__swap16_multi_v);		\
148 		__swap16_multi_v++;					\
149 		__swap16_multi_n--;					\
150 	}								\
151 } while (0)
152 
153 __BEGIN_DECLS
154 u_int64_t	htobe64(u_int64_t);
155 u_int32_t	htobe32(u_int32_t);
156 u_int16_t	htobe16(u_int16_t);
157 u_int64_t	betoh64(u_int64_t);
158 u_int32_t	betoh32(u_int32_t);
159 u_int16_t	betoh16(u_int16_t);
160 
161 u_int64_t	htole64(u_int64_t);
162 u_int32_t	htole32(u_int32_t);
163 u_int16_t	htole16(u_int16_t);
164 u_int64_t	letoh64(u_int64_t);
165 u_int32_t	letoh32(u_int32_t);
166 u_int16_t	letoh16(u_int16_t);
167 __END_DECLS
168 
169 #if BYTE_ORDER == LITTLE_ENDIAN
170 
171 /* Can be overridden by machine/endian.h before inclusion of this file.  */
172 #ifndef _QUAD_HIGHWORD
173 #define _QUAD_HIGHWORD 1
174 #endif
175 #ifndef _QUAD_LOWWORD
176 #define _QUAD_LOWWORD 0
177 #endif
178 
179 #define htobe16 swap16
180 #define htobe32 swap32
181 #define htobe64 swap64
182 #define betoh16 swap16
183 #define betoh32 swap32
184 #define betoh64 swap64
185 
186 #define htole16(x) ((uint16_t)(x))
187 #define htole32(x) ((uint32_t)(x))
188 #define htole64(x) ((uint64_t)(x))
189 #define letoh16(x) ((uint16_t)(x))
190 #define letoh32(x) ((uint32_t)(x))
191 #define letoh64(x) ((uint64_t)(x))
192 
193 #endif /* BYTE_ORDER */
194 
195 #if BYTE_ORDER == BIG_ENDIAN
196 
197 /* Can be overridden by machine/endian.h before inclusion of this file.  */
198 #ifndef _QUAD_HIGHWORD
199 #define _QUAD_HIGHWORD 0
200 #endif
201 #ifndef _QUAD_LOWWORD
202 #define _QUAD_LOWWORD 1
203 #endif
204 
205 #define htole16 swap16
206 #define htole32 swap32
207 #define htole64 swap64
208 #define letoh16 swap16
209 #define letoh32 swap32
210 #define letoh64 swap64
211 
212 #define htobe16(x) ((uint16_t)(x))
213 #define htobe32(x) ((uint32_t)(x))
214 #define htobe64(x) ((uint64_t)(x))
215 #define betoh16(x) ((uint16_t)(x))
216 #define betoh32(x) ((uint32_t)(x))
217 #define betoh64(x) ((uint64_t)(x))
218 
219 #endif /* BYTE_ORDER */
220 
221 #if BYTE_ORDER == PDP_ENDIAN
222 #error You are crazy. Go away.
223 #endif /* BYTE_ORDER */
224 
225 #define	bswap16		swap16
226 #define	bswap32		swap32
227 #define	bswap64		swap64
228 
229 #define	htons		htobe16
230 #define	htonl		htobe32
231 #define	ntohs		betoh16
232 #define	ntohl		betoh32
233 
234 #define	be16toh		betoh16
235 #define	be32toh		betoh32
236 #define	be64toh		betoh64
237 #define	le16toh		letoh16
238 #define	le32toh		letoh32
239 #define	le64toh		letoh64
240 
241 #define	NTOHL(x)	(x) = ntohl((u_int32_t)(x))
242 #define	NTOHS(x)	(x) = ntohs((u_int16_t)(x))
243 #define	HTONL(x)	(x) = htonl((u_int32_t)(x))
244 #define	HTONS(x)	(x) = htons((u_int16_t)(x))
245 
246 #define	BE16TOH(x)	(x) = be16toh((u_int16_t)(x))
247 #define	BE32TOH(x)	(x) = be32toh((u_int32_t)(x))
248 #define	BE64TOH(x)	(x) = be64toh((u_int64_t)(x))
249 #define	HTOBE16(x)	(x) = htobe16((u_int16_t)(x))
250 #define	HTOBE32(x)	(x) = htobe32((u_int32_t)(x))
251 #define	HTOBE64(x)	(x) = htobe64((u_int64_t)(x))
252 #define	LE16TOH(x)	(x) = le16toh((u_int16_t)(x))
253 #define	LE32TOH(x)	(x) = le32toh((u_int32_t)(x))
254 #define	LE64TOH(x)	(x) = le64toh((u_int64_t)(x))
255 #define	HTOLE16(x)	(x) = htole16((u_int16_t)(x))
256 #define	HTOLE32(x)	(x) = htole32((u_int32_t)(x))
257 #define	HTOLE64(x)	(x) = htole64((u_int64_t)(x))
258 
259 #endif /* _POSIX_SOURCE */
260 #endif /* _SYS_ENDIAN_H_ */
261