]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_gcc.h
Core: Fixed MISRA warnings.
[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 unsigned integer value. For example, 0x12345678 becomes 0x78563412.
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   \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
179   \param [in]    value  Value to reverse
180   \return               Reversed value
181  */
182 #ifndef __NO_EMBEDDED_ASM
183 __attribute__((section(".rev16_text"))) __STATIC_INLINE uint32_t __REV16(uint32_t value)
184 {
185   uint32_t result;
186   __ASM volatile("rev16 %0, %1" : "=r" (result) : "r" (value));
187   return result;
188 }
189 #endif
190
191 /**
192   \brief   Reverse byte order (16 bit)
193   \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
194   \param [in]    value  Value to reverse
195   \return               Reversed value
196  */
197 __STATIC_FORCEINLINE  int16_t __REVSH(int16_t value)
198 {
199 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
200   return (int16_t)__builtin_bswap16(value);
201 #else
202   int16_t result;
203
204   __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
205   return result;
206 #endif
207 }
208
209 /**
210   \brief   Rotate Right in unsigned value (32 bit)
211   \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
212   \param [in]    op1  Value to rotate
213   \param [in]    op2  Number of Bits to rotate
214   \return               Rotated value
215  */
216 __STATIC_FORCEINLINE  uint32_t __ROR(uint32_t op1, uint32_t op2)
217 {
218   op2 %= 32U;
219   if (op2 == 0U) {
220     return op1;
221   }
222   return (op1 >> op2) | (op1 << (32U - op2));
223 }
224
225
226 /**
227   \brief   Breakpoint
228   \param [in]    value  is ignored by the processor.
229                  If required, a debugger can use it to store additional information about the breakpoint.
230  */
231 #define __BKPT(value)                       __ASM volatile ("bkpt "#value)
232
233 /**
234   \brief   Reverse bit order of value
235   \details Reverses the bit order of the given value.
236   \param [in]    value  Value to reverse
237   \return               Reversed value
238  */
239 __STATIC_FORCEINLINE  uint32_t __RBIT(uint32_t value)
240 {
241   uint32_t result;
242
243 #if ((defined (__ARM_ARCH_7M__      ) && (__ARM_ARCH_7M__      == 1)) || \
244      (defined (__ARM_ARCH_7EM__     ) && (__ARM_ARCH_7EM__     == 1)) || \
245      (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))    )
246    __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
247 #else
248   int32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
249
250   result = value;                      /* r will be reversed bits of v; first get LSB of v */
251   for (value >>= 1U; value; value >>= 1U)
252   {
253     result <<= 1U;
254     result |= value & 1U;
255     s--;
256   }
257   result <<= s;                        /* shift when v's highest bits are zero */
258 #endif
259   return result;
260 }
261
262 /**
263   \brief   Count leading zeros
264   \param [in]  value  Value to count the leading zeros
265   \return             number of leading zeros in value
266  */
267 #define __CLZ                             __builtin_clz
268
269 /**
270   \brief   LDR Exclusive (8 bit)
271   \details Executes a exclusive LDR instruction for 8 bit value.
272   \param [in]    ptr  Pointer to data
273   \return             value of type uint8_t at (*ptr)
274  */
275 __STATIC_FORCEINLINE  uint8_t __LDREXB(volatile uint8_t *addr)
276 {
277     uint32_t result;
278
279 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
280    __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
281 #else
282     /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
283        accepted by assembler. So has to use following less efficient pattern.
284     */
285    __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
286 #endif
287    return ((uint8_t) result);    /* Add explicit type cast here */
288 }
289
290
291 /**
292   \brief   LDR Exclusive (16 bit)
293   \details Executes a exclusive LDR instruction for 16 bit values.
294   \param [in]    ptr  Pointer to data
295   \return        value of type uint16_t at (*ptr)
296  */
297 __STATIC_FORCEINLINE  uint16_t __LDREXH(volatile uint16_t *addr)
298 {
299     uint32_t result;
300
301 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
302    __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
303 #else
304     /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
305        accepted by assembler. So has to use following less efficient pattern.
306     */
307    __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
308 #endif
309    return ((uint16_t) result);    /* Add explicit type cast here */
310 }
311
312
313 /**
314   \brief   LDR Exclusive (32 bit)
315   \details Executes a exclusive LDR instruction for 32 bit values.
316   \param [in]    ptr  Pointer to data
317   \return        value of type uint32_t at (*ptr)
318  */
319 __STATIC_FORCEINLINE  uint32_t __LDREXW(volatile uint32_t *addr)
320 {
321     uint32_t result;
322
323    __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
324    return(result);
325 }
326
327
328 /**
329   \brief   STR Exclusive (8 bit)
330   \details Executes a exclusive STR instruction for 8 bit values.
331   \param [in]  value  Value to store
332   \param [in]    ptr  Pointer to location
333   \return          0  Function succeeded
334   \return          1  Function failed
335  */
336 __STATIC_FORCEINLINE  uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
337 {
338    uint32_t result;
339
340    __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
341    return(result);
342 }
343
344
345 /**
346   \brief   STR Exclusive (16 bit)
347   \details Executes a exclusive STR instruction for 16 bit values.
348   \param [in]  value  Value to store
349   \param [in]    ptr  Pointer to location
350   \return          0  Function succeeded
351   \return          1  Function failed
352  */
353 __STATIC_FORCEINLINE  uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
354 {
355    uint32_t result;
356
357    __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
358    return(result);
359 }
360
361
362 /**
363   \brief   STR Exclusive (32 bit)
364   \details Executes a exclusive STR instruction for 32 bit values.
365   \param [in]  value  Value to store
366   \param [in]    ptr  Pointer to location
367   \return          0  Function succeeded
368   \return          1  Function failed
369  */
370 __STATIC_FORCEINLINE  uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
371 {
372    uint32_t result;
373
374    __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
375    return(result);
376 }
377
378
379 /**
380   \brief   Remove the exclusive lock
381   \details Removes the exclusive lock which is created by LDREX.
382  */
383 __STATIC_FORCEINLINE  void __CLREX(void)
384 {
385   __ASM volatile ("clrex" ::: "memory");
386 }
387
388 /**
389   \brief   Signed Saturate
390   \details Saturates a signed value.
391   \param [in]  value  Value to be saturated
392   \param [in]    sat  Bit position to saturate to (1..32)
393   \return             Saturated value
394  */
395 #define __SSAT(ARG1,ARG2) \
396 __extension__ \
397 ({                          \
398   int32_t __RES, __ARG1 = (ARG1); \
399   __ASM ("ssat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
400   __RES; \
401  })
402
403
404 /**
405   \brief   Unsigned Saturate
406   \details Saturates an unsigned value.
407   \param [in]  value  Value to be saturated
408   \param [in]    sat  Bit position to saturate to (0..31)
409   \return             Saturated value
410  */
411 #define __USAT(ARG1,ARG2) \
412 __extension__ \
413 ({                          \
414   uint32_t __RES, __ARG1 = (ARG1); \
415   __ASM ("usat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
416   __RES; \
417  })
418
419 /* ###########################  Core Function Access  ########################### */
420
421 /**
422   \brief   Enable IRQ Interrupts
423   \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
424            Can only be executed in Privileged modes.
425  */
426 __STATIC_FORCEINLINE void __enable_irq(void)
427 {
428   __ASM volatile ("cpsie i" : : : "memory");
429 }
430
431 /**
432   \brief   Disable IRQ Interrupts
433   \details Disables IRQ interrupts by setting the I-bit in the CPSR.
434   Can only be executed in Privileged modes.
435  */
436 __STATIC_FORCEINLINE  void __disable_irq(void)
437 {
438   __ASM volatile ("cpsid i" : : : "memory");
439 }
440
441 /**
442   \brief   Get FPSCR
443   \details Returns the current value of the Floating Point Status/Control register.
444   \return Floating Point Status/Control register value
445 */
446 __STATIC_FORCEINLINE  uint32_t __get_FPSCR(void)
447 {
448   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
449        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
450   #if __has_builtin(__builtin_arm_get_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
451     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
452     return __builtin_arm_get_fpscr();
453   #else
454     uint32_t result;
455
456     __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
457     return(result);
458   #endif
459   #else
460     return(0U);
461   #endif
462 }
463
464 /**
465   \brief   Set FPSCR
466   \details Assigns the given value to the Floating Point Status/Control register.
467   \param [in] fpscr  Floating Point Status/Control value to set
468 */
469 __STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr)
470 {
471   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
472        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
473   #if __has_builtin(__builtin_arm_set_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
474     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
475     __builtin_arm_set_fpscr(fpscr);
476   #else
477     __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory");
478   #endif
479   #else
480     (void)fpscr;
481   #endif
482 }
483
484 /** \brief  Get CPSR Register
485     \return               CPSR Register value
486  */
487 __STATIC_FORCEINLINE uint32_t __get_CPSR(void)
488 {
489   uint32_t result;
490   __ASM volatile("MRS %0, cpsr" : "=r" (result) );
491   return(result);
492 }
493
494 /** \brief  Set CPSR Register
495     \param [in]    cpsr  CPSR value to set
496  */
497 __STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr)
498 {
499 __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
500 }
501
502 /** \brief  Get Mode
503     \return                Processor Mode
504  */
505 __STATIC_FORCEINLINE uint32_t __get_mode(void) {
506     return (__get_CPSR() & 0x1FU);
507 }
508
509 /** \brief  Set Mode
510     \param [in]    mode  Mode value to set
511  */
512 __STATIC_FORCEINLINE void __set_mode(uint32_t mode) {
513   __ASM volatile("MSR  cpsr_c, %0" : : "r" (mode) : "memory");
514 }
515
516 /** \brief  Get Stack Pointer
517     \return Stack Pointer value
518  */
519 __STATIC_FORCEINLINE uint32_t __get_SP(void)
520 {
521   uint32_t result;
522   __ASM volatile("MOV  %0, sp" : "=r" (result) : : "memory");
523   return result;
524 }
525
526 /** \brief  Set Stack Pointer
527     \param [in]    stack  Stack Pointer value to set
528  */
529 __STATIC_FORCEINLINE void __set_SP(uint32_t stack)
530 {
531   __ASM volatile("MOV  sp, %0" : : "r" (stack) : "memory");
532 }
533
534 /** \brief  Get USR/SYS Stack Pointer
535     \return USR/SYS Stack Pointer value
536  */
537 __STATIC_FORCEINLINE uint32_t __get_SP_usr(void)
538 {
539   uint32_t cpsr = __get_CPSR();
540   uint32_t result;
541   __ASM volatile(
542     "CPS     #0x1F  \n"
543     "MOV     %0, sp   " : "=r"(result) : : "memory"
544    );
545   __set_CPSR(cpsr);
546   __ISB();
547   return result;
548 }
549
550 /** \brief  Set USR/SYS Stack Pointer
551     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
552  */
553 __STATIC_FORCEINLINE void __set_SP_usr(uint32_t topOfProcStack)
554 {
555   uint32_t cpsr = __get_CPSR();
556   __ASM volatile(
557     "CPS     #0x1F  \n"
558     "MOV     sp, %0   " : : "r" (topOfProcStack) : "memory"
559    );
560   __set_CPSR(cpsr);
561   __ISB();
562 }
563
564 /** \brief  Get FPEXC
565     \return               Floating Point Exception Control register value
566  */
567 __STATIC_FORCEINLINE uint32_t __get_FPEXC(void)
568 {
569 #if (__FPU_PRESENT == 1)
570   uint32_t result;
571   __ASM volatile("VMRS %0, fpexc" : "=r" (result) );
572   return(result);
573 #else
574   return(0);
575 #endif
576 }
577
578 /** \brief  Set FPEXC
579     \param [in]    fpexc  Floating Point Exception Control value to set
580  */
581 __STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc)
582 {
583 #if (__FPU_PRESENT == 1)
584   __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
585 #endif
586 }
587
588 /*
589  * Include common core functions to access Coprocessor 15 registers
590  */
591
592 #define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
593 #define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
594 #define __get_CP64(cp, op1, Rt, CRm) __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : "=r" (Rt) : : "memory" )
595 #define __set_CP64(cp, op1, Rt, CRm) __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : : "r" (Rt) : "memory" )
596
597 #include "cmsis_cp15.h"
598
599 __STATIC_FORCEINLINE int32_t log2_up(uint32_t n)
600 {
601   int32_t log = -1;
602   uint32_t t = n;
603   while(t)
604   {
605     log++; t >>=1;
606   }
607   /* if n not power of 2 -> round up*/
608   if ( n & (n - 1) ) log++;
609   return log;
610 }
611
612 __STATIC_INLINE void __L1C_MaintainDCacheSetWay(uint32_t level, uint32_t maint)
613 {
614   register volatile uint32_t Dummy;
615   register volatile uint32_t ccsidr;
616   uint32_t num_sets;
617   uint32_t num_ways;
618   uint32_t shift_way;
619   uint32_t log2_linesize;
620   uint32_t log2_num_ways;
621
622   Dummy = level << 1;
623   /* set csselr, select ccsidr register */
624   __set_CCSIDR(Dummy);
625   /* get current ccsidr register */
626   ccsidr = __get_CCSIDR();
627   num_sets = ((ccsidr & 0x0FFFE000) >> 13) + 1;
628   num_ways = ((ccsidr & 0x00001FF8) >> 3) + 1;
629   log2_linesize = (ccsidr & 0x00000007) + 2 + 2;
630   log2_num_ways = log2_up(num_ways);
631   shift_way = 32 - log2_num_ways;
632   for(int way = num_ways-1; way >= 0; way--) {
633     for(int set = num_sets-1; set >= 0; set--) {
634       Dummy = (level << 1) | (set << log2_linesize) | (way << shift_way);
635       switch (maint)
636       {
637         case 0:
638           __ASM volatile("MCR p15, 0, %0, c7, c6, 2" : : "r"(Dummy) : "memory"); // DCISW. Invalidate by Set/Way
639           break;
640
641         case 1:
642           __ASM volatile("MCR p15, 0, %0, c7, c10, 2" : : "r"(Dummy) : "memory"); // DCCSW. Clean by Set/Way
643           break;
644
645         default:
646           __ASM volatile("MCR p15, 0, %0, c7, c14, 2" : : "r"(Dummy) : "memory"); // DCCISW. Clean and Invalidate by Set/Way
647           break;
648
649       }
650     }
651   }
652   __DMB();
653 }
654
655 /** \brief  Clean and Invalidate the entire data or unified cache
656
657   Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
658  */
659 __STATIC_INLINE void __L1C_CleanInvalidateCache(uint32_t op) {
660   register volatile uint32_t clidr;
661   uint32_t cache_type;
662   clidr =  __get_CLIDR();
663   for(uint32_t i = 0; i<7; i++)
664   {
665     cache_type = (clidr >> i*3) & 0x7UL;
666     if ((cache_type >= 2) && (cache_type <= 4))
667     {
668       __L1C_MaintainDCacheSetWay(i, op);
669     }
670   }
671
672 }
673
674 /** \brief  Enable Floating Point Unit
675
676   Critical section, called from undef handler, so systick is disabled
677  */
678 __STATIC_INLINE void __FPU_Enable(void) {
679   __ASM volatile(
680         //Permit access to VFP/NEON, registers by modifying CPACR
681     "        MRC     p15,0,R1,c1,c0,2  \n"
682     "        ORR     R1,R1,#0x00F00000 \n"
683     "        MCR     p15,0,R1,c1,c0,2  \n"
684
685         //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
686     "        ISB                       \n"
687
688         //Enable VFP/NEON
689     "        VMRS    R1,FPEXC          \n"
690     "        ORR     R1,R1,#0x40000000 \n"
691     "        VMSR    FPEXC,R1          \n"
692
693         //Initialise VFP/NEON registers to 0
694     "        MOV     R2,#0             \n"
695
696 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT >= 16
697         //Initialise D16 registers to 0
698     "        VMOV    D0, R2,R2         \n"
699     "        VMOV    D1, R2,R2         \n"
700     "        VMOV    D2, R2,R2         \n"
701     "        VMOV    D3, R2,R2         \n"
702     "        VMOV    D4, R2,R2         \n"
703     "        VMOV    D5, R2,R2         \n"
704     "        VMOV    D6, R2,R2         \n"
705     "        VMOV    D7, R2,R2         \n"
706     "        VMOV    D8, R2,R2         \n"
707     "        VMOV    D9, R2,R2         \n"
708     "        VMOV    D10,R2,R2         \n"
709     "        VMOV    D11,R2,R2         \n"
710     "        VMOV    D12,R2,R2         \n"
711     "        VMOV    D13,R2,R2         \n"
712     "        VMOV    D14,R2,R2         \n"
713     "        VMOV    D15,R2,R2         \n"
714 #endif
715
716 #if TARGET_FEATURE_EXTENSION_REGISTER_COUNT == 32
717         //Initialise D32 registers to 0
718     "        VMOV    D16,R2,R2         \n"
719     "        VMOV    D17,R2,R2         \n"
720     "        VMOV    D18,R2,R2         \n"
721     "        VMOV    D19,R2,R2         \n"
722     "        VMOV    D20,R2,R2         \n"
723     "        VMOV    D21,R2,R2         \n"
724     "        VMOV    D22,R2,R2         \n"
725     "        VMOV    D23,R2,R2         \n"
726     "        VMOV    D24,R2,R2         \n"
727     "        VMOV    D25,R2,R2         \n"
728     "        VMOV    D26,R2,R2         \n"
729     "        VMOV    D27,R2,R2         \n"
730     "        VMOV    D28,R2,R2         \n"
731     "        VMOV    D29,R2,R2         \n"
732     "        VMOV    D30,R2,R2         \n"
733     "        VMOV    D31,R2,R2         \n"
734 #endif
735         //Initialise FPSCR to a known state
736     "        VMRS    R2,FPSCR          \n"
737     "        LDR     R3,=0x00086060    \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
738     "        AND     R2,R2,R3          \n"
739     "        VMSR    FPSCR,R2            "
740   );
741 }
742
743 #pragma GCC diagnostic pop
744
745 #endif /* __CMSIS_GCC_H */