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