core_compatiable.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. * Copyright (c) 2019 Nuclei Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #ifndef __CORE_COMPATIABLE_H__
  19. #define __CORE_COMPATIABLE_H__
  20. /*!
  21. * @file core_compatiable.h
  22. * @brief ARM compatiable function definitions header file
  23. */
  24. #ifdef __cplusplus
  25. extern "C" {
  26. #endif
  27. #include "core_feature_base.h"
  28. /* ===== ARM Compatiable Functions ===== */
  29. /**
  30. * \defgroup NMSIS_Core_ARMCompatiable_Functions ARM Compatiable Functions
  31. * \ingroup NMSIS_Core
  32. * \brief A few functions that compatiable with ARM CMSIS-Core.
  33. * \details
  34. *
  35. * Here we provided a few functions that compatiable with ARM CMSIS-Core,
  36. * mostly used in the DSP and NN library.
  37. * @{
  38. */
  39. /** \brief Instruction Synchronization Barrier, compatiable with ARM */
  40. #define __ISB() __RWMB()
  41. /** \brief Data Synchronization Barrier, compatiable with ARM */
  42. #define __DSB() __RWMB()
  43. /** \brief Data Memory Barrier, compatiable with ARM */
  44. #define __DMB() __RWMB()
  45. /** \brief LDRT Unprivileged (8 bit), ARM Compatiable */
  46. #define __LDRBT(ptr) __LB((ptr))
  47. /** \brief LDRT Unprivileged (16 bit), ARM Compatiable */
  48. #define __LDRHT(ptr) __LH((ptr))
  49. /** \brief LDRT Unprivileged (32 bit), ARM Compatiable */
  50. #define __LDRT(ptr) __LW((ptr))
  51. /** \brief STRT Unprivileged (8 bit), ARM Compatiable */
  52. #define __STRBT(val, ptr) __SB((ptr), (val))
  53. /** \brief STRT Unprivileged (16 bit), ARM Compatiable */
  54. #define __STRHT(val, ptr) __SH((ptr), (val))
  55. /** \brief STRT Unprivileged (32 bit), ARM Compatiable */
  56. #define __STRT(val, ptr) __SW((ptr), (val))
  57. /* ===== Saturation Operations ===== */
  58. /**
  59. * \brief Signed Saturate
  60. * \details Saturates a signed value.
  61. * \param [in] value Value to be saturated
  62. * \param [in] sat Bit position to saturate to (1..32)
  63. * \return Saturated value
  64. */
  65. #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
  66. #define __SSAT(val, sat) __RV_SCLIP32((val), (sat-1))
  67. #else
  68. __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
  69. {
  70. if ((sat >= 1U) && (sat <= 32U)) {
  71. const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
  72. const int32_t min = -1 - max ;
  73. if (val > max) {
  74. return max;
  75. } else if (val < min) {
  76. return min;
  77. }
  78. }
  79. return val;
  80. }
  81. #endif
  82. /**
  83. * \brief Unsigned Saturate
  84. * \details Saturates an unsigned value.
  85. * \param [in] value Value to be saturated
  86. * \param [in] sat Bit position to saturate to (0..31)
  87. * \return Saturated value
  88. */
  89. #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
  90. #define __USAT(val, sat) __RV_UCLIP32((val), (sat))
  91. #else
  92. __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
  93. {
  94. if (sat <= 31U) {
  95. const uint32_t max = ((1U << sat) - 1U);
  96. if (val > (int32_t)max) {
  97. return max;
  98. } else if (val < 0) {
  99. return 0U;
  100. }
  101. }
  102. return (uint32_t)val;
  103. }
  104. #endif
  105. /* ===== Data Processing Operations ===== */
  106. /**
  107. * \brief Reverse byte order (32 bit)
  108. * \details Reverses the byte order in unsigned integer value.
  109. * For example, 0x12345678 becomes 0x78563412.
  110. * \param [in] value Value to reverse
  111. * \return Reversed value
  112. */
  113. __STATIC_FORCEINLINE uint32_t __REV(uint32_t value)
  114. {
  115. uint32_t result;
  116. result = ((value & 0xff000000) >> 24)
  117. | ((value & 0x00ff0000) >> 8 )
  118. | ((value & 0x0000ff00) << 8 )
  119. | ((value & 0x000000ff) << 24);
  120. return result;
  121. }
  122. /**
  123. * \brief Reverse byte order (16 bit)
  124. * \details Reverses the byte order within each halfword of a word.
  125. * For example, 0x12345678 becomes 0x34127856.
  126. * \param [in] value Value to reverse
  127. * \return Reversed value
  128. */
  129. __STATIC_FORCEINLINE uint32_t __REV16(uint32_t value)
  130. {
  131. uint32_t result;
  132. result = ((value & 0xff000000) >> 8)
  133. | ((value & 0x00ff0000) << 8 )
  134. | ((value & 0x0000ff00) >> 8 )
  135. | ((value & 0x000000ff) << 8) ;
  136. return result;
  137. }
  138. /**
  139. * \brief Reverse byte order (16 bit)
  140. * \details Reverses the byte order in a 16-bit value
  141. * and returns the signed 16-bit result.
  142. * For example, 0x0080 becomes 0x8000.
  143. * \param [in] value Value to reverse
  144. * \return Reversed value
  145. */
  146. __STATIC_FORCEINLINE int16_t __REVSH(int16_t value)
  147. {
  148. int16_t result;
  149. result = ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
  150. return result;
  151. }
  152. /**
  153. * \brief Rotate Right in unsigned value (32 bit)
  154. * \details Rotate Right (immediate) provides the value of
  155. * the contents of a register rotated by a variable number of bits.
  156. * \param [in] op1 Value to rotate
  157. * \param [in] op2 Number of Bits to rotate(0-31)
  158. * \return Rotated value
  159. */
  160. __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
  161. {
  162. op2 = op2 & 0x1F;
  163. if (op2 == 0U) {
  164. return op1;
  165. }
  166. return (op1 >> op2) | (op1 << (32U - op2));
  167. }
  168. /**
  169. * \brief Rotate Right in uint32x2 value (64 bit)
  170. * \details Rotate Right (immediate) provides the value of
  171. * the contents of a register rotated by a variable number of bits.
  172. * \param [in] op1 Value to rotate([63:32] and [31:0] rotate separately)
  173. * \param [in] op2 Number of Bits to rotate
  174. * \return Rotated value([63:32] | [31:0])
  175. */
  176. __STATIC_INLINE uint64_t __ROR64(uint64_t op1, uint32_t op2)
  177. {
  178. op2 = op2 & 0x1F;
  179. if (op2 == 0U) {
  180. return op1;
  181. }
  182. uint32_t tmp1 = (uint32_t)op1;
  183. uint32_t tmp2 = (uint32_t)(op1 >> 32);
  184. return (uint64_t)((tmp1 >> op2) | (tmp1 << (32U - op2)))
  185. | ((uint64_t)((tmp2 >> op2) | (tmp2 << (32U - op2))) << 32);
  186. }
  187. /**
  188. * \brief Reverse bit order of value
  189. * \details Reverses the bit order of the given value.
  190. * \param [in] value Value to reverse
  191. * \return Reversed value
  192. */
  193. #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
  194. #define __RBIT(value) __RV_BITREVI((value), 31)
  195. #else
  196. __STATIC_INLINE uint32_t __RBIT(uint32_t value)
  197. {
  198. uint32_t result;
  199. uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
  200. result = value; /* r will be reversed bits of v; first get LSB of v */
  201. for (value >>= 1U; value != 0U; value >>= 1U) {
  202. result <<= 1U;
  203. result |= value & 1U;
  204. s--;
  205. }
  206. result <<= s; /* shift when v's highest bits are zero */
  207. return result;
  208. }
  209. #endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
  210. /**
  211. * \brief Count leading zeros
  212. * \details Counts the number of leading zeros of a data value.
  213. * \param [in] data Value to count the leading zeros
  214. * \return number of leading zeros in value
  215. */
  216. #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
  217. #define __CLZ(data) __RV_CLZ32(data)
  218. #else
  219. __STATIC_INLINE uint8_t __CLZ(uint32_t data)
  220. {
  221. uint8_t ret = 0;
  222. uint32_t temp = ~data;
  223. while (temp & 0x80000000) {
  224. temp <<= 1;
  225. ret++;
  226. }
  227. return ret;
  228. }
  229. #endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
  230. /**
  231. * \brief Count tailing zero
  232. * \details Return the count of least-significant bit zero.for example, return 3 if x=0bxxx1000
  233. * \param [in] data Value to count the tailing zeros
  234. * \return number of tailing zeros in value
  235. * \remark
  236. * - The value mustn't be 0, or else it will spin here
  237. */
  238. __STATIC_INLINE unsigned long __CTZ(unsigned long data)
  239. {
  240. unsigned long ret = 0;
  241. while (!(data & 1UL)) {
  242. ret++;
  243. data = data >> 1;
  244. }
  245. return ret;
  246. }
  247. /**
  248. * \brief Expand byte to unsigned long value
  249. * \details Expand byte value x to unsigned long value's each byte.
  250. * \param [in] x the byte value to be expand, the input must be uint8_t type
  251. * \return Expanded value in unsigned long
  252. */
  253. #if __RISCV_XLEN == 32
  254. #define __EXPD_BYTE(x) ((unsigned long)(((unsigned long)(x) << 0) | \
  255. ((unsigned long)(x) << 8) | \
  256. ((unsigned long)(x) << 16) | \
  257. ((unsigned long)(x) << 24)))
  258. #elif __RISCV_XLEN == 64
  259. #define __EXPD_BYTE(x) ((unsigned long)(((unsigned long)(x) << 0) | \
  260. ((unsigned long)(x) << 8) | \
  261. ((unsigned long)(x) << 16) | \
  262. ((unsigned long)(x) << 24) | \
  263. ((unsigned long)(x) << 32) | \
  264. ((unsigned long)(x) << 40) | \
  265. ((unsigned long)(x) << 48) | \
  266. ((unsigned long)(x) << 56)))
  267. #endif
  268. /** @} */ /* End of Doxygen Group NMSIS_Core_ARMCompatiable_Functions */
  269. #ifdef __cplusplus
  270. }
  271. #endif
  272. #endif /* __CORE_COMPATIABLE_H__ */