text: /*
   * Byte order utilities
   *
   * Copyright (C) 1999-2019, Broadcom.
   *
   *      Unless you and Broadcom execute a separate written software license
   * agreement governing use of this software, this software is licensed to you
   * under the terms of the GNU General Public License version 2 (the "GPL"),
   * available at http://www.broadcom.com/licenses/GPLv2.php, with the
   * following added to such license:
   *
   *      As a special exception, the copyright holders of this software give you
   * permission to link this software with independent modules, and to copy and
   * distribute the resulting executable under terms of your choice, provided that
   * you also meet, for each linked independent module, the terms and conditions of
   * the license of that module.  An independent module is a module which is not
   * derived from this software.  The special exception does not apply to any
   * modifications of the software.
   *
   *      Notwithstanding the above, under no circumstances may you combine this
   * software in any way with any other Broadcom software provided under a license
   * other than the GPL, without Broadcom's express prior written consent.
   *
   *
   * <<Broadcom-WL-IPTag/Open:>>
   *
   *  $Id: bcmendian.h 633810 2016-04-25 16:46:55Z $
   *
   * This file by default provides proper behavior on little-endian architectures.
   * On big-endian architectures, IL_BIGENDIAN should be defined.
   */
  
  #ifndef _BCMENDIAN_H_
  #define _BCMENDIAN_H_
  
  #include <typedefs.h>
  
  /* Reverse the bytes in a 16-bit value */
  #define BCMSWAP16(val) \
  	((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \
  		  (((uint16)(val) & (uint16)0xff00U) >> 8)))
  
  /* Reverse the bytes in a 32-bit value */
  #define BCMSWAP32(val) \
  	((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \
  		  (((uint32)(val) & (uint32)0x0000ff00U) <<  8) | \
  		  (((uint32)(val) & (uint32)0x00ff0000U) >>  8) | \
  		  (((uint32)(val) & (uint32)0xff000000U) >> 24)))
  
  /* Reverse the two 16-bit halves of a 32-bit value */
  #define BCMSWAP32BY16(val) \
  	((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \
  		  (((uint32)(val) & (uint32)0xffff0000U) >> 16)))
  
  /* Reverse the bytes in a 64-bit value */
  #define BCMSWAP64(val) \
  	((uint64)((((uint64)(val) & 0x00000000000000ffULL) << 56) | \
  	          (((uint64)(val) & 0x000000000000ff00ULL) << 40) | \
  	          (((uint64)(val) & 0x0000000000ff0000ULL) << 24) | \
  	          (((uint64)(val) & 0x00000000ff000000ULL) <<  8) | \
  	          (((uint64)(val) & 0x000000ff00000000ULL) >>  8) | \
  	          (((uint64)(val) & 0x0000ff0000000000ULL) >> 24) | \
  	          (((uint64)(val) & 0x00ff000000000000ULL) >> 40) | \
  	          (((uint64)(val) & 0xff00000000000000ULL) >> 56)))
  
  /* Reverse the two 32-bit halves of a 64-bit value */
  #define BCMSWAP64BY32(val) \
  	((uint64)((((uint64)(val) & 0x00000000ffffffffULL) << 32) | \
  	          (((uint64)(val) & 0xffffffff00000000ULL) >> 32)))
  
  /* Byte swapping macros
   *    Host <=> Network (Big Endian) for 16- and 32-bit values
   *    Host <=> Little-Endian for 16- and 32-bit values
   */
  #ifndef hton16
  #define HTON16(i) BCMSWAP16(i)
  #define	hton16(i) bcmswap16(i)
  #define	HTON32(i) BCMSWAP32(i)
  #define	hton32(i) bcmswap32(i)
  #define	NTOH16(i) BCMSWAP16(i)
  #define	ntoh16(i) bcmswap16(i)
  #define	NTOH32(i) BCMSWAP32(i)
  #define	ntoh32(i) bcmswap32(i)
  #define LTOH16(i) (i)
  #define ltoh16(i) (i)
  #define LTOH32(i) (i)
  #define ltoh32(i) (i)
  #define HTOL16(i) (i)
  #define htol16(i) (i)
  #define HTOL32(i) (i)
  #define htol32(i) (i)
  #define HTOL64(i) (i)
  #define htol64(i) (i)
  #endif /* hton16 */
  
  #define ltoh16_buf(buf, i)
  #define htol16_buf(buf, i)
  #define ltoh32_buf(buf, i)
  #define htol32_buf(buf, i)
  #define ltoh64_buf(buf, i)
  #define htol64_buf(buf, i)
  
  /* Unaligned loads and stores in host byte order */
  #define load32_ua(a)		ltoh32_ua(a)
  #define store32_ua(a, v)	htol32_ua_store(v, a)
  #define load16_ua(a)		ltoh16_ua(a)
  #define store16_ua(a, v)	htol16_ua_store(v, a)
  #define load64_ua(a)		ltoh64_ua(a)
  #define store64_ua(a, v)	htol64_ua_store(v, a)
  
  #define _LTOH16_UA(cp)	((cp)[0] | ((cp)[1] << 8))
  #define _LTOH32_UA(cp)	((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24))
  #define _NTOH16_UA(cp)	(((cp)[0] << 8) | (cp)[1])
  #define _NTOH32_UA(cp)	(((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3])
  
  #define _LTOH64_UA(cp)	((uint64)(cp)[0] | ((uint64)(cp)[1] << 8) | \
  	((uint64)(cp)[2] << 16) | ((uint64)(cp)[3] << 24) | \
  	((uint64)(cp)[4] << 32) | ((uint64)(cp)[5] << 40) | \
  	((uint64)(cp)[6] << 48) | ((uint64)(cp)[7] << 56))
  
  #define _NTOH64_UA(cp)	((uint64)(cp)[7] | ((uint64)(cp)[6] << 8) | \
  	((uint64)(cp)[5] << 16) | ((uint64)(cp)[4] << 24) | \
  	((uint64)(cp)[3] << 32) | ((uint64)(cp)[2] << 40) | \
  	((uint64)(cp)[1] << 48) | ((uint64)(cp)[0] << 56))
  
  #define ltoh_ua(ptr) \
  	(sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
  	 sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \
  	 sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \
  	 *(uint8 *)0)
  
  #define ntoh_ua(ptr) \
  	(sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \
  	 sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \
  	 sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \
  	 *(uint8 *)0)
  
  #ifdef __GNUC__
  
  /* GNU macro versions avoid referencing the argument multiple times, while also
   * avoiding the -fno-inline used in ROM builds.
   */
  
  #define bcmswap16(val) ({ \
  	uint16 _val = (val); \
  	BCMSWAP16(_val); \
  })
  
  #define bcmswap32(val) ({ \
  	uint32 _val = (val); \
  	BCMSWAP32(_val); \
  })
  
  #define bcmswap64(val) ({ \
  	uint64 _val = (val); \
  	BCMSWAP64(_val); \
  })
  
  #define bcmswap32by16(val) ({ \
  	uint32 _val = (val); \
  	BCMSWAP32BY16(_val); \
  })
  
  #define bcmswap16_buf(buf, len) ({ \
  	uint16 *_buf = (uint16 *)(buf); \
  	uint _wds = (len) / 2; \
  	while (_wds--) { \
  		*_buf = bcmswap16(*_buf); \
  		_buf++; \
  	} \
  })
  
  #define bcmswap32_buf(buf, len) ({ \
  	uint32 *_buf = (uint32 *)(buf); \
  	uint _wds = (len) / 4; \
  	while (_wds--) { \
  		*_buf = bcmswap32(*_buf); \
  		_buf++; \
  	} \
  })
  
  #define bcmswap64_buf(buf, len) ({ \
  	uint64 *_buf = (uint64 *)(buf); \
  	uint _wds = (len) / 8; \
  	while (_wds--) { \
  		*_buf = bcmswap64(*_buf); \
  		_buf++; \
  	} \
  })
  
  #define htol16_ua_store(val, bytes) ({ \
  	uint16 _val = (val); \
  	uint8 *_bytes = (uint8 *)(bytes); \
  	_bytes[0] = _val & 0xff; \
  	_bytes[1] = _val >> 8; \
  })
  
  #define htol32_ua_store(val, bytes) ({ \
  	uint32 _val = (val); \
  	uint8 *_bytes = (uint8 *)(bytes); \
  	_bytes[0] = _val & 0xff; \
  	_bytes[1] = (_val >> 8) & 0xff; \
  	_bytes[2] = (_val >> 16) & 0xff; \
  	_bytes[3] = _val >> 24; \
  })
  
  #define htol64_ua_store(val, bytes) ({ \
  	uint64 _val = (val); \
  	uint8 *_bytes = (uint8 *)(bytes); \
  	int i; \
  	for (i = 0; i < (int)sizeof(_val); ++i) { \
  		*_bytes++ = _val & 0xff; \
  		_val >>= 8; \
  	} \
  })
  
  #define hton16_ua_store(val, bytes) ({ \
  	uint16 _val = (val); \
  	uint8 *_bytes = (uint8 *)(bytes); \
  	_bytes[0] = _val >> 8; \
  	_bytes[1] = _val & 0xff; \
  })
  
  #define hton32_ua_store(val, bytes) ({ \
  	uint32 _val = (val); \
  	uint8 *_bytes = (uint8 *)(bytes); \
  	_bytes[0] = _val >> 24; \
  	_bytes[1] = (_val >> 16) & 0xff; \
  	_bytes[2] = (_val >> 8) & 0xff; \
  	_bytes[3] = _val & 0xff; \
  })
  
  #define ltoh16_ua(bytes) ({ \
  	const uint8 *_bytes = (const uint8 *)(bytes); \
  	_LTOH16_UA(_bytes); \
  })
  
  #define ltoh32_ua(bytes) ({ \
  	const uint8 *_bytes = (const uint8 *)(bytes); \
  	_LTOH32_UA(_bytes); \
  })
  
  #define ltoh64_ua(bytes) ({ \
  	const uint8 *_bytes = (const uint8 *)(bytes); \
  	_LTOH64_UA(_bytes); \
  })
  
  #define ntoh16_ua(bytes) ({ \
  	const uint8 *_bytes = (const uint8 *)(bytes); \
  	_NTOH16_UA(_bytes); \
  })
  
  #define ntoh32_ua(bytes) ({ \
  	const uint8 *_bytes = (const uint8 *)(bytes); \
  	_NTOH32_UA(_bytes); \
  })
  
  #define ntoh64_ua(bytes) ({ \
  	const uint8 *_bytes = (const uint8 *)(bytes); \
  	_NTOH64_UA(_bytes); \
  })
  
  #else /* !__GNUC__ */
  
  /* Inline versions avoid referencing the argument multiple times */
  static INLINE uint16
  bcmswap16(uint16 val)
  {
  	return BCMSWAP16(val);
  }
  
  static INLINE uint32
  bcmswap32(uint32 val)
  {
  	return BCMSWAP32(val);
  }
  
  static INLINE uint64
  bcmswap64(uint64 val)
  {
  	return BCMSWAP64(val);
  }
  
  static INLINE uint32
  bcmswap32by16(uint32 val)
  {
  	return BCMSWAP32BY16(val);
  }
  
  /* Reverse pairs of bytes in a buffer (not for high-performance use) */
  /* buf	- start of buffer of shorts to swap */
  /* len  - byte length of buffer */
  static INLINE void
  bcmswap16_buf(uint16 *buf, uint len)
  {
  	len = len / 2;
  
  	while (len--) {
  		*buf = bcmswap16(*buf);
  		buf++;
  	}
  }
  
  /*
   * Store 16-bit value to unaligned little-endian byte array.
   */
  static INLINE void
  htol16_ua_store(uint16 val, uint8 *bytes)
  {
  	bytes[0] = val & 0xff;
  	bytes[1] = val >> 8;
  }
  
  /*
   * Store 32-bit value to unaligned little-endian byte array.
   */
  static INLINE void
  htol32_ua_store(uint32 val, uint8 *bytes)
  {
  	bytes[0] = val & 0xff;
  	bytes[1] = (val >> 8) & 0xff;
  	bytes[2] = (val >> 16) & 0xff;
  	bytes[3] = val >> 24;
  }
  
  /*
   * Store 64-bit value to unaligned little-endian byte array.
   */
  static INLINE void
  htol64_ua_store(uint64 val, uint8 *bytes)
  {
  	int i;
  	for (i = 0; i < sizeof(val); ++i) {
  		*bytes++ = (uint8)(val & 0xff);
  		val >>= 8;
  	}
  }
  
  /*
   * Store 16-bit value to unaligned network-(big-)endian byte array.
   */
  static INLINE void
  hton16_ua_store(uint16 val, uint8 *bytes)
  {
  	bytes[0] = val >> 8;
  	bytes[1] = val & 0xff;
  }
  
  /*
   * Store 32-bit value to unaligned network-(big-)endian byte array.
   */
  static INLINE void
  hton32_ua_store(uint32 val, uint8 *bytes)
  {
  	bytes[0] = val >> 24;
  	bytes[1] = (val >> 16) & 0xff;
  	bytes[2] = (val >> 8) & 0xff;
  	bytes[3] = val & 0xff;
  }
  
  /*
   * Load 16-bit value from unaligned little-endian byte array.
   */
  static INLINE uint16
  ltoh16_ua(const void *bytes)
  {
  	return _LTOH16_UA((const uint8 *)bytes);
  }
  
  /*
   * Load 32-bit value from unaligned little-endian byte array.
   */
  static INLINE uint32
  ltoh32_ua(const void *bytes)
  {
  	return _LTOH32_UA((const uint8 *)bytes);
  }
  
  /*
   * Load 64-bit value from unaligned little-endian byte array.
   */
  static INLINE uint64
  ltoh64_ua(const void *bytes)
  {
  	return _LTOH64_UA((const uint8 *)bytes);
  }
  
  /*
   * Load 16-bit value from unaligned big-(network-)endian byte array.
   */
  static INLINE uint16
  ntoh16_ua(const void *bytes)
  {
  	return _NTOH16_UA((const uint8 *)bytes);
  }
  
  /*
   * Load 32-bit value from unaligned big-(network-)endian byte array.
   */
  static INLINE uint32
  ntoh32_ua(const void *bytes)
  {
  	return _NTOH32_UA((const uint8 *)bytes);
  }
  
  /*
   * Load 64-bit value from unaligned big-(network-)endian byte array.
   */
  static INLINE uint64
  ntoh64_ua(const void *bytes)
  {
  	return _NTOH64_UA((const uint8 *)bytes);
  }
  
  #endif /* !__GNUC__ */
  #endif /* !_BCMENDIAN_H_ */
  