]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_armcc.h
Doxygen:
[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 CNTFRQ
556
557   This function assigns the given value to PL1 Physical Timer Counter Frequency Register (CNTFRQ).
558
559   \param [in]    value  CNTFRQ Register value to set
560 */
561 __STATIC_INLINE void __set_CNTFRQ(uint32_t value) {
562   register uint32_t __regCNTFRQ         __ASM("cp15:0:c14:c0:0");
563   __regCNTFRQ = value;
564 }
565
566 /** \brief  Set CNTP_TVAL
567
568   This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL).
569
570   \param [in]    value  CNTP_TVAL Register value to set
571 */
572 __STATIC_INLINE void __set_CNTP_TVAL(uint32_t value) {
573   register uint32_t __regCNTP_TVAL         __ASM("cp15:0:c14:c2:0");
574   __regCNTP_TVAL = value;
575 }
576
577 /** \brief  Get CNTP_TVAL
578
579     This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL).
580
581     \return               CNTP_TVAL Register value
582  */
583 __STATIC_INLINE uint32_t __get_CNTP_TVAL() {
584   register uint32_t __regCNTP_TVAL         __ASM("cp15:0:c14:c2:0");
585   return(__regCNTP_TVAL);
586 }
587
588 /** \brief  Set CNTP_CTL
589
590   This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL).
591
592   \param [in]    value  CNTP_CTL Register value to set
593 */
594 __STATIC_INLINE void __set_CNTP_CTL(uint32_t value) {
595   register uint32_t __regCNTP_CTL          __ASM("cp15:0:c14:c2:1");
596   __regCNTP_CTL = value;
597 }
598
599 /** \brief  Set TLBIALL
600
601   TLB Invalidate All
602  */
603 __STATIC_INLINE void __set_TLBIALL(uint32_t value) {
604   register uint32_t __TLBIALL              __ASM("cp15:0:c8:c7:0");
605   __TLBIALL = value;
606 }
607
608 /** \brief  Set BPIALL.
609
610   Branch Predictor Invalidate All
611  */
612 __STATIC_INLINE void __set_BPIALL(uint32_t value) {
613   register uint32_t __BPIALL            __ASM("cp15:0:c7:c5:6");
614   __BPIALL = value;
615 }
616
617 /** \brief  Set ICIALLU
618
619   Instruction Cache Invalidate All
620  */
621 __STATIC_INLINE void __set_ICIALLU(uint32_t value) {
622   register uint32_t __ICIALLU         __ASM("cp15:0:c7:c5:0");
623   __ICIALLU = value;
624 }
625
626 /** \brief  Set DCCMVAC
627
628   Data cache clean
629  */
630 __STATIC_INLINE void __set_DCCMVAC(uint32_t value) {
631   register uint32_t __DCCMVAC         __ASM("cp15:0:c7:c10:1");
632   __DCCMVAC = value;
633 }
634
635 /** \brief  Set DCIMVAC
636
637   Data cache invalidate
638  */
639 __STATIC_INLINE void __set_DCIMVAC(uint32_t value) {
640   register uint32_t __DCIMVAC         __ASM("cp15:0:c7:c6:1");
641   __DCIMVAC = value;
642 }
643
644 /** \brief  Set DCCIMVAC
645
646   Data cache clean and invalidate
647  */
648 __STATIC_INLINE void __set_DCCIMVAC(uint32_t value) {
649   register uint32_t __DCCIMVAC        __ASM("cp15:0:c7:c14:1");
650   __DCCIMVAC = value;
651 }
652
653 /** \brief  Clean and Invalidate the entire data or unified cache
654
655   Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
656  */
657 __STATIC_INLINE __ASM void __L1C_CleanInvalidateCache(uint32_t op) {
658         ARM
659
660         PUSH    {R4-R11}
661
662         MRC     p15, 1, R6, c0, c0, 1      // Read CLIDR
663         ANDS    R3, R6, #0x07000000        // Extract coherency level
664         MOV     R3, R3, LSR #23            // Total cache levels << 1
665         BEQ     Finished                   // If 0, no need to clean
666
667         MOV     R10, #0                    // R10 holds current cache level << 1
668 Loop1   ADD     R2, R10, R10, LSR #1       // R2 holds cache "Set" position
669         MOV     R1, R6, LSR R2             // Bottom 3 bits are the Cache-type for this level
670         AND     R1, R1, #7                 // Isolate those lower 3 bits
671         CMP     R1, #2
672         BLT     Skip                       // No cache or only instruction cache at this level
673
674         MCR     p15, 2, R10, c0, c0, 0     // Write the Cache Size selection register
675         ISB                                // ISB to sync the change to the CacheSizeID reg
676         MRC     p15, 1, R1, c0, c0, 0      // Reads current Cache Size ID register
677         AND     R2, R1, #7                 // Extract the line length field
678         ADD     R2, R2, #4                 // Add 4 for the line length offset (log2 16 bytes)
679         LDR     R4, =0x3FF
680         ANDS    R4, R4, R1, LSR #3         // R4 is the max number on the way size (right aligned)
681         CLZ     R5, R4                     // R5 is the bit position of the way size increment
682         LDR     R7, =0x7FFF
683         ANDS    R7, R7, R1, LSR #13        // R7 is the max number of the index size (right aligned)
684
685 Loop2   MOV     R9, R4                     // R9 working copy of the max way size (right aligned)
686
687 Loop3   ORR     R11, R10, R9, LSL R5       // Factor in the Way number and cache number into R11
688         ORR     R11, R11, R7, LSL R2       // Factor in the Set number
689         CMP     R0, #0
690         BNE     Dccsw
691         MCR     p15, 0, R11, c7, c6, 2     // DCISW. Invalidate by Set/Way
692         B       cont
693 Dccsw   CMP     R0, #1
694         BNE     Dccisw
695         MCR     p15, 0, R11, c7, c10, 2    // DCCSW. Clean by Set/Way
696         B       cont
697 Dccisw  MCR     p15, 0, R11, c7, c14, 2    // DCCISW. Clean and Invalidate by Set/Way
698 cont    SUBS    R9, R9, #1                 // Decrement the Way number
699         BGE     Loop3
700         SUBS    R7, R7, #1                 // Decrement the Set number
701         BGE     Loop2
702 Skip    ADD     R10, R10, #2               // Increment the cache number
703         CMP     R3, R10
704         BGT     Loop1
705
706 Finished
707         DSB
708         POP    {R4-R11}
709         BX     lr
710 }
711
712 /** \brief  Enable Floating Point Unit
713
714   Critical section, called from undef handler, so systick is disabled
715  */
716 __STATIC_INLINE __ASM void __FPU_Enable(void) {
717         ARM
718
719         //Permit access to VFP/NEON, registers by modifying CPACR
720         MRC     p15,0,R1,c1,c0,2
721         ORR     R1,R1,#0x00F00000
722         MCR     p15,0,R1,c1,c0,2
723
724         //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
725         ISB
726
727         //Enable VFP/NEON
728         VMRS    R1,FPEXC
729         ORR     R1,R1,#0x40000000
730         VMSR    FPEXC,R1
731
732         //Initialise VFP/NEON registers to 0
733         MOV     R2,#0
734   IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} >= 16
735         //Initialise D16 registers to 0
736         VMOV    D0, R2,R2
737         VMOV    D1, R2,R2
738         VMOV    D2, R2,R2
739         VMOV    D3, R2,R2
740         VMOV    D4, R2,R2
741         VMOV    D5, R2,R2
742         VMOV    D6, R2,R2
743         VMOV    D7, R2,R2
744         VMOV    D8, R2,R2
745         VMOV    D9, R2,R2
746         VMOV    D10,R2,R2
747         VMOV    D11,R2,R2
748         VMOV    D12,R2,R2
749         VMOV    D13,R2,R2
750         VMOV    D14,R2,R2
751         VMOV    D15,R2,R2
752   ENDIF
753   IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32
754         //Initialise D32 registers to 0
755         VMOV    D16,R2,R2
756         VMOV    D17,R2,R2
757         VMOV    D18,R2,R2
758         VMOV    D19,R2,R2
759         VMOV    D20,R2,R2
760         VMOV    D21,R2,R2
761         VMOV    D22,R2,R2
762         VMOV    D23,R2,R2
763         VMOV    D24,R2,R2
764         VMOV    D25,R2,R2
765         VMOV    D26,R2,R2
766         VMOV    D27,R2,R2
767         VMOV    D28,R2,R2
768         VMOV    D29,R2,R2
769         VMOV    D30,R2,R2
770         VMOV    D31,R2,R2
771   ENDIF
772
773         //Initialise FPSCR to a known state
774         VMRS    R2,FPSCR
775         LDR     R3,=0x00086060 //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
776         AND     R2,R2,R3
777         VMSR    FPSCR,R2
778
779         BX      LR
780 }
781
782 #endif /* __CMSIS_ARMCC_H */