1/* 2 * Byte order utilities 3 * 4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved. 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,v 1.36 2009/11/09 05:29:43 Exp $ 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#ifndef IL_BIGENDIAN 52#define HTON16(i) BCMSWAP16(i) 53#define hton16(i) bcmswap16(i) 54#define HTON32(i) BCMSWAP32(i) 55#define hton32(i) bcmswap32(i) 56#define NTOH16(i) BCMSWAP16(i) 57#define ntoh16(i) bcmswap16(i) 58#define NTOH32(i) BCMSWAP32(i) 59#define ntoh32(i) bcmswap32(i) 60#define LTOH16(i) (i) 61#define ltoh16(i) (i) 62#define LTOH32(i) (i) 63#define ltoh32(i) (i) 64#define HTOL16(i) (i) 65#define htol16(i) (i) 66#define HTOL32(i) (i) 67#define htol32(i) (i) 68#else /* IL_BIGENDIAN */ 69#define HTON16(i) (i) 70#define hton16(i) (i) 71#define HTON32(i) (i) 72#define hton32(i) (i) 73#define NTOH16(i) (i) 74#define ntoh16(i) (i) 75#define NTOH32(i) (i) 76#define ntoh32(i) (i) 77#define LTOH16(i) BCMSWAP16(i) 78#define ltoh16(i) bcmswap16(i) 79#define LTOH32(i) BCMSWAP32(i) 80#define ltoh32(i) bcmswap32(i) 81#define HTOL16(i) BCMSWAP16(i) 82#define htol16(i) bcmswap16(i) 83#define HTOL32(i) BCMSWAP32(i) 84#define htol32(i) bcmswap32(i) 85#endif /* IL_BIGENDIAN */ 86#endif /* hton16 */ 87 88#ifndef IL_BIGENDIAN 89#define ltoh16_buf(buf, i) 90#define htol16_buf(buf, i) 91#else 92#define ltoh16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) 93#define htol16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i)) 94#endif /* IL_BIGENDIAN */ 95 96/* Unaligned loads and stores in host byte order */ 97#ifndef IL_BIGENDIAN 98#define load32_ua(a) ltoh32_ua(a) 99#define store32_ua(a, v) htol32_ua_store(v, a) 100#define load16_ua(a) ltoh16_ua(a) 101#define store16_ua(a, v) htol16_ua_store(v, a) 102#else 103#define load32_ua(a) ntoh32_ua(a) 104#define store32_ua(a, v) hton32_ua_store(v, a) 105#define load16_ua(a) ntoh16_ua(a) 106#define store16_ua(a, v) hton16_ua_store(v, a) 107#endif /* IL_BIGENDIAN */ 108 109#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8)) 110#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24)) 111#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1]) 112#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3]) 113 114#define ltoh_ua(ptr) \ 115 (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ 116 sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \ 117 sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \ 118 *(uint8 *)0) 119 120#define ntoh_ua(ptr) \ 121 (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ 122 sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \ 123 sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \ 124 *(uint8 *)0) 125 126#ifdef __GNUC__ 127 128/* GNU macro versions avoid referencing the argument multiple times, while also 129 * avoiding the -fno-inline used in ROM builds. 130 */ 131 132#define bcmswap16(val) ({ \ 133 uint16 _val = (val); \ 134 BCMSWAP16(_val); \ 135}) 136 137#define bcmswap32(val) ({ \ 138 uint32 _val = (val); \ 139 BCMSWAP32(_val); \ 140}) 141 142#define bcmswap32by16(val) ({ \ 143 uint32 _val = (val); \ 144 BCMSWAP32BY16(_val); \ 145}) 146 147#define bcmswap16_buf(buf, len) ({ \ 148 uint16 *_buf = (uint16 *)(buf); \ 149 uint _wds = (len) / 2; \ 150 while (_wds--) { \ 151 *_buf = bcmswap16(*_buf); \ 152 _buf++; \ 153 } \ 154}) 155 156#define htol16_ua_store(val, bytes) ({ \ 157 uint16 _val = (val); \ 158 uint8 *_bytes = (uint8 *)(bytes); \ 159 _bytes[0] = _val & 0xff; \ 160 _bytes[1] = _val >> 8; \ 161}) 162 163#define htol32_ua_store(val, bytes) ({ \ 164 uint32 _val = (val); \ 165 uint8 *_bytes = (uint8 *)(bytes); \ 166 _bytes[0] = _val & 0xff; \ 167 _bytes[1] = (_val >> 8) & 0xff; \ 168 _bytes[2] = (_val >> 16) & 0xff; \ 169 _bytes[3] = _val >> 24; \ 170}) 171 172#define hton16_ua_store(val, bytes) ({ \ 173 uint16 _val = (val); \ 174 uint8 *_bytes = (uint8 *)(bytes); \ 175 _bytes[0] = _val >> 8; \ 176 _bytes[1] = _val & 0xff; \ 177}) 178 179#define hton32_ua_store(val, bytes) ({ \ 180 uint32 _val = (val); \ 181 uint8 *_bytes = (uint8 *)(bytes); \ 182 _bytes[0] = _val >> 24; \ 183 _bytes[1] = (_val >> 16) & 0xff; \ 184 _bytes[2] = (_val >> 8) & 0xff; \ 185 _bytes[3] = _val & 0xff; \ 186}) 187 188#define ltoh16_ua(bytes) ({ \ 189 const uint8 *_bytes = (const uint8 *)(bytes); \ 190 _LTOH16_UA(_bytes); \ 191}) 192 193#define ltoh32_ua(bytes) ({ \ 194 const uint8 *_bytes = (const uint8 *)(bytes); \ 195 _LTOH32_UA(_bytes); \ 196}) 197 198#define ntoh16_ua(bytes) ({ \ 199 const uint8 *_bytes = (const uint8 *)(bytes); \ 200 _NTOH16_UA(_bytes); \ 201}) 202 203#define ntoh32_ua(bytes) ({ \ 204 const uint8 *_bytes = (const uint8 *)(bytes); \ 205 _NTOH32_UA(_bytes); \ 206}) 207 208#else /* !__GNUC__ */ 209 210/* Inline versions avoid referencing the argument multiple times */ 211static INLINE uint16 212bcmswap16(uint16 val) 213{ 214 return BCMSWAP16(val); 215} 216 217static INLINE uint32 218bcmswap32(uint32 val) 219{ 220 return BCMSWAP32(val); 221} 222 223static INLINE uint32 224bcmswap32by16(uint32 val) 225{ 226 return BCMSWAP32BY16(val); 227} 228 229/* Reverse pairs of bytes in a buffer (not for high-performance use) */ 230/* buf - start of buffer of shorts to swap */ 231/* len - byte length of buffer */ 232static INLINE void 233bcmswap16_buf(uint16 *buf, uint len) 234{ 235 len = len / 2; 236 237 while (len--) { 238 *buf = bcmswap16(*buf); 239 buf++; 240 } 241} 242 243/* 244 * Store 16-bit value to unaligned little-endian byte array. 245 */ 246static INLINE void 247htol16_ua_store(uint16 val, uint8 *bytes) 248{ 249 bytes[0] = val & 0xff; 250 bytes[1] = val >> 8; 251} 252 253/* 254 * Store 32-bit value to unaligned little-endian byte array. 255 */ 256static INLINE void 257htol32_ua_store(uint32 val, uint8 *bytes) 258{ 259 bytes[0] = val & 0xff; 260 bytes[1] = (val >> 8) & 0xff; 261 bytes[2] = (val >> 16) & 0xff; 262 bytes[3] = val >> 24; 263} 264 265/* 266 * Store 16-bit value to unaligned network-(big-)endian byte array. 267 */ 268static INLINE void 269hton16_ua_store(uint16 val, uint8 *bytes) 270{ 271 bytes[0] = val >> 8; 272 bytes[1] = val & 0xff; 273} 274 275/* 276 * Store 32-bit value to unaligned network-(big-)endian byte array. 277 */ 278static INLINE void 279hton32_ua_store(uint32 val, uint8 *bytes) 280{ 281 bytes[0] = val >> 24; 282 bytes[1] = (val >> 16) & 0xff; 283 bytes[2] = (val >> 8) & 0xff; 284 bytes[3] = val & 0xff; 285} 286 287/* 288 * Load 16-bit value from unaligned little-endian byte array. 289 */ 290static INLINE uint16 291ltoh16_ua(const void *bytes) 292{ 293 return _LTOH16_UA((const uint8 *)bytes); 294} 295 296/* 297 * Load 32-bit value from unaligned little-endian byte array. 298 */ 299static INLINE uint32 300ltoh32_ua(const void *bytes) 301{ 302 return _LTOH32_UA((const uint8 *)bytes); 303} 304 305/* 306 * Load 16-bit value from unaligned big-(network-)endian byte array. 307 */ 308static INLINE uint16 309ntoh16_ua(const void *bytes) 310{ 311 return _NTOH16_UA((const uint8 *)bytes); 312} 313 314/* 315 * Load 32-bit value from unaligned big-(network-)endian byte array. 316 */ 317static INLINE uint32 318ntoh32_ua(const void *bytes) 319{ 320 return _NTOH32_UA((const uint8 *)bytes); 321} 322 323#endif /* !__GNUC__ */ 324#endif /* !_BCMENDIAN_H_ */ 325