]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_gcc.h
Add cmsis_iccarm.h for Core_A
[cmsis] / CMSIS / Core_A / Include / cmsis_gcc.h
1 /**************************************************************************//**
2  * @file     cmsis_gcc.h
3  * @brief    CMSIS compiler specific macros, functions, instructions
4  * @version  V1.0.1
5  * @date     07. Sep 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_GCC_H
26 #define __CMSIS_GCC_H
27
28 /* ignore some GCC warnings */
29 #pragma GCC diagnostic push
30 #pragma GCC diagnostic ignored "-Wsign-conversion"
31 #pragma GCC diagnostic ignored "-Wconversion"
32 #pragma GCC diagnostic ignored "-Wunused-parameter"
33
34 /* Fallback for __has_builtin */
35 #ifndef __has_builtin
36   #define __has_builtin(x) (0)
37 #endif
38
39 /* CMSIS compiler specific defines */
40 #ifndef   __ASM
41   #define __ASM                                  asm
42 #endif
43 #ifndef   __INLINE
44   #define __INLINE                               inline
45 #endif
46 #ifndef   __FORCEINLINE                              
47   #define __FORCEINLINE                          __attribute__((always_inline))
48 #endif                                          
49 #ifndef   __STATIC_INLINE
50   #define __STATIC_INLINE                        static inline
51 #endif
52 #ifndef   __STATIC_FORCEINLINE                 
53   #define __STATIC_FORCEINLINE                   __attribute__((always_inline)) static inline
54 #endif                                           
55 #ifndef   __NO_RETURN
56   #define __NO_RETURN                            __attribute__((noreturn))
57 #endif
58 #ifndef   __USED
59   #define __USED                                 __attribute__((used))
60 #endif
61 #ifndef   __WEAK
62   #define __WEAK                                 __attribute__((weak))
63 #endif
64 #ifndef   __PACKED
65   #define __PACKED                               __attribute__((packed, aligned(1)))
66 #endif
67 #ifndef   __PACKED_STRUCT
68   #define __PACKED_STRUCT                        struct __attribute__((packed, aligned(1)))
69 #endif
70 #ifndef   __UNALIGNED_UINT16_WRITE
71   #pragma GCC diagnostic push
72   #pragma GCC diagnostic ignored "-Wpacked"
73 /*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
74   __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
75   #pragma GCC diagnostic pop
76   #define __UNALIGNED_UINT16_WRITE(addr, val)    (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
77 #endif
78 #ifndef   __UNALIGNED_UINT16_READ
79   #pragma GCC diagnostic push
80   #pragma GCC diagnostic ignored "-Wpacked"
81 /*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
82   __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
83   #pragma GCC diagnostic pop
84   #define __UNALIGNED_UINT16_READ(addr)          (((const struct T_UINT16_READ *)(const void *)(addr))->v)
85 #endif
86 #ifndef   __UNALIGNED_UINT32_WRITE
87   #pragma GCC diagnostic push
88   #pragma GCC diagnostic ignored "-Wpacked"
89 /*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
90   __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
91   #pragma GCC diagnostic pop
92   #define __UNALIGNED_UINT32_WRITE(addr, val)    (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
93 #endif
94 #ifndef   __UNALIGNED_UINT32_READ
95   #pragma GCC diagnostic push
96   #pragma GCC diagnostic ignored "-Wpacked"
97   __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
98   #pragma GCC diagnostic pop
99   #define __UNALIGNED_UINT32_READ(addr)          (((const struct T_UINT32_READ *)(const void *)(addr))->v)
100 #endif
101 #ifndef   __ALIGNED
102   #define __ALIGNED(x)                           __attribute__((aligned(x)))
103 #endif
104
105 /* ##########################  Core Instruction Access  ######################### */
106 /**
107   \brief   No Operation
108  */
109 #define __NOP()                             __ASM volatile ("nop")
110
111 /**
112   \brief   Wait For Interrupt
113  */
114 #define __WFI()                             __ASM volatile ("wfi")
115
116 /**
117   \brief   Wait For Event
118  */
119 #define __WFE()                             __ASM volatile ("wfe")
120
121 /**
122   \brief   Send Event
123  */
124 #define __SEV()                             __ASM volatile ("sev")
125
126 /**
127   \brief   Instruction Synchronization Barrier
128   \details Instruction Synchronization Barrier flushes the pipeline in the processor,
129            so that all instructions following the ISB are fetched from cache or memory,
130            after the instruction has been completed.
131  */
132 __STATIC_FORCEINLINE  void __ISB(void)
133 {
134   __ASM volatile ("isb 0xF":::"memory");
135 }
136
137
138 /**
139   \brief   Data Synchronization Barrier
140   \details Acts as a special kind of Data Memory Barrier.
141            It completes when all explicit memory accesses before this instruction complete.
142  */
143 __STATIC_FORCEINLINE  void __DSB(void)
144 {
145   __ASM volatile ("dsb 0xF":::"memory");
146 }
147
148 /**
149   \brief   Data Memory Barrier
150   \details Ensures the apparent order of the explicit memory operations before
151            and after the instruction, without ensuring their completion.
152  */
153 __STATIC_FORCEINLINE  void __DMB(void)
154 {
155   __ASM volatile ("dmb 0xF":::"memory");
156 }
157
158 /**
159   \brief   Reverse byte order (32 bit)
160   \details Reverses the byte order in integer value.
161   \param [in]    value  Value to reverse
162   \return               Reversed value
163  */
164 __STATIC_FORCEINLINE  uint32_t __REV(uint32_t value)
165 {
166 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
167   return __builtin_bswap32(value);
168 #else
169   uint32_t result;
170
171   __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
172   return(result);
173 #endif
174 }
175
176 /**
177   \brief   Reverse byte order (16 bit)
178   \param [in]    value  Value to reverse
179   \return               Reversed value
180  */
181 #ifndef __NO_EMBEDDED_ASM
182 __attribute__((section(".rev16_text"))) __STATIC_INLINE uint32_t __REV16(uint32_t value)
183 {
184   uint32_t result;
185   __ASM volatile("rev16 %0, %1" : "=r" (result) : "r" (value));
186   return result;
187 }
188 #endif
189
190 /**
191   \brief   Reverse byte order in signed short value
192   \details Reverses the byte order in a signed short value with sign extension to integer.
193   \param [in]    value  Value to reverse
194   \return               Reversed value
195  */
196 __STATIC_FORCEINLINE  int32_t __REVSH(int32_t value)
197 {
198 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
199   return (short)__builtin_bswap16(value);
200 #else
201   int32_t result;
202
203   __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
204   return(result);
205 #endif
206 }
207
208 /**
209   \brief   Rotate Right in unsigned value (32 bit)
210   \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
211   \param [in]    op1  Value to rotate
212   \param [in]    op2  Number of Bits to rotate
213   \return               Rotated value
214  */
215 __STATIC_FORCEINLINE  uint32_t __ROR(uint32_t op1, uint32_t op2)
216 {
217   return (op1 >> op2) | (op1 << (32U - op2));
218 }
219
220 /**
221   \brief   Breakpoint
222   \param [in]    value  is ignored by the processor.
223                  If required, a debugger can use it to store additional information about the breakpoint.
224  */
225 #define __BKPT(value)                       __ASM volatile ("bkpt "#value)
226
227 /**
228   \brief   Reverse bit order of value
229   \details Reverses the bit order of the given value.
230   \param [in]    value  Value to reverse
231   \return               Reversed value
232  */
233 __STATIC_FORCEINLINE  uint32_t __RBIT(uint32_t value)
234 {
235   uint32_t result;
236
237 #if ((defined (__ARM_ARCH_7M__      ) && (__ARM_ARCH_7M__      == 1)) || \
238      (defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
239      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
240    __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
241 #else
242   int32_t s = (4 /*sizeof(v)*/ * 8) - 1; /* extra shift needed at end */
243
244   result = value;                      /* r will be reversed bits of v; first get LSB of v */
245   for (value >>= 1U; value; value >>= 1U)
246   {
247     result <<= 1U;
248     result |= value & 1U;
249     s--;
250   }
251   result <<= s;                        /* shift when v's highest bits are zero */
252 #endif
253   return(result);
254 }
255
256 /**
257   \brief   Count leading zeros
258   \param [in]  value  Value to count the leading zeros
259   \return             number of leading zeros in value
260  */
261 #define __CLZ                             __builtin_clz
262
263 /**
264   \brief   LDR Exclusive (8 bit)
265   \details Executes a exclusive LDR instruction for 8 bit value.
266   \param [in]    ptr  Pointer to data
267   \return             value of type uint8_t at (*ptr)
268  */
269 __STATIC_FORCEINLINE  uint8_t __LDREXB(volatile uint8_t *addr)
270 {
271     uint32_t result;
272
273 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
274    __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
275 #else
276     /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
277        accepted by assembler. So has to use following less efficient pattern.
278     */
279    __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
280 #endif
281    return ((uint8_t) result);    /* Add explicit type cast here */
282 }
283
284
285 /**
286   \brief   LDR Exclusive (16 bit)
287   \details Executes a exclusive LDR instruction for 16 bit values.
288   \param [in]    ptr  Pointer to data
289   \return        value of type uint16_t at (*ptr)
290  */
291 __STATIC_FORCEINLINE  uint16_t __LDREXH(volatile uint16_t *addr)
292 {
293     uint32_t result;
294
295 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
296    __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
297 #else
298     /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
299        accepted by assembler. So has to use following less efficient pattern.
300     */
301    __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
302 #endif
303    return ((uint16_t) result);    /* Add explicit type cast here */
304 }
305
306
307 /**
308   \brief   LDR Exclusive (32 bit)
309   \details Executes a exclusive LDR instruction for 32 bit values.
310   \param [in]    ptr  Pointer to data
311   \return        value of type uint32_t at (*ptr)
312  */
313 __STATIC_FORCEINLINE  uint32_t __LDREXW(volatile uint32_t *addr)
314 {
315     uint32_t result;
316
317    __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
318    return(result);
319 }
320
321
322 /**
323   \brief   STR Exclusive (8 bit)
324   \details Executes a exclusive STR instruction for 8 bit values.
325   \param [in]  value  Value to store
326   \param [in]    ptr  Pointer to location
327   \return          0  Function succeeded
328   \return          1  Function failed
329  */
330 __STATIC_FORCEINLINE  uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
331 {
332    uint32_t result;
333
334    __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
335    return(result);
336 }
337
338
339 /**
340   \brief   STR Exclusive (16 bit)
341   \details Executes a exclusive STR instruction for 16 bit values.
342   \param [in]  value  Value to store
343   \param [in]    ptr  Pointer to location
344   \return          0  Function succeeded
345   \return          1  Function failed
346  */
347 __STATIC_FORCEINLINE  uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
348 {
349    uint32_t result;
350
351    __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
352    return(result);
353 }
354
355
356 /**
357   \brief   STR Exclusive (32 bit)
358   \details Executes a exclusive STR instruction for 32 bit values.
359   \param [in]  value  Value to store
360   \param [in]    ptr  Pointer to location
361   \return          0  Function succeeded
362   \return          1  Function failed
363  */
364 __STATIC_FORCEINLINE  uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
365 {
366    uint32_t result;
367
368    __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
369    return(result);
370 }
371
372
373 /**
374   \brief   Remove the exclusive lock
375   \details Removes the exclusive lock which is created by LDREX.
376  */
377 __STATIC_FORCEINLINE  void __CLREX(void)
378 {
379   __ASM volatile ("clrex" ::: "memory");
380 }
381
382 /**
383   \brief   Signed Saturate
384   \details Saturates a signed value.
385   \param [in]  value  Value to be saturated
386   \param [in]    sat  Bit position to saturate to (1..32)
387   \return             Saturated value
388  */
389 #define __SSAT(ARG1,ARG2) \
390 __extension__ \
391 ({                          \
392   int32_t __RES, __ARG1 = (ARG1); \
393   __ASM ("ssat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
394   __RES; \
395  })
396
397
398 /**
399   \brief   Unsigned Saturate
400   \details Saturates an unsigned value.
401   \param [in]  value  Value to be saturated
402   \param [in]    sat  Bit position to saturate to (0..31)
403   \return             Saturated value
404  */
405 #define __USAT(ARG1,ARG2) \
406 __extension__ \
407 ({                          \
408   uint32_t __RES, __ARG1 = (ARG1); \
409   __ASM ("usat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
410   __RES; \
411  })
412
413 /* ###########################  Core Function Access  ########################### */
414
415 /**
416   \brief   Enable IRQ Interrupts
417   \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
418            Can only be executed in Privileged modes.
419  */
420 __STATIC_FORCEINLINE void __enable_irq(void)
421 {
422   __ASM volatile ("cpsie i" : : : "memory");
423 }
424
425 /**
426   \brief   Disable IRQ Interrupts
427   \details Disables IRQ interrupts by setting the I-bit in the CPSR.
428   Can only be executed in Privileged modes.
429  */
430 __STATIC_FORCEINLINE  void __disable_irq(void)
431 {
432   __ASM volatile ("cpsid i" : : : "memory");
433 }
434
435 /**
436   \brief   Get FPSCR
437   \details Returns the current value of the Floating Point Status/Control register.
438   \return Floating Point Status/Control register value
439 */
440 __STATIC_FORCEINLINE  uint32_t __get_FPSCR(void)
441 {
442   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
443        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
444   #if __has_builtin(__builtin_arm_get_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
445     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
446     return __builtin_arm_get_fpscr();
447   #else
448     uint32_t result;
449
450     __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
451     return(result);
452   #endif
453   #else
454     return(0U);
455   #endif
456 }
457
458 /**
459   \brief   Set FPSCR
460   \details Assigns the given value to the Floating Point Status/Control register.
461   \param [in] fpscr  Floating Point Status/Control value to set
462 */
463 __STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr)
464 {
465   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
466        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
467   #if __has_builtin(__builtin_arm_set_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
468     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
469     __builtin_arm_set_fpscr(fpscr);
470   #else
471     __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory");
472   #endif
473   #else
474     (void)fpscr;
475   #endif
476 }
477
478 /** \brief  Get CPSR Register
479     \return               CPSR Register value
480  */
481 __STATIC_FORCEINLINE uint32_t __get_CPSR(void)
482 {
483   uint32_t result;
484   __ASM volatile("MRS %0, cpsr" : "=r" (result) );
485   return(result);
486 }
487
488 /** \brief  Set CPSR Register
489     \param [in]    cpsr  CPSR value to set
490  */
491 __STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr)
492 {
493 __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
494 }
495
496 /** \brief  Get Mode
497     \return                Processor Mode
498  */
499 __STATIC_FORCEINLINE uint32_t __get_mode(void) {
500     return (__get_CPSR() & 0x1FU);
501 }
502
503 /** \brief  Set Mode
504     \param [in]    mode  Mode value to set
505  */
506 __STATIC_FORCEINLINE void __set_mode(uint32_t mode) {
507   __ASM volatile("MSR  cpsr_c, %0" : : "r" (mode) : "memory");
508 }
509
510 /** \brief  Get Stack Pointer
511     \return Stack Pointer value
512  */
513 __STATIC_FORCEINLINE uint32_t __get_SP(void)
514 {
515   uint32_t result;
516   __ASM volatile("MOV  %0, sp" : "=r" (result) : : "memory");
517   return result;
518 }
519
520 /** \brief  Set Stack Pointer
521     \param [in]    stack  Stack Pointer value to set
522  */
523 __STATIC_FORCEINLINE void __set_SP(uint32_t stack)
524 {
525   __ASM volatile("MOV  sp, %0" : : "r" (stack) : "memory");
526 }
527
528 /** \brief  Get USR/SYS Stack Pointer
529     \return USR/SYS Stack Pointer value
530  */
531 __STATIC_FORCEINLINE uint32_t __get_SP_usr(void)
532 {
533   uint32_t cpsr = __get_CPSR();
534   uint32_t result;
535   __ASM volatile(
536     "CPS     #0x1F  \n"
537     "MOV     %0, sp   " : "=r"(result) : : "memory"
538    );
539   __set_CPSR(cpsr);
540   __ISB();
541   return result;
542 }
543
544 /** \brief  Set USR/SYS Stack Pointer
545     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
546  */
547 __STATIC_FORCEINLINE void __set_SP_usr(uint32_t topOfProcStack)
548 {
549   uint32_t cpsr = __get_CPSR();
550   __ASM volatile(
551     "CPS     #0x1F  \n"
552     "MOV     sp, %0   " : : "r" (topOfProcStack) : "memory"
553    );
554   __set_CPSR(cpsr);
555   __ISB();
556 }
557
558 /** \brief  Get FPEXC
559     \return               Floating Point Exception Control register value
560  */
561 __STATIC_FORCEINLINE uint32_t __get_FPEXC(void)
562 {
563 #if (__FPU_PRESENT == 1)
564   uint32_t result;
565   __ASM volatile("VMRS %0, fpexc" : "=r" (result) );
566   return(result);
567 #else
568   return(0);
569 #endif
570 }
571
572 /** \brief  Set FPEXC
573     \param [in]    fpexc  Floating Point Exception Control value to set
574  */
575 __STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc)
576 {
577 #if (__FPU_PRESENT == 1)
578   __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
579 #endif
580 }
581
582 /*
583  * Include common core functions to access Coprocessor 15 registers
584  */
585
586 #define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
587 #define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
588
589 #include "cmsis_cp15.h"
590
591 __STATIC_FORCEINLINE int32_t log2_up(uint32_t n)
592 {
593   int32_t log = -1;
594   uint32_t t = n;
595   while(t)
596   {
597     log++; t >>=1;
598   }
599   /* if n not power of 2 -> round up*/
600   if ( n & (n - 1) ) log++;
601   return log;
602 }
603
604 __STATIC_INLINE void __L1C_MaintainDCacheSetWay(uint32_t level, uint32_t maint)
605 {
606   register volatile uint32_t Dummy;
607   register volatile uint32_t ccsidr;
608   uint32_t num_sets;
609   uint32_t num_ways;
610   uint32_t shift_way;
611   uint32_t log2_linesize;
612   uint32_t log2_num_ways;
613
614   Dummy = level << 1;
615   /* set csselr, select ccsidr register */
616   __set_CCSIDR(Dummy);
617   /* get current ccsidr register */
618   ccsidr = __get_CCSIDR();
619   num_sets = ((ccsidr & 0x0FFFE000) >> 13) + 1;
620   num_ways = ((ccsidr & 0x00001FF8) >> 3) + 1;
621   log2_linesize = (ccsidr & 0x00000007) + 2 + 2;
622   log2_num_ways = log2_up(num_ways);
623   shift_way = 32 - log2_num_ways;
624   for(int way = num_ways-1; way >= 0; way--) {
625     for(int set = num_sets-1; set >= 0; set--) {
626       Dummy = (level << 1) | (set << log2_linesize) | (way << shift_way);
627       switch (maint)
628       {
629         case 0:
630           __ASM volatile("MCR p15, 0, %0, c7, c6, 2" : : "r"(Dummy) : "memory"); // DCISW. Invalidate by Set/Way
631           break;
632
633         case 1:
634           __ASM volatile("MCR p15, 0, %0, c7, c10, 2" : : "r"(Dummy) : "memory"); // DCCSW. Clean by Set/Way
635           break;
636
637         default:
638           __ASM volatile("MCR p15, 0, %0, c7, c14, 2" : : "r"(Dummy) : "memory"); // DCCISW. Clean and Invalidate by Set/Way
639           break;
640
641       }
642     }
643   }
644   __DMB();
645 }
646
647 /** \brief  Clean and Invalidate the entire data or unified cache
648
649   Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
650  */
651 __STATIC_INLINE void __L1C_CleanInvalidateCache(uint32_t op) {
652   register volatile uint32_t clidr;
653   uint32_t cache_type;
654   clidr =  __get_CLIDR();
655   for(uint32_t i = 0; i<7; i++)
656   {
657     cache_type = (clidr >> i*3) & 0x7UL;
658     if ((cache_type >= 2) && (cache_type <= 4))
659     {
660       __L1C_MaintainDCacheSetWay(i, op);
661     }
662   }
663
664 }
665
666 /** \brief  Enable Floating Point Unit
667
668   Critical section, called from undef handler, so systick is disabled
669  */
670 __STATIC_INLINE void __FPU_Enable(void) {
671   __ASM volatile(
672         //Permit access to VFP/NEON, registers by modifying CPACR
673     "        MRC     p15,0,R1,c1,c0,2  \n"
674     "        ORR     R1,R1,#0x00F00000 \n"
675     "        MCR     p15,0,R1,c1,c0,2  \n"
676
677         //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
678     "        ISB                       \n"
679
680         //Enable VFP/NEON
681     "        VMRS    R1,FPEXC          \n"
682     "        ORR     R1,R1,#0x40000000 \n"
683     "        VMSR    FPEXC,R1          \n"
684
685         //Initialise VFP/NEON registers to 0
686     "        MOV     R2,#0             \n"
687
688 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT >= 16
689         //Initialise D16 registers to 0
690     "        VMOV    D0, R2,R2         \n"
691     "        VMOV    D1, R2,R2         \n"
692     "        VMOV    D2, R2,R2         \n"
693     "        VMOV    D3, R2,R2         \n"
694     "        VMOV    D4, R2,R2         \n"
695     "        VMOV    D5, R2,R2         \n"
696     "        VMOV    D6, R2,R2         \n"
697     "        VMOV    D7, R2,R2         \n"
698     "        VMOV    D8, R2,R2         \n"
699     "        VMOV    D9, R2,R2         \n"
700     "        VMOV    D10,R2,R2         \n"
701     "        VMOV    D11,R2,R2         \n"
702     "        VMOV    D12,R2,R2         \n"
703     "        VMOV    D13,R2,R2         \n"
704     "        VMOV    D14,R2,R2         \n"
705     "        VMOV    D15,R2,R2         \n"
706 #endif
707
708 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
709         //Initialise D32 registers to 0
710     "        VMOV    D16,R2,R2         \n"
711     "        VMOV    D17,R2,R2         \n"
712     "        VMOV    D18,R2,R2         \n"
713     "        VMOV    D19,R2,R2         \n"
714     "        VMOV    D20,R2,R2         \n"
715     "        VMOV    D21,R2,R2         \n"
716     "        VMOV    D22,R2,R2         \n"
717     "        VMOV    D23,R2,R2         \n"
718     "        VMOV    D24,R2,R2         \n"
719     "        VMOV    D25,R2,R2         \n"
720     "        VMOV    D26,R2,R2         \n"
721     "        VMOV    D27,R2,R2         \n"
722     "        VMOV    D28,R2,R2         \n"
723     "        VMOV    D29,R2,R2         \n"
724     "        VMOV    D30,R2,R2         \n"
725     "        VMOV    D31,R2,R2         \n"
726 #endif
727         //Initialise FPSCR to a known state
728     "        VMRS    R2,FPSCR          \n"
729     "        LDR     R3,=0x00086060    \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
730     "        AND     R2,R2,R3          \n"
731     "        VMSR    FPSCR,R2            "
732   );
733 }
734
735 #pragma GCC diagnostic pop
736
737 #endif /* __CMSIS_GCC_H */