]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_armcc.h
CMSIS-Core(A): Enhanced documentation for cache access maintenance.
[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 register
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 register
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 register
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 register
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 register
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 register
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 register
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 register
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 register
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 register
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 register
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 the \ref CMSIS_SCTLR "System Control Register" register.
482     \param [in]    sctlr  System Control Register value to set
483  */
484 __STATIC_INLINE void __set_SCTLR(uint32_t sctlr)
485 {
486   register uint32_t __regSCTLR         __ASM("cp15:0:c1:c0:0");
487   __regSCTLR = sctlr;
488 }
489
490 /** \brief  Get SCTLR register
491     \return               System Control Register value
492  */
493 __STATIC_INLINE uint32_t __get_SCTLR() {
494   register uint32_t __regSCTLR         __ASM("cp15:0:c1:c0:0");
495   return(__regSCTLR);
496 }
497
498 /** \brief  Set ACTRL register
499     \param [in]    actrl  Auxiliary Control Register value to set
500  */
501 __STATIC_INLINE void __set_ACTRL(uint32_t actrl)
502 {
503   register uint32_t __regACTRL         __ASM("cp15:0:c1:c0:1");
504   __regACTRL = actrl;
505 }
506
507 /** \brief  Get ACTRL register
508     \return               Auxiliary Control Register value
509  */
510 __STATIC_INLINE uint32_t __get_ACTRL(void)
511 {
512   register uint32_t __regACTRL         __ASM("cp15:0:c1:c0:1");
513   return(__regACTRL);
514 }
515
516 /** \brief  Get MPIDR register
517     \return               Multiprocessor Affinity Register value
518  */
519 __STATIC_INLINE uint32_t __get_MPIDR(void)
520 {
521   register uint32_t __regMPIDR         __ASM("cp15:0:c0:c0:5");
522   return(__regMPIDR);
523 }
524
525  /** \brief  Get VBAR register
526     \return               Vector Base Address Register
527  */
528 __STATIC_INLINE uint32_t __get_VBAR(void)
529 {
530   register uint32_t __regVBAR         __ASM("cp15:0:c12:c0:0");
531   return(__regVBAR);
532 }
533
534 /** \brief  Set VBAR register
535     \param [in]    vbar  Vector Base Address Register value to set
536  */
537 __STATIC_INLINE void __set_VBAR(uint32_t vbar)
538 {
539   register uint32_t __regVBAR          __ASM("cp15:0:c12:c0:0");
540   __regVBAR = vbar;
541 }
542
543 /** \brief  Set CNTFRQ register
544   \param [in]    value  CNTFRQ Register value to set
545 */
546 __STATIC_INLINE void __set_CNTFRQ(uint32_t value) {
547   register uint32_t __regCNTFRQ         __ASM("cp15:0:c14:c0:0");
548   __regCNTFRQ = value;
549 }
550
551 /** \brief  Set CNTP_TVAL register
552   \param [in]    value  CNTP_TVAL Register value to set
553 */
554 __STATIC_INLINE void __set_CNTP_TVAL(uint32_t value) {
555   register uint32_t __regCNTP_TVAL         __ASM("cp15:0:c14:c2:0");
556   __regCNTP_TVAL = value;
557 }
558
559 /** \brief  Get CNTP_TVAL register
560     \return               CNTP_TVAL Register value
561  */
562 __STATIC_INLINE uint32_t __get_CNTP_TVAL() {
563   register uint32_t __regCNTP_TVAL         __ASM("cp15:0:c14:c2:0");
564   return(__regCNTP_TVAL);
565 }
566
567 /** \brief  Set CNTP_CTL register
568   \param [in]    value  CNTP_CTL Register value to set
569 */
570 __STATIC_INLINE void __set_CNTP_CTL(uint32_t value) {
571   register uint32_t __regCNTP_CTL          __ASM("cp15:0:c14:c2:1");
572   __regCNTP_CTL = value;
573 }
574
575 /** \brief  Set TLBIALL register
576  */
577 __STATIC_INLINE void __set_TLBIALL(uint32_t value) {
578   register uint32_t __TLBIALL              __ASM("cp15:0:c8:c7:0");
579   __TLBIALL = value;
580 }
581
582 /** \brief  Set Branch Predictor Invalidate All register.
583 * \param [in] value New register value to be set.
584 */
585 __STATIC_INLINE void __set_BPIALL(uint32_t value) {
586   register uint32_t __BPIALL            __ASM("cp15:0:c7:c5:6");
587   __BPIALL = value;
588 }
589
590 /** \brief  Set ICIALLU register
591  */
592 __STATIC_INLINE void __set_ICIALLU(uint32_t value) {
593   register uint32_t __ICIALLU         __ASM("cp15:0:c7:c5:0");
594   __ICIALLU = value;
595 }
596
597 /** \brief  Set DCCMVAC register
598  */
599 __STATIC_INLINE void __set_DCCMVAC(uint32_t value) {
600   register uint32_t __DCCMVAC         __ASM("cp15:0:c7:c10:1");
601   __DCCMVAC = value;
602 }
603
604 /** \brief  Set DCIMVAC register
605  */
606 __STATIC_INLINE void __set_DCIMVAC(uint32_t value) {
607   register uint32_t __DCIMVAC         __ASM("cp15:0:c7:c6:1");
608   __DCIMVAC = value;
609 }
610
611 /** \brief  Set DCCIMVAC register
612  */
613 __STATIC_INLINE void __set_DCCIMVAC(uint32_t value) {
614   register uint32_t __DCCIMVAC        __ASM("cp15:0:c7:c14:1");
615   __DCCIMVAC = value;
616 }
617
618 /** \brief  Clean and Invalidate the entire data or unified cache
619  * \param op 0 - invalidate, 1 - clean, otherwise - invalidate and clean
620  */
621 __STATIC_INLINE __ASM void __L1C_CleanInvalidateCache(uint32_t op) {
622         ARM
623
624         PUSH    {R4-R11}
625
626         MRC     p15, 1, R6, c0, c0, 1      // Read CLIDR
627         ANDS    R3, R6, #0x07000000        // Extract coherency level
628         MOV     R3, R3, LSR #23            // Total cache levels << 1
629         BEQ     Finished                   // If 0, no need to clean
630
631         MOV     R10, #0                    // R10 holds current cache level << 1
632 Loop1   ADD     R2, R10, R10, LSR #1       // R2 holds cache "Set" position
633         MOV     R1, R6, LSR R2             // Bottom 3 bits are the Cache-type for this level
634         AND     R1, R1, #7                 // Isolate those lower 3 bits
635         CMP     R1, #2
636         BLT     Skip                       // No cache or only instruction cache at this level
637
638         MCR     p15, 2, R10, c0, c0, 0     // Write the Cache Size selection register
639         ISB                                // ISB to sync the change to the CacheSizeID reg
640         MRC     p15, 1, R1, c0, c0, 0      // Reads current Cache Size ID register
641         AND     R2, R1, #7                 // Extract the line length field
642         ADD     R2, R2, #4                 // Add 4 for the line length offset (log2 16 bytes)
643         LDR     R4, =0x3FF
644         ANDS    R4, R4, R1, LSR #3         // R4 is the max number on the way size (right aligned)
645         CLZ     R5, R4                     // R5 is the bit position of the way size increment
646         LDR     R7, =0x7FFF
647         ANDS    R7, R7, R1, LSR #13        // R7 is the max number of the index size (right aligned)
648
649 Loop2   MOV     R9, R4                     // R9 working copy of the max way size (right aligned)
650
651 Loop3   ORR     R11, R10, R9, LSL R5       // Factor in the Way number and cache number into R11
652         ORR     R11, R11, R7, LSL R2       // Factor in the Set number
653         CMP     R0, #0
654         BNE     Dccsw
655         MCR     p15, 0, R11, c7, c6, 2     // DCISW. Invalidate by Set/Way
656         B       cont
657 Dccsw   CMP     R0, #1
658         BNE     Dccisw
659         MCR     p15, 0, R11, c7, c10, 2    // DCCSW. Clean by Set/Way
660         B       cont
661 Dccisw  MCR     p15, 0, R11, c7, c14, 2    // DCCISW. Clean and Invalidate by Set/Way
662 cont    SUBS    R9, R9, #1                 // Decrement the Way number
663         BGE     Loop3
664         SUBS    R7, R7, #1                 // Decrement the Set number
665         BGE     Loop2
666 Skip    ADD     R10, R10, #2               // Increment the cache number
667         CMP     R3, R10
668         BGT     Loop1
669
670 Finished
671         DSB
672         POP    {R4-R11}
673         BX     lr
674 }
675
676 /** \brief  Enable Floating Point Unit
677
678   Critical section, called from undef handler, so systick is disabled
679  */
680 __STATIC_INLINE __ASM void __FPU_Enable(void) {
681         ARM
682
683         //Permit access to VFP/NEON, registers by modifying CPACR
684         MRC     p15,0,R1,c1,c0,2
685         ORR     R1,R1,#0x00F00000
686         MCR     p15,0,R1,c1,c0,2
687
688         //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
689         ISB
690
691         //Enable VFP/NEON
692         VMRS    R1,FPEXC
693         ORR     R1,R1,#0x40000000
694         VMSR    FPEXC,R1
695
696         //Initialise VFP/NEON registers to 0
697         MOV     R2,#0
698   IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} >= 16
699         //Initialise D16 registers to 0
700         VMOV    D0, R2,R2
701         VMOV    D1, R2,R2
702         VMOV    D2, R2,R2
703         VMOV    D3, R2,R2
704         VMOV    D4, R2,R2
705         VMOV    D5, R2,R2
706         VMOV    D6, R2,R2
707         VMOV    D7, R2,R2
708         VMOV    D8, R2,R2
709         VMOV    D9, R2,R2
710         VMOV    D10,R2,R2
711         VMOV    D11,R2,R2
712         VMOV    D12,R2,R2
713         VMOV    D13,R2,R2
714         VMOV    D14,R2,R2
715         VMOV    D15,R2,R2
716   ENDIF
717   IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32
718         //Initialise D32 registers to 0
719         VMOV    D16,R2,R2
720         VMOV    D17,R2,R2
721         VMOV    D18,R2,R2
722         VMOV    D19,R2,R2
723         VMOV    D20,R2,R2
724         VMOV    D21,R2,R2
725         VMOV    D22,R2,R2
726         VMOV    D23,R2,R2
727         VMOV    D24,R2,R2
728         VMOV    D25,R2,R2
729         VMOV    D26,R2,R2
730         VMOV    D27,R2,R2
731         VMOV    D28,R2,R2
732         VMOV    D29,R2,R2
733         VMOV    D30,R2,R2
734         VMOV    D31,R2,R2
735   ENDIF
736
737         //Initialise FPSCR to a known state
738         VMRS    R2,FPSCR
739         LDR     R3,=0x00086060 //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
740         AND     R2,R2,R3
741         VMSR    FPSCR,R2
742
743         BX      LR
744 }
745
746 #endif /* __CMSIS_ARMCC_H */