Home | History | Annotate | Download | only in include
      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
    181 bcmswap16(uint16 val)
    182 {
    183 	return BCMSWAP16(val);
    184 }
    185 
    186 static INLINE uint32
    187 bcmswap32(uint32 val)
    188 {
    189 	return BCMSWAP32(val);
    190 }
    191 
    192 static INLINE uint32
    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
    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
    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
    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
    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
    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
    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
    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
    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
    287 ntoh32_ua(const void *bytes)
    288 {
    289 	return _NTOH32_UA((const uint8 *)bytes);
    290 }
    291 
    292 #endif /* !__GNUC__ */
    293 #endif /* !_BCMENDIAN_H_ */
    294