]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_armclang.h
CMSIS-Core(A): Added register correlation between CMSIS and TRMs.
[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.00
5  * @date     05. Apr 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   __STATIC_INLINE                       
40   #define __STATIC_INLINE                        static __inline
41 #endif                                                                                    
42 #ifndef   __NO_RETURN                           
43   #define __NO_RETURN                            __declspec(noreturn)
44 #endif                                          
45 #ifndef   __USED                                
46   #define __USED                                 __attribute__((used))
47 #endif                                          
48 #ifndef   __WEAK                                
49   #define __WEAK                                 __attribute__((weak))
50 #endif
51 #ifndef   __PACKED
52   #define __PACKED                               __attribute__((packed, aligned(1)))
53 #endif
54 #ifndef   __PACKED_STRUCT
55   #define __PACKED_STRUCT                        struct __attribute__((packed, aligned(1)))
56 #endif
57 #ifndef   __UNALIGNED_UINT16_WRITE
58   #pragma clang diagnostic push
59   #pragma clang diagnostic ignored "-Wpacked"
60 /*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
61   __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
62   #pragma clang diagnostic pop
63   #define __UNALIGNED_UINT16_WRITE(addr, val)    (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
64 #endif
65 #ifndef   __UNALIGNED_UINT16_READ
66   #pragma clang diagnostic push
67   #pragma clang diagnostic ignored "-Wpacked"
68 /*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
69   __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
70   #pragma clang diagnostic pop
71   #define __UNALIGNED_UINT16_READ(addr)          (((const struct T_UINT16_READ *)(const void *)(addr))->v)
72 #endif
73 #ifndef   __UNALIGNED_UINT32_WRITE
74   #pragma clang diagnostic push
75   #pragma clang diagnostic ignored "-Wpacked"
76 /*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
77   __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
78   #pragma clang diagnostic pop
79   #define __UNALIGNED_UINT32_WRITE(addr, val)    (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
80 #endif
81 #ifndef   __UNALIGNED_UINT32_READ
82   #pragma clang diagnostic push
83   #pragma clang diagnostic ignored "-Wpacked"
84   __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
85   #pragma clang diagnostic pop
86   #define __UNALIGNED_UINT32_READ(addr)          (((const struct T_UINT32_READ *)(const void *)(addr))->v)
87 #endif
88 #ifndef   __ALIGNED
89   #define __ALIGNED(x)                           __attribute__((aligned(x)))
90 #endif                                        
91 #ifndef   __PACKED                            
92   #define __PACKED                               __attribute__((packed))
93 #endif
94
95
96 /* ###########################  Core Function Access  ########################### */
97
98 /**
99   \brief   Get FPSCR
100   \return               Floating Point Status/Control register value
101  */
102 __STATIC_INLINE uint32_t __get_FPSCR(void)
103 {
104 #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
105      (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
106   uint32_t result;
107   __ASM volatile("MRS %0, fpscr" : "=r" (result) );
108   return(result);
109 #else
110    return(0U);
111 #endif
112 }
113
114 /**
115   \brief   Set FPSCR
116   \param [in]    fpscr  Floating Point Status/Control value to set
117  */
118 __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
119 {
120 #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
121      (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
122   __ASM volatile ("MSR fpscr, %0" : : "r" (fpscr) : "memory");
123 #else
124   (void)fpscr;
125 #endif
126 }
127
128 /* ##########################  Core Instruction Access  ######################### */
129 /**
130   \brief   No Operation
131  */
132 #define __NOP                             __builtin_arm_nop
133
134 /**
135   \brief   Wait For Interrupt
136  */
137 #define __WFI                             __builtin_arm_wfi
138
139 /**
140   \brief   Wait For Event
141  */
142 #define __WFE                             __builtin_arm_wfe
143
144 /**
145   \brief   Send Event
146  */
147 #define __SEV                             __builtin_arm_sev
148
149 /**
150   \brief   Instruction Synchronization Barrier
151  */
152 #define __ISB() do {\
153                    __schedule_barrier();\
154                    __builtin_arm_isb(0xF);\
155                    __schedule_barrier();\
156                 } while (0U)
157
158 /**
159   \brief   Data Synchronization Barrier
160  */
161 #define __DSB() do {\
162                    __schedule_barrier();\
163                    __builtin_arm_dsb(0xF);\
164                    __schedule_barrier();\
165                 } while (0U)
166
167 /**
168   \brief   Data Memory Barrier
169  */
170 #define __DMB() do {\
171                    __schedule_barrier();\
172                    __builtin_arm_dmb(0xF);\
173                    __schedule_barrier();\
174                 } while (0U)
175
176 /**
177   \brief   Reverse byte order (32 bit)
178   \param [in]    value  Value to reverse
179   \return               Reversed value
180  */
181 #define __REV                             __builtin_bswap32
182
183 /**
184   \brief   Reverse byte order (16 bit)
185   \param [in]    value  Value to reverse
186   \return               Reversed value
187  */
188 #ifndef __NO_EMBEDDED_ASM
189 __attribute__((section(".rev16_text"))) __STATIC_INLINE uint32_t __REV16(uint32_t value)
190 {
191   uint32_t result;
192   __ASM volatile("rev16 %0, %1" : "=r" (result) : "r" (value));
193   return result;
194 }
195 #endif
196
197 /**
198   \brief   Reverse byte order in signed short value
199   \param [in]    value  Value to reverse
200   \return               Reversed value
201  */
202 #ifndef __NO_EMBEDDED_ASM
203 __attribute__((section(".revsh_text"))) __STATIC_INLINE int32_t __REVSH(int32_t value)
204 {
205   int32_t result;
206   __ASM volatile("revsh %0, %1" : "=r" (result) : "r" (value));
207   return result;
208 }
209 #endif
210
211 /**
212   \brief   Rotate Right in unsigned value (32 bit)
213   \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
214   \param [in]    op1  Value to rotate
215   \param [in]    op2  Number of Bits to rotate
216   \return               Rotated value
217  */
218 __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
219 {
220   return (op1 >> op2) | (op1 << (32U - op2));
221 }
222
223 /**
224   \brief   Breakpoint
225   \param [in]    value  is ignored by the processor.
226                  If required, a debugger can use it to store additional information about the breakpoint.
227  */
228 #define __BKPT(value)                       __ASM volatile ("bkpt "#value)
229
230 /**
231   \brief   Reverse bit order of value
232   \param [in]    value  Value to reverse
233   \return               Reversed value
234  */
235 #define __RBIT                            __builtin_arm_rbit
236
237 /**
238   \brief   Count leading zeros
239   \param [in]  value  Value to count the leading zeros
240   \return             number of leading zeros in value
241  */
242 #define __CLZ                             __builtin_clz
243
244 /**
245   \brief   LDR Exclusive (8 bit)
246   \details Executes a exclusive LDR instruction for 8 bit value.
247   \param [in]    ptr  Pointer to data
248   \return             value of type uint8_t at (*ptr)
249  */
250 #define __LDREXB        (uint8_t)__builtin_arm_ldrex
251
252
253 /**
254   \brief   LDR Exclusive (16 bit)
255   \details Executes a exclusive LDR instruction for 16 bit values.
256   \param [in]    ptr  Pointer to data
257   \return        value of type uint16_t at (*ptr)
258  */
259 #define __LDREXH        (uint16_t)__builtin_arm_ldrex
260
261 /**
262   \brief   LDR Exclusive (32 bit)
263   \details Executes a exclusive LDR instruction for 32 bit values.
264   \param [in]    ptr  Pointer to data
265   \return        value of type uint32_t at (*ptr)
266  */
267 #define __LDREXW        (uint32_t)__builtin_arm_ldrex
268
269 /**
270   \brief   STR Exclusive (8 bit)
271   \details Executes a exclusive STR instruction for 8 bit values.
272   \param [in]  value  Value to store
273   \param [in]    ptr  Pointer to location
274   \return          0  Function succeeded
275   \return          1  Function failed
276  */
277 #define __STREXB        (uint32_t)__builtin_arm_strex
278
279 /**
280   \brief   STR Exclusive (16 bit)
281   \details Executes a exclusive STR instruction for 16 bit values.
282   \param [in]  value  Value to store
283   \param [in]    ptr  Pointer to location
284   \return          0  Function succeeded
285   \return          1  Function failed
286  */
287 #define __STREXH        (uint32_t)__builtin_arm_strex
288
289 /**
290   \brief   STR Exclusive (32 bit)
291   \details Executes a exclusive STR instruction for 32 bit values.
292   \param [in]  value  Value to store
293   \param [in]    ptr  Pointer to location
294   \return          0  Function succeeded
295   \return          1  Function failed
296  */
297 #define __STREXW        (uint32_t)__builtin_arm_strex
298
299 /**
300   \brief   Remove the exclusive lock
301   \details Removes the exclusive lock which is created by LDREX.
302  */
303 #define __CLREX             __builtin_arm_clrex
304
305 /** \brief  Get CPSR Register
306     \return               CPSR Register value
307  */
308 __STATIC_INLINE uint32_t __get_CPSR(void)
309 {
310   uint32_t result;
311   __ASM volatile("MRS %0, cpsr" : "=r" (result) );
312   return(result);
313 }
314
315 /** \brief  Set CPSR Register
316     \param [in]    cpsr  CPSR value to set
317  */
318 __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
319 {
320 __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
321 }
322
323 /** \brief  Get Mode
324     \return                Processor Mode
325  */
326 __STATIC_INLINE uint32_t __get_mode(void) {
327         return (__get_CPSR() & 0x1FU);
328 }
329
330 /** \brief  Set Mode
331     \param [in]    mode  Mode value to set
332  */
333 __STATIC_INLINE void __set_mode(uint32_t mode) {
334   __ASM volatile("MSR  cpsr_c, %0" : : "r" (mode) : "memory");
335 }
336
337 /** \brief  Set Stack Pointer
338     \param [in]    stack  Stack Pointer value to set
339  */
340 __STATIC_INLINE void __set_SP(uint32_t stack)
341 {
342   __ASM volatile("MOV  sp, %0" : : "r" (stack) : "memory");
343 }
344
345 /** \brief  Set USR/SYS Stack Pointer
346     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
347  */
348 __STATIC_INLINE void __set_SP_usr(uint32_t topOfProcStack)
349 {
350   __ASM volatile(
351     ".preserve8         \n"
352     "BIC     r0, r0, #7 \n" // ensure stack is 8-byte aligned
353     "MRS     r1, cpsr   \n"
354     "CPS     #0x1F      \n" // no effect in USR mode
355     "MOV     sp, r0     \n"
356     "MSR     cpsr_c, r1 \n" // no effect in USR mode
357     "ISB"
358    );
359 }
360
361 /** \brief  Get FPEXC
362     \return               Floating Point Exception Control register value
363  */
364 __STATIC_INLINE uint32_t __get_FPEXC(void)
365 {
366 #if (__FPU_PRESENT == 1)
367   uint32_t result;
368   __ASM volatile("MRS %0, fpexc" : "=r" (result) );
369   return(result);
370 #else
371   return(0);
372 #endif
373 }
374
375 /** \brief  Set FPEXC
376     \param [in]    fpexc  Floating Point Exception Control value to set
377  */
378 __STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
379 {
380 #if (__FPU_PRESENT == 1)
381   __ASM volatile ("MSR fpexc, %0" : : "r" (fpexc) : "memory");
382 #endif
383 }
384
385 /** \brief  Get ACTLR
386     \return               Auxiliary Control register value
387  */
388 __STATIC_INLINE uint32_t __get_ACTLR(void)
389 {
390   uint32_t result;
391   __ASM volatile("MRS %0, actlr" : "=r" (result) );
392   return(result);
393 }
394
395 /** \brief  Set ACTLR
396     \param [in]    actlr  Auxiliary Control value to set
397  */
398 __STATIC_INLINE void __set_ACTLR(uint32_t actlr)
399 {
400   __ASM volatile ("MSR fpexc, %0" : : "r" (actlr) : "memory");
401 }
402 /** \brief  Get CPACR
403     \return               Coprocessor Access Control register value
404  */
405 __STATIC_INLINE uint32_t __get_CPACR(void)
406 {
407   uint32_t result;
408   __ASM volatile("MRC p15, 0, %0, c1, c0, 2" : "=r"(result));
409   return result;
410 }
411
412 /** \brief  Set CPACR
413     \param [in]    cpacr  Coprocessor Access Control value to set
414  */
415 __STATIC_INLINE void __set_CPACR(uint32_t cpacr)
416 {
417   __ASM volatile("MCR p15, 0, %0, c1, c0, 2" : : "r"(cpacr) : "memory");
418 }
419
420 /** \brief  Get DFSR
421     \return               Data Fault Status Register value
422  */
423 __STATIC_INLINE uint32_t __get_DFSR(void)
424 {
425   uint32_t result;
426   __ASM volatile("MRC p15, 0, %0, c5, c0, 0" : "=r"(result));
427   return result;
428 }
429
430 /** \brief  Set DFSR
431     \param [in]    dfsr  Data Fault Status value to set
432  */
433 __STATIC_INLINE void __set_DFSR(uint32_t dfsr)
434 {
435   __ASM volatile("MCR p15, 0, %0, c5, c0, 0" : : "r"(dfsr) : "memory");
436 }
437
438 /** \brief  Get IFSR
439     \return               Instruction Fault Status Register value
440  */
441 __STATIC_INLINE uint32_t __get_IFSR(void)
442 {
443   uint32_t result;
444   __ASM volatile("MRC p15, 0, %0, c5, c0, 1" : "=r"(result));
445   return result;
446 }
447
448 /** \brief  Set IFSR
449     \param [in]    ifsr  Instruction Fault Status value to set
450  */
451 __STATIC_INLINE void __set_IFSR(uint32_t ifsr)
452 {
453   __ASM volatile("MCR p15, 0, %0, c5, c0, 1" : : "r"(ifsr) : "memory");
454 }
455
456 /** \brief  Get ISR
457     \return               Interrupt Status Register value
458  */
459 __STATIC_INLINE uint32_t __get_ISR(void)
460 {
461   uint32_t result;
462   __ASM volatile("MRC p15, 0, %0, c12, c1, 0" : "=r"(result));
463   return result;
464 }
465
466 /** \brief  Get CBAR
467     \return               Configuration Base Address register value
468  */
469 __STATIC_INLINE uint32_t __get_CBAR() {
470   uint32_t result;
471   __ASM volatile("MRC p15, 4, %0, c15, c0, 0" : "=r"(result));
472   return result;
473 }
474
475 /** \brief  Get TTBR0
476
477     This function returns the value of the Translation Table Base Register 0.
478
479     \return               Translation Table Base Register 0 value
480  */
481 __STATIC_INLINE uint32_t __get_TTBR0() {
482   uint32_t result;
483   __ASM volatile("MRC p15, 0, %0, c2, c0, 0" : "=r"(result));
484   return result;
485 }
486
487 /** \brief  Set TTBR0
488
489     This function assigns the given value to the Translation Table Base Register 0.
490
491     \param [in]    ttbr0  Translation Table Base Register 0 value to set
492  */
493 __STATIC_INLINE void __set_TTBR0(uint32_t ttbr0) {
494   __ASM volatile("MCR p15, 0, %0, c2, c0, 0" : : "r"(ttbr0) : "memory");
495 }
496
497 /** \brief  Get DACR
498
499     This function returns the value of the Domain Access Control Register.
500
501     \return               Domain Access Control Register value
502  */
503 __STATIC_INLINE uint32_t __get_DACR() {
504   uint32_t result;
505   __ASM volatile("MRC p15, 0, %0, c3, c0, 0" : "=r"(result));
506   return result;
507 }
508
509 /** \brief  Set DACR
510
511     This function assigns the given value to the Domain Access Control Register.
512
513     \param [in]    dacr   Domain Access Control Register value to set
514  */
515 __STATIC_INLINE void __set_DACR(uint32_t dacr) {
516   __ASM volatile("MCR p15, 0, %0, c3, c0, 0" : : "r"(dacr) : "memory");
517 }
518
519 /** \brief  Set SCTLR
520
521     This function assigns the given value to the System Control Register.
522
523     \param [in]    sctlr  System Control Register value to set
524  */
525 __STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
526 {
527   __ASM volatile("MCR p15, 0, %0, c1, c0, 0" : : "r"(sctlr) : "memory");
528 }
529
530 /** \brief  Get SCTLR
531     \return               System Control Register value
532  */
533 __STATIC_INLINE uint32_t __get_SCTLR() {
534   uint32_t result;
535   __ASM volatile("MRC p15, 0, %0, c1, c0, 0" : "=r"(result));
536   return result;
537 }
538
539 /** \brief  Set ACTRL
540     \param [in]    actrl  Auxiliary Control Register value to set
541  */
542 __STATIC_INLINE void __set_ACTRL(uint32_t actrl)
543 {
544   __ASM volatile("MCR p15, 0, %0, c1, c0, 1" : : "r"(actrl) : "memory");
545 }
546
547 /** \brief  Get ACTRL
548     \return               Auxiliary Control Register value
549  */
550 __STATIC_INLINE uint32_t __get_ACTRL(void)
551 {
552   uint32_t result;
553   __ASM volatile("MRC p15, 0, %0, c1, c0, 1" : "=r"(result));
554   return result;
555 }
556
557 /** \brief  Get MPIDR
558
559     This function returns the value of the Multiprocessor Affinity Register.
560
561     \return               Multiprocessor Affinity Register value
562  */
563 __STATIC_INLINE uint32_t __get_MPIDR(void)
564 {
565   uint32_t result;
566   __ASM volatile("MRC p15, 0, %0, c0, c0, 5" : "=r"(result));
567   return result;
568 }
569
570  /** \brief  Get VBAR
571
572     This function returns the value of the Vector Base Address Register.
573
574     \return               Vector Base Address Register
575  */
576 __STATIC_INLINE uint32_t __get_VBAR(void)
577 {
578   uint32_t result;
579   __ASM volatile("MRC p15, 0, %0, c12, c0, 0" : "=r"(result));
580   return result;
581 }
582
583 /** \brief  Set VBAR
584
585     This function assigns the given value to the Vector Base Address Register.
586
587     \param [in]    vbar  Vector Base Address Register value to set
588  */
589 __STATIC_INLINE void __set_VBAR(uint32_t vbar)
590 {
591   __ASM volatile("MCR p15, 0, %0, c12, c0, 1" : : "r"(vbar) : "memory");
592 }
593
594 /** \brief  Set CNTFRQ
595
596   This function assigns the given value to PL1 Physical Timer Counter Frequency Register (CNTFRQ).
597
598   \param [in]    value  CNTFRQ Register value to set
599 */
600 __STATIC_INLINE void __set_CNTFRQ(uint32_t value) {
601   __ASM volatile("MCR p15, 0, %0, c14, c0, 0" : : "r"(value) : "memory");
602 }
603
604 /** \brief  Set CNTP_TVAL
605
606   This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL).
607
608   \param [in]    value  CNTP_TVAL Register value to set
609 */
610 __STATIC_INLINE void __set_CNTP_TVAL(uint32_t value) {
611   __ASM volatile("MCR p15, 0, %0, c14, c2, 0" : : "r"(value) : "memory");
612 }
613
614 /** \brief  Get CNTP_TVAL
615
616     This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL).
617
618     \return               CNTP_TVAL Register value
619  */
620 __STATIC_INLINE uint32_t __get_CNTP_TVAL() {
621   uint32_t result;
622   __ASM volatile("MRC p15, 0, %0, c14, c2, 0" : "=r"(result));
623   return result;
624 }
625
626 /** \brief  Set CNTP_CTL
627
628   This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL).
629
630   \param [in]    value  CNTP_CTL Register value to set
631 */
632 __STATIC_INLINE void __set_CNTP_CTL(uint32_t value) {
633   __ASM volatile("MCR p15, 0, %0, c14, c2, 1" : : "r"(value) : "memory");
634 }
635
636 /** \brief  Get CNTP_CTL register
637     \return               CNTP_CTL Register value
638  */
639 __STATIC_INLINE uint32_t __get_CNTP_CTL() {
640   uint32_t result;
641   __ASM volatile("MRC p15, 0, %0, c14, c2, 1" : "=r"(result));
642   return result;
643 }
644
645 /** \brief  Set TLBIALL
646
647   TLB Invalidate All
648  */
649 __STATIC_INLINE void __set_TLBIALL(uint32_t value) {
650   __ASM volatile("MCR p15, 0, %0, c8, c7, 0" : : "r"(value) : "memory");
651 }
652
653 /** \brief  Set BPIALL.
654
655   Branch Predictor Invalidate All
656  */
657 __STATIC_INLINE void __set_BPIALL(uint32_t value) {
658   __ASM volatile("MCR p15, 0, %0, c7, c5, 6" : : "r"(value) : "memory");
659 }
660
661 /** \brief  Set ICIALLU
662
663   Instruction Cache Invalidate All
664  */
665 __STATIC_INLINE void __set_ICIALLU(uint32_t value) {
666   __ASM volatile("MCR p15, 0, %0, c7, c5, 0" : : "r"(value) : "memory");
667 }
668
669 /** \brief  Set DCCMVAC
670
671   Data cache clean
672  */
673 __STATIC_INLINE void __set_DCCMVAC(uint32_t value) {
674   __ASM volatile("MCR p15, 0, %0, c7, c10, 1" : : "r"(value) : "memory");
675 }
676
677 /** \brief  Set DCIMVAC
678
679   Data cache invalidate
680  */
681 __STATIC_INLINE void __set_DCIMVAC(uint32_t value) {
682   __ASM volatile("MCR p15, 0, %0, c7, c6, 1" : : "r"(value) : "memory");
683 }
684
685 /** \brief  Set DCCIMVAC
686
687   Data cache clean and invalidate
688  */
689 __STATIC_INLINE void __set_DCCIMVAC(uint32_t value) {
690   __ASM volatile("MCR p15, 0, %0, c7, c14, 1" : : "r"(value) : "memory");
691 }
692
693 /** \brief  Clean and Invalidate the entire data or unified cache
694
695   Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
696  */
697 __STATIC_INLINE void __L1C_CleanInvalidateCache(uint32_t op) {
698   __ASM volatile(
699     "        PUSH    {R4-R11}                   \n"
700
701     "        MRC     p15, 1, R6, c0, c0, 1      \n" // Read CLIDR
702     "        ANDS    R3, R6, #0x07000000        \n" // Extract coherency level
703     "        MOV     R3, R3, LSR #23            \n" // Total cache levels << 1
704     "        BEQ     Finished                   \n" // If 0, no need to clean
705
706     "        MOV     R10, #0                    \n" // R10 holds current cache level << 1
707     "Loop1:  ADD     R2, R10, R10, LSR #1       \n" // R2 holds cache "Set" position
708     "        MOV     R1, R6, LSR R2             \n" // Bottom 3 bits are the Cache-type for this level
709     "        AND     R1, R1, #7                 \n" // Isolate those lower 3 bits
710     "        CMP     R1, #2                     \n"
711     "        BLT     Skip                       \n" // No cache or only instruction cache at this level
712
713     "        MCR     p15, 2, R10, c0, c0, 0     \n" // Write the Cache Size selection register
714     "        ISB                                \n" // ISB to sync the change to the CacheSizeID reg
715     "        MRC     p15, 1, R1, c0, c0, 0      \n" // Reads current Cache Size ID register
716     "        AND     R2, R1, #7                 \n" // Extract the line length field
717     "        ADD     R2, R2, #4                 \n" // Add 4 for the line length offset (log2 16 bytes)
718     "        LDR     R4, =0x3FF                 \n"
719     "        ANDS    R4, R4, R1, LSR #3         \n" // R4 is the max number on the way size (right aligned)
720     "        CLZ     R5, R4                     \n" // R5 is the bit position of the way size increment
721     "        LDR     R7, =0x7FFF                \n"
722     "        ANDS    R7, R7, R1, LSR #13        \n" // R7 is the max number of the index size (right aligned)
723
724     "Loop2:  MOV     R9, R4                     \n" // R9 working copy of the max way size (right aligned)
725
726     "Loop3:  ORR     R11, R10, R9, LSL R5       \n" // Factor in the Way number and cache number into R11
727     "        ORR     R11, R11, R7, LSL R2       \n" // Factor in the Set number
728     "        CMP     R0, #0                     \n"
729     "        BNE     Dccsw                      \n"
730     "        MCR     p15, 0, R11, c7, c6, 2     \n" // DCISW. Invalidate by Set/Way
731     "        B       cont                       \n"
732     "Dccsw:  CMP     R0, #1                     \n"
733     "        BNE     Dccisw                     \n"
734     "        MCR     p15, 0, R11, c7, c10, 2    \n" // DCCSW. Clean by Set/Way
735     "        B       cont                       \n"
736     "Dccisw: MCR     p15, 0, R11, c7, c14, 2    \n" // DCCISW. Clean and Invalidate by Set/Way
737     "cont:   SUBS    R9, R9, #1                 \n" // Decrement the Way number
738     "        BGE     Loop3                      \n"
739     "        SUBS    R7, R7, #1                 \n" // Decrement the Set number
740     "        BGE     Loop2                      \n"
741     "Skip:   ADD     R10, R10, #2               \n" // Increment the cache number
742     "        CMP     R3, R10                    \n"
743     "        BGT     Loop1                      \n"
744
745     "Finished:                                  \n"
746     "        DSB                                \n"
747     "        POP    {R4-R11}                      "
748   );
749 }
750
751 /** \brief  Enable Floating Point Unit
752
753   Critical section, called from undef handler, so systick is disabled
754  */
755 __STATIC_INLINE void __FPU_Enable(void) {
756   __ASM volatile(
757             //Permit access to VFP/NEON, registers by modifying CPACR
758     "        MRC     p15,0,R1,c1,c0,2  \n"
759     "        ORR     R1,R1,#0x00F00000 \n"
760     "        MCR     p15,0,R1,c1,c0,2  \n"
761
762             //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
763     "        ISB                       \n"
764
765             //Enable VFP/NEON
766     "        VMRS    R1,FPEXC          \n"
767     "        ORR     R1,R1,#0x40000000 \n"
768     "        VMSR    FPEXC,R1          \n"
769
770             //Initialise VFP/NEON registers to 0
771     "        MOV     R2,#0             \n"
772 #if 0 // TODO: Initialize FPU registers according to available register count
773     ".if {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} >= 16 \n"
774             //Initialise D16 registers to 0
775     "        VMOV    D0, R2,R2         \n"
776     "        VMOV    D1, R2,R2         \n"
777     "        VMOV    D2, R2,R2         \n"
778     "        VMOV    D3, R2,R2         \n"
779     "        VMOV    D4, R2,R2         \n"
780     "        VMOV    D5, R2,R2         \n"
781     "        VMOV    D6, R2,R2         \n"
782     "        VMOV    D7, R2,R2         \n"
783     "        VMOV    D8, R2,R2         \n"
784     "        VMOV    D9, R2,R2         \n"
785     "        VMOV    D10,R2,R2         \n"
786     "        VMOV    D11,R2,R2         \n"
787     "        VMOV    D12,R2,R2         \n"
788     "        VMOV    D13,R2,R2         \n"
789     "        VMOV    D14,R2,R2         \n"
790     "        VMOV    D15,R2,R2         \n"
791     ".endif                            \n"
792
793     ".if {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32 \n"
794             //Initialise D32 registers to 0
795     "        VMOV    D16,R2,R2         \n"
796     "        VMOV    D17,R2,R2         \n"
797     "        VMOV    D18,R2,R2         \n"
798     "        VMOV    D19,R2,R2         \n"
799     "        VMOV    D20,R2,R2         \n"
800     "        VMOV    D21,R2,R2         \n"
801     "        VMOV    D22,R2,R2         \n"
802     "        VMOV    D23,R2,R2         \n"
803     "        VMOV    D24,R2,R2         \n"
804     "        VMOV    D25,R2,R2         \n"
805     "        VMOV    D26,R2,R2         \n"
806     "        VMOV    D27,R2,R2         \n"
807     "        VMOV    D28,R2,R2         \n"
808     "        VMOV    D29,R2,R2         \n"
809     "        VMOV    D30,R2,R2         \n"
810     "        VMOV    D31,R2,R2         \n"
811     ".endif                            \n"
812 #endif
813             //Initialise FPSCR to a known state
814     "        VMRS    R2,FPSCR          \n"
815     "        LDR     R3,=0x00086060    \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
816     "        AND     R2,R2,R3          \n"
817     "        VMSR    FPSCR,R2            "
818   );
819 }
820
821 #endif /* __CMSIS_ARMCC_H */