]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_armclang.h
Core(M): Added cast to __USAT error return value to suppress compiler warnings.
[cmsis] / CMSIS / Core_A / Include / cmsis_armclang.h
1 /**************************************************************************//**
2  * @file     cmsis_armclang.h
3  * @brief    CMSIS compiler specific macros, functions, instructions
4  * @version  V1.0.1
5  * @date     07. Sep 2017
6  ******************************************************************************/
7 /*
8  * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  *
12  * Licensed under the Apache License, Version 2.0 (the License); you may
13  * not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  * www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
20  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */
24
25 #ifndef __CMSIS_ARMCLANG_H
26 #define __CMSIS_ARMCLANG_H
27
28 #ifndef __ARM_COMPAT_H
29 #include <arm_compat.h>    /* Compatibility header for ARM Compiler 5 intrinsics */
30 #endif
31
32 /* CMSIS compiler specific defines */
33 #ifndef   __ASM
34   #define __ASM                                  __asm
35 #endif                                          
36 #ifndef   __INLINE                              
37   #define __INLINE                               __inline
38 #endif                                          
39 #ifndef   __FORCEINLINE                              
40   #define __FORCEINLINE                          __attribute__((always_inline))
41 #endif                                          
42 #ifndef   __STATIC_INLINE                       
43   #define __STATIC_INLINE                        static __inline
44 #endif                                                                                    
45 #ifndef   __STATIC_FORCEINLINE                 
46   #define __STATIC_FORCEINLINE                   __attribute__((always_inline)) static __inline
47 #endif                                           
48 #ifndef   __NO_RETURN                           
49   #define __NO_RETURN                            __declspec(noreturn)
50 #endif                                          
51 #ifndef   __USED                                
52   #define __USED                                 __attribute__((used))
53 #endif                                          
54 #ifndef   __WEAK                                
55   #define __WEAK                                 __attribute__((weak))
56 #endif
57 #ifndef   __PACKED
58   #define __PACKED                               __attribute__((packed, aligned(1)))
59 #endif
60 #ifndef   __PACKED_STRUCT
61   #define __PACKED_STRUCT                        struct __attribute__((packed, aligned(1)))
62 #endif
63 #ifndef   __UNALIGNED_UINT16_WRITE
64   #pragma clang diagnostic push
65   #pragma clang diagnostic ignored "-Wpacked"
66 /*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
67   __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
68   #pragma clang diagnostic pop
69   #define __UNALIGNED_UINT16_WRITE(addr, val)    (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
70 #endif
71 #ifndef   __UNALIGNED_UINT16_READ
72   #pragma clang diagnostic push
73   #pragma clang diagnostic ignored "-Wpacked"
74 /*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
75   __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
76   #pragma clang diagnostic pop
77   #define __UNALIGNED_UINT16_READ(addr)          (((const struct T_UINT16_READ *)(const void *)(addr))->v)
78 #endif
79 #ifndef   __UNALIGNED_UINT32_WRITE
80   #pragma clang diagnostic push
81   #pragma clang diagnostic ignored "-Wpacked"
82 /*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
83   __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
84   #pragma clang diagnostic pop
85   #define __UNALIGNED_UINT32_WRITE(addr, val)    (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
86 #endif
87 #ifndef   __UNALIGNED_UINT32_READ
88   #pragma clang diagnostic push
89   #pragma clang diagnostic ignored "-Wpacked"
90   __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
91   #pragma clang diagnostic pop
92   #define __UNALIGNED_UINT32_READ(addr)          (((const struct T_UINT32_READ *)(const void *)(addr))->v)
93 #endif
94 #ifndef   __ALIGNED
95   #define __ALIGNED(x)                           __attribute__((aligned(x)))
96 #endif                                        
97 #ifndef   __PACKED                            
98   #define __PACKED                               __attribute__((packed))
99 #endif
100
101 /* ##########################  Core Instruction Access  ######################### */
102 /**
103   \brief   No Operation
104  */
105 #define __NOP                             __builtin_arm_nop
106
107 /**
108   \brief   Wait For Interrupt
109  */
110 #define __WFI                             __builtin_arm_wfi
111
112 /**
113   \brief   Wait For Event
114  */
115 #define __WFE                             __builtin_arm_wfe
116
117 /**
118   \brief   Send Event
119  */
120 #define __SEV                             __builtin_arm_sev
121
122 /**
123   \brief   Instruction Synchronization Barrier
124  */
125 #define __ISB() do {\
126                    __schedule_barrier();\
127                    __builtin_arm_isb(0xF);\
128                    __schedule_barrier();\
129                 } while (0U)
130
131 /**
132   \brief   Data Synchronization Barrier
133  */
134 #define __DSB() do {\
135                    __schedule_barrier();\
136                    __builtin_arm_dsb(0xF);\
137                    __schedule_barrier();\
138                 } while (0U)
139
140 /**
141   \brief   Data Memory Barrier
142  */
143 #define __DMB() do {\
144                    __schedule_barrier();\
145                    __builtin_arm_dmb(0xF);\
146                    __schedule_barrier();\
147                 } while (0U)
148
149 /**
150   \brief   Reverse byte order (32 bit)
151   \param [in]    value  Value to reverse
152   \return               Reversed value
153  */
154 #define __REV                             __builtin_bswap32
155
156 /**
157   \brief   Reverse byte order (16 bit)
158   \param [in]    value  Value to reverse
159   \return               Reversed value
160  */
161 #ifndef __NO_EMBEDDED_ASM
162 __attribute__((section(".rev16_text"))) __STATIC_INLINE uint32_t __REV16(uint32_t value)
163 {
164   uint32_t result;
165   __ASM volatile("rev16 %0, %1" : "=r" (result) : "r" (value));
166   return result;
167 }
168 #endif
169
170 /**
171   \brief   Reverse byte order in signed short value
172   \param [in]    value  Value to reverse
173   \return               Reversed value
174  */
175 #ifndef __NO_EMBEDDED_ASM
176 __attribute__((section(".revsh_text"))) __STATIC_INLINE int32_t __REVSH(int32_t value)
177 {
178   int32_t result;
179   __ASM volatile("revsh %0, %1" : "=r" (result) : "r" (value));
180   return result;
181 }
182 #endif
183
184 /**
185   \brief   Rotate Right in unsigned value (32 bit)
186   \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
187   \param [in]    op1  Value to rotate
188   \param [in]    op2  Number of Bits to rotate
189   \return               Rotated value
190  */
191 __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
192 {
193   return (op1 >> op2) | (op1 << (32U - op2));
194 }
195
196 /**
197   \brief   Breakpoint
198   \param [in]    value  is ignored by the processor.
199                  If required, a debugger can use it to store additional information about the breakpoint.
200  */
201 #define __BKPT(value)                       __ASM volatile ("bkpt "#value)
202
203 /**
204   \brief   Reverse bit order of value
205   \param [in]    value  Value to reverse
206   \return               Reversed value
207  */
208 #define __RBIT                            __builtin_arm_rbit
209
210 /**
211   \brief   Count leading zeros
212   \param [in]  value  Value to count the leading zeros
213   \return             number of leading zeros in value
214  */
215 #define __CLZ                             __builtin_clz
216
217 /**
218   \brief   LDR Exclusive (8 bit)
219   \details Executes a exclusive LDR instruction for 8 bit value.
220   \param [in]    ptr  Pointer to data
221   \return             value of type uint8_t at (*ptr)
222  */
223 #define __LDREXB        (uint8_t)__builtin_arm_ldrex
224
225
226 /**
227   \brief   LDR Exclusive (16 bit)
228   \details Executes a exclusive LDR instruction for 16 bit values.
229   \param [in]    ptr  Pointer to data
230   \return        value of type uint16_t at (*ptr)
231  */
232 #define __LDREXH        (uint16_t)__builtin_arm_ldrex
233
234 /**
235   \brief   LDR Exclusive (32 bit)
236   \details Executes a exclusive LDR instruction for 32 bit values.
237   \param [in]    ptr  Pointer to data
238   \return        value of type uint32_t at (*ptr)
239  */
240 #define __LDREXW        (uint32_t)__builtin_arm_ldrex
241
242 /**
243   \brief   STR Exclusive (8 bit)
244   \details Executes a exclusive STR instruction for 8 bit values.
245   \param [in]  value  Value to store
246   \param [in]    ptr  Pointer to location
247   \return          0  Function succeeded
248   \return          1  Function failed
249  */
250 #define __STREXB        (uint32_t)__builtin_arm_strex
251
252 /**
253   \brief   STR Exclusive (16 bit)
254   \details Executes a exclusive STR instruction for 16 bit values.
255   \param [in]  value  Value to store
256   \param [in]    ptr  Pointer to location
257   \return          0  Function succeeded
258   \return          1  Function failed
259  */
260 #define __STREXH        (uint32_t)__builtin_arm_strex
261
262 /**
263   \brief   STR Exclusive (32 bit)
264   \details Executes a exclusive STR instruction for 32 bit values.
265   \param [in]  value  Value to store
266   \param [in]    ptr  Pointer to location
267   \return          0  Function succeeded
268   \return          1  Function failed
269  */
270 #define __STREXW        (uint32_t)__builtin_arm_strex
271
272 /**
273   \brief   Remove the exclusive lock
274   \details Removes the exclusive lock which is created by LDREX.
275  */
276 #define __CLREX             __builtin_arm_clrex
277
278 /**
279   \brief   Signed Saturate
280   \details Saturates a signed value.
281   \param [in]  value  Value to be saturated
282   \param [in]    sat  Bit position to saturate to (1..32)
283   \return             Saturated value
284  */
285 #define __SSAT             __builtin_arm_ssat
286
287 /**
288   \brief   Unsigned Saturate
289   \details Saturates an unsigned value.
290   \param [in]  value  Value to be saturated
291   \param [in]    sat  Bit position to saturate to (0..31)
292   \return             Saturated value
293  */
294 #define __USAT             __builtin_arm_usat
295
296
297 /* ###########################  Core Function Access  ########################### */
298
299 /**
300   \brief   Get FPSCR
301   \details Returns the current value of the Floating Point Status/Control register.
302   \return               Floating Point Status/Control register value
303  */
304 #define __get_FPSCR      __builtin_arm_get_fpscr
305
306 /**
307   \brief   Set FPSCR
308   \details Assigns the given value to the Floating Point Status/Control register.
309   \param [in]    fpscr  Floating Point Status/Control value to set
310  */
311 #define __set_FPSCR      __builtin_arm_set_fpscr
312
313 /** \brief  Get CPSR Register
314     \return               CPSR Register value
315  */
316 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CPSR(void)
317 {
318   uint32_t result;
319   __ASM volatile("MRS %0, cpsr" : "=r" (result) );
320   return(result);
321 }
322
323 /** \brief  Set CPSR Register
324     \param [in]    cpsr  CPSR value to set
325  */
326 __attribute__((always_inline)) __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
327 {
328 __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
329 }
330
331 /** \brief  Get Mode
332     \return                Processor Mode
333  */
334 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_mode(void)
335 {
336         return (__get_CPSR() & 0x1FU);
337 }
338
339 /** \brief  Set Mode
340     \param [in]    mode  Mode value to set
341  */
342 __attribute__((always_inline)) __STATIC_INLINE void __set_mode(uint32_t mode)
343 {
344   __ASM volatile("MSR  cpsr_c, %0" : : "r" (mode) : "memory");
345 }
346
347 /** \brief  Get Stack Pointer
348     \return Stack Pointer value
349  */
350 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_SP()
351 {
352   uint32_t result;
353   __ASM volatile("MOV  %0, sp" : "=r" (result) : : "memory");
354   return result;
355 }
356
357 /** \brief  Set Stack Pointer
358     \param [in]    stack  Stack Pointer value to set
359  */
360 __attribute__((always_inline)) __STATIC_INLINE void __set_SP(uint32_t stack)
361 {
362   __ASM volatile("MOV  sp, %0" : : "r" (stack) : "memory");
363 }
364
365 /** \brief  Get USR/SYS Stack Pointer
366     \return USR/SYS Stack Pointer value
367  */
368 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_SP_usr()
369 {
370   uint32_t cpsr;
371   uint32_t result;
372   __ASM volatile(
373     "MRS     %0, cpsr   \n"
374     "CPS     #0x1F      \n" // no effect in USR mode
375     "MOV     %1, sp     \n"
376     "MSR     cpsr_c, %2 \n" // no effect in USR mode
377     "ISB" :  "=r"(cpsr), "=r"(result) : "r"(cpsr) : "memory"
378    );
379   return result;
380 }
381
382 /** \brief  Set USR/SYS Stack Pointer
383     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
384  */
385 __attribute__((always_inline)) __STATIC_INLINE void __set_SP_usr(uint32_t topOfProcStack)
386 {
387   uint32_t cpsr;
388   __ASM volatile(
389     "MRS     %0, cpsr   \n"
390     "CPS     #0x1F      \n" // no effect in USR mode
391     "MOV     sp, %1     \n"
392     "MSR     cpsr_c, %2 \n" // no effect in USR mode
393     "ISB" : "=r"(cpsr) : "r" (topOfProcStack), "r"(cpsr) : "memory"
394    );
395 }
396
397 /** \brief  Get FPEXC
398     \return               Floating Point Exception Control register value
399  */
400 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPEXC(void)
401 {
402 #if (__FPU_PRESENT == 1)
403   uint32_t result;
404   __ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory");
405   return(result);
406 #else
407   return(0);
408 #endif
409 }
410
411 /** \brief  Set FPEXC
412     \param [in]    fpexc  Floating Point Exception Control value to set
413  */
414 __attribute__((always_inline)) __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
415 {
416 #if (__FPU_PRESENT == 1)
417   __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
418 #endif
419 }
420
421 /*
422  * Include common core functions to access Coprocessor 15 registers
423  */
424
425 #define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
426 #define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
427
428 #include "cmsis_cp15.h"
429
430
431 /** \brief  Clean and Invalidate the entire data or unified cache
432
433   Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
434  */
435 __STATIC_INLINE void __L1C_CleanInvalidateCache(uint32_t op)
436 {
437   __ASM volatile(
438     "        PUSH    {R4-R11}                   \n"
439
440     "        MRC     p15, 1, R6, c0, c0, 1      \n" // Read CLIDR
441     "        ANDS    R3, R6, #0x07000000        \n" // Extract coherency level
442     "        MOV     R3, R3, LSR #23            \n" // Total cache levels << 1
443     "        BEQ     Finished                   \n" // If 0, no need to clean
444
445     "        MOV     R10, #0                    \n" // R10 holds current cache level << 1
446     "Loop1:  ADD     R2, R10, R10, LSR #1       \n" // R2 holds cache "Set" position
447     "        MOV     R1, R6, LSR R2             \n" // Bottom 3 bits are the Cache-type for this level
448     "        AND     R1, R1, #7                 \n" // Isolate those lower 3 bits
449     "        CMP     R1, #2                     \n"
450     "        BLT     Skip                       \n" // No cache or only instruction cache at this level
451
452     "        MCR     p15, 2, R10, c0, c0, 0     \n" // Write the Cache Size selection register
453     "        ISB                                \n" // ISB to sync the change to the CacheSizeID reg
454     "        MRC     p15, 1, R1, c0, c0, 0      \n" // Reads current Cache Size ID register
455     "        AND     R2, R1, #7                 \n" // Extract the line length field
456     "        ADD     R2, R2, #4                 \n" // Add 4 for the line length offset (log2 16 bytes)
457     "        LDR     R4, =0x3FF                 \n"
458     "        ANDS    R4, R4, R1, LSR #3         \n" // R4 is the max number on the way size (right aligned)
459     "        CLZ     R5, R4                     \n" // R5 is the bit position of the way size increment
460     "        LDR     R7, =0x7FFF                \n"
461     "        ANDS    R7, R7, R1, LSR #13        \n" // R7 is the max number of the index size (right aligned)
462
463     "Loop2:  MOV     R9, R4                     \n" // R9 working copy of the max way size (right aligned)
464
465     "Loop3:  ORR     R11, R10, R9, LSL R5       \n" // Factor in the Way number and cache number into R11
466     "        ORR     R11, R11, R7, LSL R2       \n" // Factor in the Set number
467     "        CMP     R0, #0                     \n"
468     "        BNE     Dccsw                      \n"
469     "        MCR     p15, 0, R11, c7, c6, 2     \n" // DCISW. Invalidate by Set/Way
470     "        B       cont                       \n"
471     "Dccsw:  CMP     R0, #1                     \n"
472     "        BNE     Dccisw                     \n"
473     "        MCR     p15, 0, R11, c7, c10, 2    \n" // DCCSW. Clean by Set/Way
474     "        B       cont                       \n"
475     "Dccisw: MCR     p15, 0, R11, c7, c14, 2    \n" // DCCISW. Clean and Invalidate by Set/Way
476     "cont:   SUBS    R9, R9, #1                 \n" // Decrement the Way number
477     "        BGE     Loop3                      \n"
478     "        SUBS    R7, R7, #1                 \n" // Decrement the Set number
479     "        BGE     Loop2                      \n"
480     "Skip:   ADD     R10, R10, #2               \n" // Increment the cache number
481     "        CMP     R3, R10                    \n"
482     "        BGT     Loop1                      \n"
483
484     "Finished:                                  \n"
485     "        DSB                                \n"
486     "        POP    {R4-R11}                      "
487   );
488 }
489
490 /** \brief  Enable Floating Point Unit
491
492   Critical section, called from undef handler, so systick is disabled
493  */
494 __STATIC_INLINE void __FPU_Enable(void)
495 {
496   __ASM volatile(
497             //Permit access to VFP/NEON, registers by modifying CPACR
498     "        MRC     p15,0,R1,c1,c0,2  \n"
499     "        ORR     R1,R1,#0x00F00000 \n"
500     "        MCR     p15,0,R1,c1,c0,2  \n"
501
502             //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
503     "        ISB                       \n"
504
505             //Enable VFP/NEON
506     "        VMRS    R1,FPEXC          \n"
507     "        ORR     R1,R1,#0x40000000 \n"
508     "        VMSR    FPEXC,R1          \n"
509
510             //Initialise VFP/NEON registers to 0
511     "        MOV     R2,#0             \n"
512
513 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT >= 16
514             //Initialise D16 registers to 0
515     "        VMOV    D0, R2,R2         \n"
516     "        VMOV    D1, R2,R2         \n"
517     "        VMOV    D2, R2,R2         \n"
518     "        VMOV    D3, R2,R2         \n"
519     "        VMOV    D4, R2,R2         \n"
520     "        VMOV    D5, R2,R2         \n"
521     "        VMOV    D6, R2,R2         \n"
522     "        VMOV    D7, R2,R2         \n"
523     "        VMOV    D8, R2,R2         \n"
524     "        VMOV    D9, R2,R2         \n"
525     "        VMOV    D10,R2,R2         \n"
526     "        VMOV    D11,R2,R2         \n"
527     "        VMOV    D12,R2,R2         \n"
528     "        VMOV    D13,R2,R2         \n"
529     "        VMOV    D14,R2,R2         \n"
530     "        VMOV    D15,R2,R2         \n"
531 #endif
532
533 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
534             //Initialise D32 registers to 0
535     "        VMOV    D16,R2,R2         \n"
536     "        VMOV    D17,R2,R2         \n"
537     "        VMOV    D18,R2,R2         \n"
538     "        VMOV    D19,R2,R2         \n"
539     "        VMOV    D20,R2,R2         \n"
540     "        VMOV    D21,R2,R2         \n"
541     "        VMOV    D22,R2,R2         \n"
542     "        VMOV    D23,R2,R2         \n"
543     "        VMOV    D24,R2,R2         \n"
544     "        VMOV    D25,R2,R2         \n"
545     "        VMOV    D26,R2,R2         \n"
546     "        VMOV    D27,R2,R2         \n"
547     "        VMOV    D28,R2,R2         \n"
548     "        VMOV    D29,R2,R2         \n"
549     "        VMOV    D30,R2,R2         \n"
550     "        VMOV    D31,R2,R2         \n"
551     ".endif                            \n"
552 #endif
553             //Initialise FPSCR to a known state
554     "        VMRS    R2,FPSCR          \n"
555     "        LDR     R3,=0x00086060    \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
556     "        AND     R2,R2,R3          \n"
557     "        VMSR    FPSCR,R2            "
558   );
559 }
560
561 #endif /* __CMSIS_ARMCLANG_H */