• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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