• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Byte order utilities
3  *
4  * Copyright (C) 1999-2019, Broadcom.
5  *
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  *
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions
16  * of the license of that module.  An independent module is a module which is
17  * not derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  *
20  *      Notwithstanding the above, under no circumstances may you combine this
21  * software in any way with any other Broadcom software provided under a license
22  * other than the GPL, without Broadcom's express prior written consent.
23  *
24  *
25  * <<Broadcom-WL-IPTag/Open:>>
26  *
27  *  $Id: bcmendian.h 788572 2018-11-13 03:52:19Z $
28  *
29  * This file by default provides proper behavior on little-endian architectures.
30  * On big-endian architectures, IL_BIGENDIAN should be defined.
31  */
32 
33 #ifndef _BCMENDIAN_H_
34 #define _BCMENDIAN_H_
35 
36 #include <typedefs.h>
37 
38 /* Reverse the bytes in a 16-bit value */
39 #define BCMSWAP16(val)                                                         \
40     ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) |                       \
41               (((uint16)(val) & (uint16)0xff00U) >> 8)))
42 
43 /* Reverse the bytes in a 32-bit value */
44 #define BCMSWAP32(val)                                                         \
45     ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) |                  \
46               (((uint32)(val) & (uint32)0x0000ff00U) << 8) |                   \
47               (((uint32)(val) & (uint32)0x00ff0000U) >> 8) |                   \
48               (((uint32)(val) & (uint32)0xff000000U) >> 24)))
49 
50 /* Reverse the two 16-bit halves of a 32-bit value */
51 #define BCMSWAP32BY16(val)                                                     \
52     ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) |                  \
53               (((uint32)(val) & (uint32)0xffff0000U) >> 16)))
54 
55 /* Reverse the bytes in a 64-bit value */
56 #define BCMSWAP64(val)                                                         \
57     ((uint64)((((uint64)(val)&0x00000000000000ffULL) << 56) |                  \
58               (((uint64)(val)&0x000000000000ff00ULL) << 40) |                  \
59               (((uint64)(val)&0x0000000000ff0000ULL) << 24) |                  \
60               (((uint64)(val)&0x00000000ff000000ULL) << 8) |                   \
61               (((uint64)(val)&0x000000ff00000000ULL) >> 8) |                   \
62               (((uint64)(val)&0x0000ff0000000000ULL) >> 24) |                  \
63               (((uint64)(val)&0x00ff000000000000ULL) >> 40) |                  \
64               (((uint64)(val)&0xff00000000000000ULL) >> 56)))
65 
66 /* Reverse the two 32-bit halves of a 64-bit value */
67 #define BCMSWAP64BY32(val)                                                     \
68     ((uint64)((((uint64)(val)&0x00000000ffffffffULL) << 32) |                  \
69               (((uint64)(val)&0xffffffff00000000ULL) >> 32)))
70 
71 /* Byte swapping macros
72  *    Host <=> Network (Big Endian) for 16- and 32-bit values
73  *    Host <=> Little-Endian for 16- and 32-bit values
74  */
75 #ifndef hton16
76 #define HTON16(i) BCMSWAP16(i)
77 #define hton16(i) bcmswap16(i)
78 #define HTON32(i) BCMSWAP32(i)
79 #define hton32(i) bcmswap32(i)
80 #define NTOH16(i) BCMSWAP16(i)
81 #define ntoh16(i) bcmswap16(i)
82 #define NTOH32(i) BCMSWAP32(i)
83 #define ntoh32(i) bcmswap32(i)
84 #define LTOH16(i) (i)
85 #define ltoh16(i) (i)
86 #define LTOH32(i) (i)
87 #define ltoh32(i) (i)
88 #define HTOL16(i) (i)
89 #define htol16(i) (i)
90 #define HTOL32(i) (i)
91 #define htol32(i) (i)
92 #define HTOL64(i) (i)
93 #define htol64(i) (i)
94 #endif /* hton16 */
95 
96 #define ltoh16_buf(buf, i)
97 #define htol16_buf(buf, i)
98 #define ltoh32_buf(buf, i)
99 #define htol32_buf(buf, i)
100 #define ltoh64_buf(buf, i)
101 #define htol64_buf(buf, i)
102 
103 /* Unaligned loads and stores in host byte order */
104 #define load32_ua(a) ltoh32_ua(a)
105 #define store32_ua(a, v) htol32_ua_store(v, a)
106 #define load16_ua(a) ltoh16_ua(a)
107 #define store16_ua(a, v) htol16_ua_store(v, a)
108 #define load64_ua(a) ltoh64_ua(a)
109 #define store64_ua(a, v) htol64_ua_store(v, a)
110 
111 #define _LTOH16_UA(cp) (uint16)((cp)[0] | ((cp)[1] << 8))
112 #define _LTOH32_UA(cp)                                                         \
113     (uint32)((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24))
114 #define _NTOH16_UA(cp) (uint16)(((cp)[0] << 8) | (cp)[1])
115 #define _NTOH32_UA(cp)                                                         \
116     (uint32)(((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3])
117 
118 #define _LTOH64_UA(cp)                                                         \
119     ((uint64)(cp)[0] | ((uint64)(cp)[1] << 8) | ((uint64)(cp)[2] << 16) |      \
120      ((uint64)(cp)[3] << 24) | ((uint64)(cp)[4] << 32) |                       \
121      ((uint64)(cp)[5] << 40) | ((uint64)(cp)[6] << 48) |                       \
122      ((uint64)(cp)[7] << 56))
123 
124 #define _NTOH64_UA(cp)                                                         \
125     ((uint64)(cp)[7] | ((uint64)(cp)[6] << 8) | ((uint64)(cp)[5] << 16) |      \
126      ((uint64)(cp)[4] << 24) | ((uint64)(cp)[3] << 32) |                       \
127      ((uint64)(cp)[2] << 40) | ((uint64)(cp)[1] << 48) |                       \
128      ((uint64)(cp)[0] << 56))
129 
130 #define ltoh_ua(ptr)                                                           \
131     (sizeof(*(ptr)) == sizeof(uint8)    ? *(const uint8 *)(ptr)                \
132      : sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr))     \
133      : sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr))     \
134                                         : *(uint8 *)0)
135 
136 #define ntoh_ua(ptr)                                                           \
137     (sizeof(*(ptr)) == sizeof(uint8)    ? *(const uint8 *)(ptr)                \
138      : sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr))     \
139      : sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr))     \
140                                         : *(uint8 *)0)
141 
142 #ifdef __GNUC__
143 
144 /* GNU macro versions avoid referencing the argument multiple times, while also
145  * avoiding the -fno-inline used in ROM builds.
146  */
147 
148 #define bcmswap16(val)                                                         \
149     ({                                                                         \
150         uint16 _val = (val);                                                   \
151         BCMSWAP16(_val);                                                       \
152     })
153 
154 #define bcmswap32(val)                                                         \
155     ({                                                                         \
156         uint32 _val = (val);                                                   \
157         BCMSWAP32(_val);                                                       \
158     })
159 
160 #define bcmswap64(val)                                                         \
161     ({                                                                         \
162         uint64 _val = (val);                                                   \
163         BCMSWAP64(_val);                                                       \
164     })
165 
166 #define bcmswap32by16(val)                                                     \
167     ({                                                                         \
168         uint32 _val = (val);                                                   \
169         BCMSWAP32BY16(_val);                                                   \
170     })
171 
172 #define bcmswap16_buf(buf, len)                                                \
173     ({                                                                         \
174         uint16 *_buf = (uint16 *)(buf);                                        \
175         uint _wds = (len) / 2;                                                 \
176         while (_wds--) {                                                       \
177             *_buf = bcmswap16(*_buf);                                          \
178             _buf++;                                                            \
179         }                                                                      \
180     })
181 
182 #define bcmswap32_buf(buf, len)                                                \
183     ({                                                                         \
184         uint32 *_buf = (uint32 *)(buf);                                        \
185         uint _wds = (len) / 4;                                                 \
186         while (_wds--) {                                                       \
187             *_buf = bcmswap32(*_buf);                                          \
188             _buf++;                                                            \
189         }                                                                      \
190     })
191 
192 #define bcmswap64_buf(buf, len)                                                \
193     ({                                                                         \
194         uint64 *_buf = (uint64 *)(buf);                                        \
195         uint _wds = (len) / 8;                                                 \
196         while (_wds--) {                                                       \
197             *_buf = bcmswap64(*_buf);                                          \
198             _buf++;                                                            \
199         }                                                                      \
200     })
201 
202 #define htol16_ua_store(val, bytes)                                            \
203     ({                                                                         \
204         uint16 _val = (val);                                                   \
205         uint8 *_bytes = (uint8 *)(bytes);                                      \
206         _bytes[0] = _val & 0xff;                                               \
207         _bytes[1] = _val >> 8;                                                 \
208     })
209 
210 #define htol32_ua_store(val, bytes)                                            \
211     ({                                                                         \
212         uint32 _val = (val);                                                   \
213         uint8 *_bytes = (uint8 *)(bytes);                                      \
214         _bytes[0] = _val & 0xff;                                               \
215         _bytes[1] = (_val >> 8) & 0xff;                                        \
216         _bytes[2] = (_val >> 16) & 0xff;                                       \
217         _bytes[3] = _val >> 24;                                                \
218     })
219 
220 #define htol64_ua_store(val, bytes)                                            \
221     ({                                                                         \
222         uint64 _val = (val);                                                   \
223         uint8 *_bytes = (uint8 *)(bytes);                                      \
224         int i;                                                                 \
225         for (i = 0; i < (int)sizeof(_val); ++i) {                              \
226             *_bytes++ = _val & 0xff;                                           \
227             _val >>= 8;                                                        \
228         }                                                                      \
229     })
230 
231 #define hton16_ua_store(val, bytes)                                            \
232     ({                                                                         \
233         uint16 _val = (val);                                                   \
234         uint8 *_bytes = (uint8 *)(bytes);                                      \
235         _bytes[0] = _val >> 8;                                                 \
236         _bytes[1] = _val & 0xff;                                               \
237     })
238 
239 #define hton32_ua_store(val, bytes)                                            \
240     ({                                                                         \
241         uint32 _val = (val);                                                   \
242         uint8 *_bytes = (uint8 *)(bytes);                                      \
243         _bytes[0] = _val >> 24;                                                \
244         _bytes[1] = (_val >> 16) & 0xff;                                       \
245         _bytes[2] = (_val >> 8) & 0xff;                                        \
246         _bytes[3] = _val & 0xff;                                               \
247     })
248 
249 #define ltoh16_ua(bytes)                                                       \
250     ({                                                                         \
251         const uint8 *_bytes = (const uint8 *)(bytes);                          \
252         _LTOH16_UA(_bytes);                                                    \
253     })
254 
255 #define ltoh32_ua(bytes)                                                       \
256     ({                                                                         \
257         const uint8 *_bytes = (const uint8 *)(bytes);                          \
258         _LTOH32_UA(_bytes);                                                    \
259     })
260 
261 #define ltoh64_ua(bytes)                                                       \
262     ({                                                                         \
263         const uint8 *_bytes = (const uint8 *)(bytes);                          \
264         _LTOH64_UA(_bytes);                                                    \
265     })
266 
267 #define ntoh16_ua(bytes)                                                       \
268     ({                                                                         \
269         const uint8 *_bytes = (const uint8 *)(bytes);                          \
270         _NTOH16_UA(_bytes);                                                    \
271     })
272 
273 #define ntoh32_ua(bytes)                                                       \
274     ({                                                                         \
275         const uint8 *_bytes = (const uint8 *)(bytes);                          \
276         _NTOH32_UA(_bytes);                                                    \
277     })
278 
279 #define ntoh64_ua(bytes)                                                       \
280     ({                                                                         \
281         const uint8 *_bytes = (const uint8 *)(bytes);                          \
282         _NTOH64_UA(_bytes);                                                    \
283     })
284 
285 #else /* !__GNUC__ */
286 
287 /* Inline versions avoid referencing the argument multiple times */
bcmswap16(uint16 val)288 static INLINE uint16 bcmswap16(uint16 val)
289 {
290     return BCMSWAP16(val);
291 }
292 
bcmswap32(uint32 val)293 static INLINE uint32 bcmswap32(uint32 val)
294 {
295     return BCMSWAP32(val);
296 }
297 
bcmswap64(uint64 val)298 static INLINE uint64 bcmswap64(uint64 val)
299 {
300     return BCMSWAP64(val);
301 }
302 
bcmswap32by16(uint32 val)303 static INLINE uint32 bcmswap32by16(uint32 val)
304 {
305     return BCMSWAP32BY16(val);
306 }
307 
308 /* Reverse pairs of bytes in a buffer (not for high-performance use) */
309 /* buf	- start of buffer of shorts to swap */
310 /* len  - byte length of buffer */
bcmswap16_buf(uint16 * buf,uint len)311 static INLINE void bcmswap16_buf(uint16 *buf, uint len)
312 {
313     len = len / 2;
314 
315     while (len--) {
316         *buf = bcmswap16(*buf);
317         buf++;
318     }
319 }
320 
321 /*
322  * Store 16-bit value to unaligned little-endian byte array.
323  */
htol16_ua_store(uint16 val,uint8 * bytes)324 static INLINE void htol16_ua_store(uint16 val, uint8 *bytes)
325 {
326     bytes[0] = val & 0xff;
327     bytes[1] = val >> 8;
328 }
329 
330 /*
331  * Store 32-bit value to unaligned little-endian byte array.
332  */
htol32_ua_store(uint32 val,uint8 * bytes)333 static INLINE void htol32_ua_store(uint32 val, uint8 *bytes)
334 {
335     bytes[0] = val & 0xff;
336     bytes[1] = (val >> 8) & 0xff;
337     bytes[2] = (val >> 16) & 0xff;
338     bytes[3] = val >> 24;
339 }
340 
341 /*
342  * Store 64-bit value to unaligned little-endian byte array.
343  */
htol64_ua_store(uint64 val,uint8 * bytes)344 static INLINE void htol64_ua_store(uint64 val, uint8 *bytes)
345 {
346     int i;
347     for (i = 0; i < sizeof(val); ++i) {
348         *bytes++ = (uint8)(val & 0xff);
349         val >>= 8;
350     }
351 }
352 
353 /*
354  * Store 16-bit value to unaligned network-(big-)endian byte array.
355  */
hton16_ua_store(uint16 val,uint8 * bytes)356 static INLINE void hton16_ua_store(uint16 val, uint8 *bytes)
357 {
358     bytes[0] = val >> 8;
359     bytes[1] = val & 0xff;
360 }
361 
362 /*
363  * Store 32-bit value to unaligned network-(big-)endian byte array.
364  */
hton32_ua_store(uint32 val,uint8 * bytes)365 static INLINE void hton32_ua_store(uint32 val, uint8 *bytes)
366 {
367     bytes[0] = val >> 24;
368     bytes[1] = (val >> 16) & 0xff;
369     bytes[2] = (val >> 8) & 0xff;
370     bytes[3] = val & 0xff;
371 }
372 
373 /*
374  * Load 16-bit value from unaligned little-endian byte array.
375  */
ltoh16_ua(const void * bytes)376 static INLINE uint16 ltoh16_ua(const void *bytes)
377 {
378     return _LTOH16_UA((const uint8 *)bytes);
379 }
380 
381 /*
382  * Load 32-bit value from unaligned little-endian byte array.
383  */
ltoh32_ua(const void * bytes)384 static INLINE uint32 ltoh32_ua(const void *bytes)
385 {
386     return _LTOH32_UA((const uint8 *)bytes);
387 }
388 
389 /*
390  * Load 64-bit value from unaligned little-endian byte array.
391  */
ltoh64_ua(const void * bytes)392 static INLINE uint64 ltoh64_ua(const void *bytes)
393 {
394     return _LTOH64_UA((const uint8 *)bytes);
395 }
396 
397 /*
398  * Load 16-bit value from unaligned big-(network-)endian byte array.
399  */
ntoh16_ua(const void * bytes)400 static INLINE uint16 ntoh16_ua(const void *bytes)
401 {
402     return _NTOH16_UA((const uint8 *)bytes);
403 }
404 
405 /*
406  * Load 32-bit value from unaligned big-(network-)endian byte array.
407  */
ntoh32_ua(const void * bytes)408 static INLINE uint32 ntoh32_ua(const void *bytes)
409 {
410     return _NTOH32_UA((const uint8 *)bytes);
411 }
412 
413 /*
414  * Load 64-bit value from unaligned big-(network-)endian byte array.
415  */
ntoh64_ua(const void * bytes)416 static INLINE uint64 ntoh64_ua(const void *bytes)
417 {
418     return _NTOH64_UA((const uint8 *)bytes);
419 }
420 
421 #endif /* !__GNUC__ */
422 #endif /* !_BCMENDIAN_H_ */
423