]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_core/include/csi-gcc/csi_instr.h
Introduce a port for T-HEAD CK802. A simple demo for T-HEAD CB2201 is also included.
[freertos] / FreeRTOS / Demo / T-HEAD_CB2201_CDK / csi / csi_core / include / csi-gcc / csi_instr.h
1 /*
2  * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /******************************************************************************
18  * @file     csi_instr.h
19  * @brief    CSI Header File for instruct.
20  * @version  V1.0
21  * @date     02. June 2017
22  ******************************************************************************/
23
24 #ifndef _CSI_INSTR_H_
25 #define _CSI_INSTR_H_
26
27
28 #define __CSI_GCC_OUT_REG(r) "=r" (r)
29 #define __CSI_GCC_USE_REG(r) "r" (r)
30
31 /**
32   \brief   No Operation
33   \details No Operation does nothing. This instruction can be used for code alignment purposes.
34  */
35 __ALWAYS_INLINE void __NOP(void)
36 {
37     __ASM volatile("nop");
38 }
39
40
41 /**
42   \brief   Wait For Interrupt
43   \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
44  */
45 __ALWAYS_INLINE void __WFI(void)
46 {
47     __ASM volatile("wait");
48 }
49
50 /**
51   \brief   Wait For Interrupt
52   \details Wait For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
53  */
54 __ALWAYS_INLINE void __WAIT(void)
55 {
56     __ASM volatile("wait");
57 }
58
59 /**
60   \brief   Doze For Interrupt
61   \details Doze For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
62  */
63 __ALWAYS_INLINE void __DOZE(void)
64 {
65     __ASM volatile("doze");
66 }
67
68 /**
69   \brief   Stop For Interrupt
70   \details Stop For Interrupt is a hint instruction that suspends execution until one interrupt occurs.
71  */
72 __ALWAYS_INLINE void __STOP(void)
73 {
74     __ASM volatile("stop");
75 }
76
77 /**
78   \brief   Instruction Synchronization Barrier
79   \details Instruction Synchronization Barrier flushes the pipeline in the processor,
80            so that all instructions following the ISB are fetched from cache or memory,
81            after the instruction has been completed.
82  */
83 __ALWAYS_INLINE void __ISB(void)
84 {
85     __ASM volatile("sync"::: "memory");
86 }
87
88
89 /**
90   \brief   Data Synchronization Barrier
91   \details Acts as a special kind of Data Memory Barrier.
92            It completes when all explicit memory accesses before this instruction complete.
93  */
94 __ALWAYS_INLINE void __DSB(void)
95 {
96     __ASM volatile("sync"::: "memory");
97 }
98
99
100 /**
101   \brief   Data Memory Barrier
102   \details Ensures the apparent order of the explicit memory operations before
103            and after the instruction, without ensuring their completion.
104  */
105 __ALWAYS_INLINE void __DMB(void)
106 {
107     __ASM volatile("sync"::: "memory");
108 }
109
110
111 /**
112   \brief   Reverse byte order (32 bit)
113   \details Reverses the byte order in integer value.
114   \param [in]    value  Value to reverse
115   \return               Reversed value
116  */
117 __ALWAYS_INLINE uint32_t __REV(uint32_t value)
118 {
119     return __builtin_bswap32(value);
120 }
121
122
123 /**
124   \brief   Reverse byte order (16 bit)
125   \details Reverses the byte order in two unsigned short values.
126   \param [in]    value  Value to reverse
127   \return               Reversed value
128  */
129 __ALWAYS_INLINE uint32_t __REV16(uint32_t value)
130 {
131     uint32_t result;
132 #if (__CK80X >= 2)
133     __ASM volatile("revh %0, %1" : __CSI_GCC_OUT_REG(result) : __CSI_GCC_USE_REG(value));
134 #else
135     result = ((value & 0xFF000000) >> 8) | ((value & 0x00FF0000) << 8) |
136              ((value & 0x0000FF00) >> 8) | ((value & 0x000000FF) << 8);
137 #endif
138     return (result);
139 }
140
141
142 /**
143   \brief   Reverse byte order in signed short value
144   \details Reverses the byte order in a signed short value with sign extension to integer.
145   \param [in]    value  Value to reverse
146   \return               Reversed value
147  */
148 __ALWAYS_INLINE int32_t __REVSH(int32_t value)
149 {
150     return (short)(((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8));
151 }
152
153
154 /**
155   \brief   Rotate Right in unsigned value (32 bit)
156   \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
157   \param [in]    op1  Value to rotate
158   \param [in]    op2  Number of Bits to rotate
159   \return               Rotated value
160  */
161 __ALWAYS_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
162 {
163     return (op1 >> op2) | (op1 << (32U - op2));
164 }
165
166
167 /**
168   \brief   Breakpoint
169   \details Causes the processor to enter Debug state
170            Debug tools can use this to investigate system state when the instruction at a particular address is reached.
171  */
172 __ALWAYS_INLINE void __BKPT()
173 {
174     __ASM volatile("bkpt");
175 }
176
177 /**
178   \brief   Reverse bit order of value
179   \details Reverses the bit order of the given value.
180   \param [in]    value  Value to reverse
181   \return               Reversed value
182  */
183 __ALWAYS_INLINE uint32_t __RBIT(uint32_t value)
184 {
185     uint32_t result;
186
187 #if (__CK80X >= 0x03U)
188     __ASM volatile("brev %0, %1" : "=r"(result) : "r"(value));
189 #else
190     int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */
191
192     result = value;                      /* r will be reversed bits of v; first get LSB of v */
193
194     for (value >>= 1U; value; value >>= 1U) {
195         result <<= 1U;
196         result |= value & 1U;
197         s--;
198     }
199
200     result <<= s;                        /* shift when v's highest bits are zero */
201 #endif
202     return (result);
203 }
204
205
206 /**
207   \brief   Count leading zeros
208   \details Counts the number of leading zeros of a data value.
209   \param [in]  value  Value to count the leading zeros
210   \return             number of leading zeros in value
211  */
212 #define __CLZ             __builtin_clz
213 /**
214   \details This function saturates a signed value.
215   \param [in]    x   Value to be saturated
216   \param [in]    y   Bit position to saturate to [1..32]
217   \return            Saturated value.
218  */
219 __ALWAYS_INLINE int32_t __SSAT(int32_t x, uint32_t y)
220 {
221     int32_t posMax, negMin;
222     uint32_t i;
223
224     posMax = 1;
225
226     for (i = 0; i < (y - 1); i++) {
227         posMax = posMax * 2;
228     }
229
230     if (x > 0) {
231         posMax = (posMax - 1);
232
233         if (x > posMax) {
234             x = posMax;
235         }
236
237 //    x &= (posMax * 2 + 1);
238     } else {
239         negMin = -posMax;
240
241         if (x < negMin) {
242             x = negMin;
243         }
244
245 //    x &= (posMax * 2 - 1);
246     }
247
248     return (x);
249 }
250
251 /**
252   \brief   Unsigned Saturate
253   \details Saturates an unsigned value.
254   \param [in]  value  Value to be saturated
255   \param [in]    sat  Bit position to saturate to (0..31)
256   \return             Saturated value
257  */
258 __ALWAYS_INLINE uint32_t __USAT(uint32_t value, uint32_t sat)
259 {
260     uint32_t result;
261
262     if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) {
263         result = 0xFFFFFFFF >> (32 - sat);
264     } else {
265         result = value;
266     }
267
268     return (result);
269 }
270
271 /**
272   \brief   Unsigned Saturate for internal use
273   \details Saturates an unsigned value, should not call directly.
274   \param [in]  value  Value to be saturated
275   \param [in]    sat  Bit position to saturate to (0..31)
276   \return             Saturated value
277  */
278 __ALWAYS_INLINE uint32_t __IUSAT(uint32_t value, uint32_t sat)
279 {
280     uint32_t result;
281
282     if (value & 0x80000000) { /* only overflow set bit-31 */
283         result = 0;
284     } else if ((((0xFFFFFFFF >> sat) << sat) & value) != 0) {
285         result = 0xFFFFFFFF >> (32 - sat);
286     } else {
287         result = value;
288     }
289
290     return (result);
291 }
292
293 /**
294   \brief   Rotate Right with Extend
295   \details This function moves each bit of a bitstring right by one bit.
296            The carry input is shifted in at the left end of the bitstring.
297   \note    carry input will always 0.
298   \param [in]    op1  Value to rotate
299   \return               Rotated value
300  */
301 __ALWAYS_INLINE uint32_t __RRX(uint32_t op1)
302 {
303 #if (__CK80X >= 2)
304     uint32_t res = 0;
305     __ASM volatile("bgeni    t0, 31\n\t"
306                    "lsri     %0, 1\n\t"
307                    "movt     %1, t0\n\t"
308                    "or       %1, %1, %0\n\t"
309                : "=r"(op1), "=r"(res): "0"(op1), "1"(res): "t0");
310     return res;
311 #else
312     uint32_t res = 0;
313     __ASM volatile("movi     r7, 0\n\t"
314                    "bseti    r7, 31\n\t"
315                    "lsri     %0, 1\n\t"
316                    "bf       1f\n\t"
317                    "mov     %1, r7\n\t"
318                    "1:\n\t"
319                    "or       %1, %1, %0\n\t"
320                : "=r"(op1), "=r"(res): "0"(op1), "1"(res): "r7");
321     return res;
322 #endif
323 }
324
325 /**
326   \brief   LDRT Unprivileged (8 bit)
327   \details Executes a Unprivileged LDRT instruction for 8 bit value.
328   \param [in]    addr  Pointer to location
329   \return             value of type uint8_t at (*ptr)
330  */
331 __ALWAYS_INLINE uint8_t __LDRBT(volatile uint8_t *addr)
332 {
333     uint32_t result;
334 //#warning "__LDRBT"
335     __ASM volatile("ldb %0, (%1, 0)" : "=r"(result) : "r"(addr));
336     return ((uint8_t) result);    /* Add explicit type cast here */
337 }
338
339
340 /**
341   \brief   LDRT Unprivileged (16 bit)
342   \details Executes a Unprivileged LDRT instruction for 16 bit values.
343   \param [in]    addr  Pointer to location
344   \return        value of type uint16_t at (*ptr)
345  */
346 __ALWAYS_INLINE uint16_t __LDRHT(volatile uint16_t *addr)
347 {
348     uint32_t result;
349
350 //#warning "__LDRHT"
351     __ASM volatile("ldh %0, (%1, 0)" : "=r"(result) : "r"(addr));
352     return ((uint16_t) result);    /* Add explicit type cast here */
353 }
354
355
356 /**
357   \brief   LDRT Unprivileged (32 bit)
358   \details Executes a Unprivileged LDRT instruction for 32 bit values.
359   \param [in]    addr  Pointer to location
360   \return        value of type uint32_t at (*ptr)
361  */
362 __ALWAYS_INLINE uint32_t __LDRT(volatile uint32_t *addr)
363 {
364     uint32_t result;
365
366 //#warning "__LDRT"
367     __ASM volatile("ldw %0, (%1, 0)" : "=r"(result) : "r"(addr));
368     return (result);
369 }
370
371
372 /**
373   \brief   STRT Unprivileged (8 bit)
374   \details Executes a Unprivileged STRT instruction for 8 bit values.
375   \param [in]  value  Value to store
376   \param [in]    addr  Pointer to location
377  */
378 __ALWAYS_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr)
379 {
380 //#warning "__STRBT"
381     __ASM volatile("stb %1, (%0, 0)" :: "r"(addr), "r"((uint32_t)value) : "memory");
382 }
383
384
385 /**
386   \brief   STRT Unprivileged (16 bit)
387   \details Executes a Unprivileged STRT instruction for 16 bit values.
388   \param [in]  value  Value to store
389   \param [in]    addr  Pointer to location
390  */
391 __ALWAYS_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr)
392 {
393 //#warning "__STRHT"
394     __ASM volatile("sth %1, (%0, 0)" :: "r"(addr), "r"((uint32_t)value) : "memory");
395 }
396
397
398 /**
399   \brief   STRT Unprivileged (32 bit)
400   \details Executes a Unprivileged STRT instruction for 32 bit values.
401   \param [in]  value  Value to store
402   \param [in]    addr  Pointer to location
403  */
404 __ALWAYS_INLINE void __STRT(uint32_t value, volatile uint32_t *addr)
405 {
406 //#warning "__STRT"
407     __ASM volatile("stw %1, (%0, 0)" :: "r"(addr), "r"(value) : "memory");
408 }
409
410 /*@}*/ /* end of group CSI_Core_InstructionInterface */
411
412
413 /* ##########################  FPU functions  #################################### */
414
415 /**
416   \brief   get FPU type
417   \details returns the FPU type, always 0.
418   \returns
419    - \b  0: No FPU
420    - \b  1: Single precision FPU
421    - \b  2: Double + Single precision FPU
422  */
423 __ALWAYS_INLINE uint32_t __get_FPUType(void)
424 {
425     uint32_t result;
426
427 #ifdef __CK610
428     __ASM volatile("mfcr %0, cr13" : "=r"(result));
429 #else
430     __ASM volatile("mfcr %0, cr<13, 0>" : "=r"(result));
431 #endif
432     return 0;
433 }
434
435
436 #endif /* _CSI_INSTR_H_ */