bcmendian.h 11 KB

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