1 /*
2  * Byte order utilities
3  *
4  * Copyright (C) 1999-2013, Broadcom Corporation
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  *  $Id: bcmendian.h 241182 2011-02-17 21:50:03Z $
19  *
20  * This file by default provides proper behavior on little-endian architectures.
21  * On big-endian architectures, IL_BIGENDIAN should be defined.
22  */
23 
24 #ifndef _BCMENDIAN_H_
25 #define _BCMENDIAN_H_
26 
27 #include <typedefs.h>
28 
29 /* Reverse the bytes in a 16-bit value */
30 #define BCMSWAP16(val) \
31 	((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \
32 		  (((uint16)(val) & (uint16)0xff00U) >> 8)))
33 
34 /* Reverse the bytes in a 32-bit value */
35 #define BCMSWAP32(val) \
36 	((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \
37 		  (((uint32)(val) & (uint32)0x0000ff00U) <<  8) | \
38 		  (((uint32)(val) & (uint32)0x00ff0000U) >>  8) | \
39 		  (((uint32)(val) & (uint32)0xff000000U) >> 24)))
40 
41 /* Reverse the two 16-bit halves of a 32-bit value */
42 #define BCMSWAP32BY16(val) \
43 	((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \
44 		  (((uint32)(val) & (uint32)0xffff0000U) >> 16)))
45 
46 /* Byte swapping macros
47  *    Host <=> Network (Big Endian) for 16- and 32-bit values
48  *    Host <=> Little-Endian for 16- and 32-bit values
49  */
50 #ifndef hton16
51 #define HTON16(i) BCMSWAP16(i)
52 #define	hton16(i) bcmswap16(i)
53 #define	HTON32(i) BCMSWAP32(i)
54 #define	hton32(i) bcmswap32(i)
55 #define	NTOH16(i) BCMSWAP16(i)
56 #define	ntoh16(i) bcmswap16(i)
57 #define	NTOH32(i) BCMSWAP32(i)
58 #define	ntoh32(i) bcmswap32(i)
59 #define LTOH16(i) (i)
60 #define ltoh16(i) (i)
61 #define LTOH32(i) (i)
62 #define ltoh32(i) (i)
63 #define HTOL16(i) (i)
64 #define htol16(i) (i)
65 #define HTOL32(i) (i)
66 #define htol32(i) (i)
67 #endif /* hton16 */
68 
69 #define ltoh16_buf(buf, i)
70 #define htol16_buf(buf, i)
71 
72 /* Unaligned loads and stores in host byte order */
73 #define load32_ua(a)		ltoh32_ua(a)
74 #define store32_ua(a, v)	htol32_ua_store(v, a)
75 #define load16_ua(a)		ltoh16_ua(a)
76 #define store16_ua(a, v)	htol16_ua_store(v, a)
77 
78 #define _LTOH16_UA(cp)	((cp)[0] | ((cp)[1] << 8))
79 #define _LTOH32_UA(cp)	((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24))
80 #define _NTOH16_UA(cp)	(((cp)[0] << 8) | (cp)[1])
81 #define _NTOH32_UA(cp)	(((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3])
82 
83 #define ltoh_ua(ptr) \
84 	(sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
85 	 sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \
86 	 sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \
87 	 *(uint8 *)0)
88 
89 #define ntoh_ua(ptr) \
90 	(sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
91 	 sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \
92 	 sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \
93 	 *(uint8 *)0)
94 
95 #ifdef __GNUC__
96 
97 /* GNU macro versions avoid referencing the argument multiple times, while also
98  * avoiding the -fno-inline used in ROM builds.
99  */
100 
101 #define bcmswap16(val) ({ \
102 	uint16 _val = (val); \
103 	BCMSWAP16(_val); \
104 })
105 
106 #define bcmswap32(val) ({ \
107 	uint32 _val = (val); \
108 	BCMSWAP32(_val); \
109 })
110 
111 #define bcmswap32by16(val) ({ \
112 	uint32 _val = (val); \
113 	BCMSWAP32BY16(_val); \
114 })
115 
116 #define bcmswap16_buf(buf, len) ({ \
117 	uint16 *_buf = (uint16 *)(buf); \
118 	uint _wds = (len) / 2; \
119 	while (_wds--) { \
120 		*_buf = bcmswap16(*_buf); \
121 		_buf++; \
122 	} \
123 })
124 
125 #define htol16_ua_store(val, bytes) ({ \
126 	uint16 _val = (val); \
127 	uint8 *_bytes = (uint8 *)(bytes); \
128 	_bytes[0] = _val & 0xff; \
129 	_bytes[1] = _val >> 8; \
130 })
131 
132 #define htol32_ua_store(val, bytes) ({ \
133 	uint32 _val = (val); \
134 	uint8 *_bytes = (uint8 *)(bytes); \
135 	_bytes[0] = _val & 0xff; \
136 	_bytes[1] = (_val >> 8) & 0xff; \
137 	_bytes[2] = (_val >> 16) & 0xff; \
138 	_bytes[3] = _val >> 24; \
139 })
140 
141 #define hton16_ua_store(val, bytes) ({ \
142 	uint16 _val = (val); \
143 	uint8 *_bytes = (uint8 *)(bytes); \
144 	_bytes[0] = _val >> 8; \
145 	_bytes[1] = _val & 0xff; \
146 })
147 
148 #define hton32_ua_store(val, bytes) ({ \
149 	uint32 _val = (val); \
150 	uint8 *_bytes = (uint8 *)(bytes); \
151 	_bytes[0] = _val >> 24; \
152 	_bytes[1] = (_val >> 16) & 0xff; \
153 	_bytes[2] = (_val >> 8) & 0xff; \
154 	_bytes[3] = _val & 0xff; \
155 })
156 
157 #define ltoh16_ua(bytes) ({ \
158 	const uint8 *_bytes = (const uint8 *)(bytes); \
159 	_LTOH16_UA(_bytes); \
160 })
161 
162 #define ltoh32_ua(bytes) ({ \
163 	const uint8 *_bytes = (const uint8 *)(bytes); \
164 	_LTOH32_UA(_bytes); \
165 })
166 
167 #define ntoh16_ua(bytes) ({ \
168 	const uint8 *_bytes = (const uint8 *)(bytes); \
169 	_NTOH16_UA(_bytes); \
170 })
171 
172 #define ntoh32_ua(bytes) ({ \
173 	const uint8 *_bytes = (const uint8 *)(bytes); \
174 	_NTOH32_UA(_bytes); \
175 })
176 
177 #else /* !__GNUC__ */
178 
179 /* Inline versions avoid referencing the argument multiple times */
180 static INLINE uint16
bcmswap16(uint16 val)181 bcmswap16(uint16 val)
182 {
183 	return BCMSWAP16(val);
184 }
185 
186 static INLINE uint32
bcmswap32(uint32 val)187 bcmswap32(uint32 val)
188 {
189 	return BCMSWAP32(val);
190 }
191 
192 static INLINE uint32
bcmswap32by16(uint32 val)193 bcmswap32by16(uint32 val)
194 {
195 	return BCMSWAP32BY16(val);
196 }
197 
198 /* Reverse pairs of bytes in a buffer (not for high-performance use) */
199 /* buf	- start of buffer of shorts to swap */
200 /* len  - byte length of buffer */
201 static INLINE void
bcmswap16_buf(uint16 * buf,uint len)202 bcmswap16_buf(uint16 *buf, uint len)
203 {
204 	len = len / 2;
205 
206 	while (len--) {
207 		*buf = bcmswap16(*buf);
208 		buf++;
209 	}
210 }
211 
212 /*
213  * Store 16-bit value to unaligned little-endian byte array.
214  */
215 static INLINE void
htol16_ua_store(uint16 val,uint8 * bytes)216 htol16_ua_store(uint16 val, uint8 *bytes)
217 {
218 	bytes[0] = val & 0xff;
219 	bytes[1] = val >> 8;
220 }
221 
222 /*
223  * Store 32-bit value to unaligned little-endian byte array.
224  */
225 static INLINE void
htol32_ua_store(uint32 val,uint8 * bytes)226 htol32_ua_store(uint32 val, uint8 *bytes)
227 {
228 	bytes[0] = val & 0xff;
229 	bytes[1] = (val >> 8) & 0xff;
230 	bytes[2] = (val >> 16) & 0xff;
231 	bytes[3] = val >> 24;
232 }
233 
234 /*
235  * Store 16-bit value to unaligned network-(big-)endian byte array.
236  */
237 static INLINE void
hton16_ua_store(uint16 val,uint8 * bytes)238 hton16_ua_store(uint16 val, uint8 *bytes)
239 {
240 	bytes[0] = val >> 8;
241 	bytes[1] = val & 0xff;
242 }
243 
244 /*
245  * Store 32-bit value to unaligned network-(big-)endian byte array.
246  */
247 static INLINE void
hton32_ua_store(uint32 val,uint8 * bytes)248 hton32_ua_store(uint32 val, uint8 *bytes)
249 {
250 	bytes[0] = val >> 24;
251 	bytes[1] = (val >> 16) & 0xff;
252 	bytes[2] = (val >> 8) & 0xff;
253 	bytes[3] = val & 0xff;
254 }
255 
256 /*
257  * Load 16-bit value from unaligned little-endian byte array.
258  */
259 static INLINE uint16
ltoh16_ua(const void * bytes)260 ltoh16_ua(const void *bytes)
261 {
262 	return _LTOH16_UA((const uint8 *)bytes);
263 }
264 
265 /*
266  * Load 32-bit value from unaligned little-endian byte array.
267  */
268 static INLINE uint32
ltoh32_ua(const void * bytes)269 ltoh32_ua(const void *bytes)
270 {
271 	return _LTOH32_UA((const uint8 *)bytes);
272 }
273 
274 /*
275  * Load 16-bit value from unaligned big-(network-)endian byte array.
276  */
277 static INLINE uint16
ntoh16_ua(const void * bytes)278 ntoh16_ua(const void *bytes)
279 {
280 	return _NTOH16_UA((const uint8 *)bytes);
281 }
282 
283 /*
284  * Load 32-bit value from unaligned big-(network-)endian byte array.
285  */
286 static INLINE uint32
ntoh32_ua(const void * bytes)287 ntoh32_ua(const void *bytes)
288 {
289 	return _NTOH32_UA((const uint8 *)bytes);
290 }
291 
292 #endif /* !__GNUC__ */
293 #endif /* !_BCMENDIAN_H_ */
294