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