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