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
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
42 /** \brief Data Synchronization Barrier, compatiable with ARM */
43 #define __DSB() __RWMB()
44
45 /** \brief Data Memory Barrier, compatiable with ARM */
46 #define __DMB() __RWMB()
47
48 /** \brief LDRT Unprivileged (8 bit), ARM Compatiable */
49 #define __LDRBT(ptr) __LB((ptr))
50 /** \brief LDRT Unprivileged (16 bit), ARM Compatiable */
51 #define __LDRHT(ptr) __LH((ptr))
52 /** \brief LDRT Unprivileged (32 bit), ARM Compatiable */
53 #define __LDRT(ptr) __LW((ptr))
54
55 /** \brief STRT Unprivileged (8 bit), ARM Compatiable */
56 #define __STRBT(val, ptr) __SB((ptr), (val))
57 /** \brief STRT Unprivileged (16 bit), ARM Compatiable */
58 #define __STRHT(val, ptr) __SH((ptr), (val))
59 /** \brief STRT Unprivileged (32 bit), ARM Compatiable */
60 #define __STRT(val, ptr) __SW((ptr), (val))
61
62 /* ===== Saturation Operations ===== */
63 /**
64 * \brief Signed Saturate
65 * \details Saturates a signed value.
66 * \param [in] value Value to be saturated
67 * \param [in] sat Bit position to saturate to (1..32)
68 * \return Saturated value
69 */
70 #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
71 #define __SSAT(val, sat) __RV_SCLIP32((val), (sat-1))
72 #else
73 __STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat)
74 {
75 if ((sat >= 1U) && (sat <= 32U)) {
76 const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
77 const int32_t min = -1 - max ;
78 if (val > max) {
79 return max;
80 } else if (val < min) {
81 return min;
82 }
83 }
84 return val;
85 }
86 #endif
87
88 /**
89 * \brief Unsigned Saturate
90 * \details Saturates an unsigned value.
91 * \param [in] value Value to be saturated
92 * \param [in] sat Bit position to saturate to (0..31)
93 * \return Saturated value
94 */
95 #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
96 #define __USAT(val, sat) __RV_UCLIP32((val), (sat))
97 #else
98 __STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat)
99 {
100 if (sat <= 31U) {
101 const uint32_t max = ((1U << sat) - 1U);
102 if (val > (int32_t)max) {
103 return max;
104 } else if (val < 0) {
105 return 0U;
106 }
107 }
108 return (uint32_t)val;
109 }
110 #endif
111
112 /* ===== Data Processing Operations ===== */
113 /**
114 * \brief Reverse byte order (32 bit)
115 * \details Reverses the byte order in unsigned integer value.
116 * For example, 0x12345678 becomes 0x78563412.
117 * \param [in] value Value to reverse
118 * \return Reversed value
119 */
__REV(uint32_t value)120 __STATIC_FORCEINLINE uint32_t __REV(uint32_t value)
121 {
122 uint32_t result;
123
124 result = ((value & 0xff000000) >> 24)
125 | ((value & 0x00ff0000) >> 8 )
126 | ((value & 0x0000ff00) << 8 )
127 | ((value & 0x000000ff) << 24);
128 return result;
129 }
130
131 /**
132 * \brief Reverse byte order (16 bit)
133 * \details Reverses the byte order within each halfword of a word.
134 * For example, 0x12345678 becomes 0x34127856.
135 * \param [in] value Value to reverse
136 * \return Reversed value
137 */
__REV16(uint32_t value)138 __STATIC_FORCEINLINE uint32_t __REV16(uint32_t value)
139 {
140 uint32_t result;
141 result = ((value & 0xff000000) >> 8)
142 | ((value & 0x00ff00000) << 8 )
143 | ((value & 0x0000ff00) >> 8 )
144 | ((value & 0x000000ff) << 8) ;
145
146 return result;
147 }
148
149 /**
150 * \brief Reverse byte order (16 bit)
151 * \details Reverses the byte order in a 16-bit value
152 * and returns the signed 16-bit result.
153 * For example, 0x0080 becomes 0x8000.
154 * \param [in] value Value to reverse
155 * \return Reversed value
156 */
__REVSH(int16_t value)157 __STATIC_FORCEINLINE int16_t __REVSH(int16_t value)
158 {
159 int16_t result;
160 result = ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
161 return result;
162 }
163
164 /**
165 * \brief Rotate Right in unsigned value (32 bit)
166 * \details Rotate Right (immediate) provides the value of
167 * the contents of a register rotated by a variable number of bits.
168 * \param [in] op1 Value to rotate
169 * \param [in] op2 Number of Bits to rotate(0-31)
170 * \return Rotated value
171 */
__ROR(uint32_t op1,uint32_t op2)172 __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
173 {
174 op2 = op2 & 0x1F;
175 if (op2 == 0U) {
176 return op1;
177 }
178 return (op1 >> op2) | (op1 << (32U - op2));
179 }
180
181 /**
182 * \brief Reverse bit order of value
183 * \details Reverses the bit order of the given value.
184 * \param [in] value Value to reverse
185 * \return Reversed value
186 */
187 #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
188 #define __RBIT(value) __RV_BITREVI((value), 31)
189 #else
__RBIT(uint32_t value)190 __STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value)
191 {
192 uint32_t result;
193 uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
194
195 result = value; /* r will be reversed bits of v; first get LSB of v */
196 for (value >>= 1U; value != 0U; value >>= 1U) {
197 result <<= 1U;
198 result |= value & 1U;
199 s--;
200 }
201 result <<= s; /* shift when v's highest bits are zero */
202 return result;
203 }
204 #endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
205
206 /**
207 * \brief Count leading zeros
208 * \details Counts the number of leading zeros of a data value.
209 * \param [in] data Value to count the leading zeros
210 * \return number of leading zeros in value
211 */
212 #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
213 #define __CLZ(data) __RV_CLZ32(data)
214 #else
__CLZ(uint32_t data)215 __STATIC_FORCEINLINE uint8_t __CLZ(uint32_t data)
216 {
217 uint8_t ret = 0;
218 uint32_t temp = ~data;
219 while (temp & 0x80000000) {
220 temp <<= 1;
221 ret++;
222 }
223 return ret;
224 }
225 #endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
226
227 /** @} */ /* End of Doxygen Group NMSIS_Core_ARMCompatiable_Functions */
228
229 #ifdef __cplusplus
230 }
231 #endif
232 #endif /* __CORE_COMPATIABLE_H__ */
233