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