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