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