nu_bitutil.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-2-7 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #ifndef __NU_BITUTIL_H__
  13. #define __NU_BITUTIL_H__
  14. #if defined(__ICCARM__)
  15. #include <arm_math.h>
  16. #elif defined (__ARMCC_VERSION)
  17. #ifdef __has_include
  18. #if __has_include("cmsis_compiler.h")
  19. #include "cmsis_compiler.h"
  20. #endif
  21. #endif
  22. #if !defined(__CLZ)
  23. #define __CLZ __clz
  24. #endif
  25. #endif
  26. #include <stdint.h>
  27. #if !defined(__STATIC_INLINE)
  28. #define __STATIC_INLINE static inline
  29. #endif
  30. #ifdef __cplusplus
  31. extern "C" {
  32. #endif
  33. /* ----------------------------------------------
  34. * Count Leading Zeros Count Trailing Zeros
  35. * (MSB)00000000000000001000000000001000(LSB)
  36. * ################| |!!!
  37. * Find Highest Set Find First Set
  38. * ----------------------------------------------
  39. *
  40. * ----------------------------------------------
  41. * Count Leading Ones Count Trailing Ones
  42. * (MSB)11111111111111110111111111110111(LSB)
  43. * ^^^^^^^^^^^^^^^^| |@@@
  44. * Find Highest Zero Find First Zero
  45. * ----------------------------------------------
  46. */
  47. /* Count Leading Zeros in word - Find Highest Set
  48. EX: x=(MSB)00000000000000001000000000001000(LSB)
  49. ################|
  50. Find Highest Set
  51. nu_clz will start zero-counting from MSB and return the number.
  52. */
  53. __STATIC_INLINE int nu_clz(uint32_t x)
  54. {
  55. return x ? __CLZ(x) : 32;
  56. }
  57. /* Count Leading Ones in word - Find Highest Zero
  58. EX: x=(MSB)11111111111111110111111111110111(LSB)
  59. ^^^^^^^^^^^^^^^^|
  60. Find Highest Zero
  61. nu_clo will start one-counting from MSB and return the number.
  62. */
  63. __STATIC_INLINE int nu_clo(uint32_t x)
  64. {
  65. return nu_clz(~x);
  66. }
  67. /* Count Trailing Zero in word - Find First Set
  68. EX: x=(MSB)00000000000000001000000000001000(LSB)
  69. |!!!
  70. Find First Set
  71. nu_ctz will start zero-counting from LSB and return the number.
  72. */
  73. __STATIC_INLINE int nu_ctz(uint32_t x)
  74. {
  75. int c = 32;
  76. if (x)
  77. c = __CLZ(x & -x);
  78. return x ? 31 - c : c;
  79. }
  80. /* Count Trailing Ones in word - Find First Zero
  81. EX: x=(MSB)11111111111111110111111111110111(LSB)
  82. |@@@
  83. Find First Zero
  84. nu_cto will start one-counting from LSB and return the number.
  85. */
  86. __STATIC_INLINE int nu_cto(uint32_t x)
  87. {
  88. return nu_ctz(~x);
  89. }
  90. /* Get 16-bit from a byte-array in little-endian */
  91. __STATIC_INLINE uint16_t nu_get16_le(const uint8_t *pos)
  92. {
  93. uint16_t val;
  94. val = *pos ++;
  95. val += (*pos << 8);
  96. return val;
  97. }
  98. /* Set 16-bit to a byte-array in little-endian */
  99. __STATIC_INLINE void nu_set16_le(uint8_t *pos, uint16_t val)
  100. {
  101. *pos ++ = val & 0xFF;
  102. *pos = val >> 8;
  103. }
  104. /* Get 32-bit from a byte-array in little-endian */
  105. __STATIC_INLINE uint32_t nu_get32_le(const uint8_t *pos)
  106. {
  107. uint32_t val;
  108. val = *pos ++;
  109. val += (*pos ++ << 8);
  110. val += (*pos ++ << 16);
  111. val += (*pos ++ << 24);
  112. return val;
  113. }
  114. /* Get 24-bit from a byte-array in little-endian */
  115. __STATIC_INLINE uint32_t nu_get24_le(const uint8_t *pos)
  116. {
  117. uint32_t val;
  118. val = *pos ++;
  119. val += (*pos ++ << 8);
  120. val += (*pos ++ << 16);
  121. return val;
  122. }
  123. /* Set 24-bit to a byte-array in little-endian */
  124. __STATIC_INLINE void nu_set24_le(uint8_t *pos, uint32_t val)
  125. {
  126. *pos ++ = val & 0xFF;
  127. *pos ++ = (val >> 8) & 0xFF;
  128. *pos ++ = (val >> 16) & 0xFF;
  129. }
  130. /* Set 32-bit to a byte-array in little-endian */
  131. __STATIC_INLINE void nu_set32_le(uint8_t *pos, uint32_t val)
  132. {
  133. *pos ++ = val & 0xFF;
  134. *pos ++ = (val >> 8) & 0xFF;
  135. *pos ++ = (val >> 16) & 0xFF;
  136. *pos = (val >> 24) & 0xFF;
  137. }
  138. /* Get 16-bit from a byte-array in big-endian */
  139. __STATIC_INLINE uint16_t nu_get16_be(const uint8_t *pos)
  140. {
  141. uint16_t val;
  142. val = *pos ++;
  143. val <<= 8;
  144. val += *pos;
  145. return val;
  146. }
  147. /* Set 16-bit to a byte-array in big-endian */
  148. __STATIC_INLINE void nu_set16_be(uint8_t *pos, uint16_t val)
  149. {
  150. *pos ++ = val >> 8;
  151. *pos = (val & 0xFF);
  152. }
  153. /* Get 24-bit from a byte-array in big-endian */
  154. __STATIC_INLINE uint32_t nu_get24_be(const uint8_t *pos)
  155. {
  156. uint32_t val;
  157. val = *pos ++;
  158. val <<= 8;
  159. val += *pos ++;
  160. val <<= 8;
  161. val += *pos ++;
  162. return val;
  163. }
  164. /* Set 24-bit to a byte-array in big-endian */
  165. __STATIC_INLINE void nu_set24_be(uint8_t *pos, uint32_t val)
  166. {
  167. *pos ++ = val >> 16;
  168. *pos ++ = val >> 8;
  169. *pos ++ = (val & 0xFF);
  170. }
  171. /* Get 32-bit from a byte-array in big-endian */
  172. __STATIC_INLINE uint32_t nu_get32_be(const uint8_t *pos)
  173. {
  174. uint32_t val;
  175. val = *pos ++;
  176. val <<= 8;
  177. val += *pos ++;
  178. val <<= 8;
  179. val += *pos ++;
  180. val <<= 8;
  181. val += *pos;
  182. return val;
  183. }
  184. /* Set 32-bit to a byte-array in big-endian */
  185. __STATIC_INLINE void nu_set32_be(uint8_t *pos, uint32_t val)
  186. {
  187. *pos ++ = val >> 24;
  188. *pos ++ = val >> 16;
  189. *pos ++ = val >> 8;
  190. *pos ++ = (val & 0xFF);
  191. }
  192. #ifdef __cplusplus
  193. }
  194. #endif
  195. #endif //__NU_BITUTIL_H__