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