]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_gcc.h
Core(A): Refactored all Coprocessor 15 related core functions into a common header...
[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.00
5  * @date     06. Jul 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 __attribute__((always_inline)) __STATIC_INLINE 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 ({                          \
391   int32_t __RES, __ARG1 = (ARG1); \
392   __ASM ("ssat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
393   __RES; \
394  })
395
396
397 /**
398   \brief   Unsigned Saturate
399   \details Saturates an unsigned value.
400   \param [in]  value  Value to be saturated
401   \param [in]    sat  Bit position to saturate to (0..31)
402   \return             Saturated value
403  */
404 #define __USAT(ARG1,ARG2) \
405 ({                          \
406   uint32_t __RES, __ARG1 = (ARG1); \
407   __ASM ("usat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) ); \
408   __RES; \
409  })
410
411 /* ###########################  Core Function Access  ########################### */
412
413 /**
414   \brief   Enable IRQ Interrupts
415   \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
416            Can only be executed in Privileged modes.
417  */
418 __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
419 {
420   __ASM volatile ("cpsie i" : : : "memory");
421 }
422
423 /**
424   \brief   Disable IRQ Interrupts
425   \details Disables IRQ interrupts by setting the I-bit in the CPSR.
426   Can only be executed in Privileged modes.
427  */
428 __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
429 {
430   __ASM volatile ("cpsid i" : : : "memory");
431 }
432
433 /**
434   \brief   Get FPSCR
435   \details Returns the current value of the Floating Point Status/Control register.
436   \return Floating Point Status/Control register value
437 */
438 __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void)
439 {
440   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
441        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
442   #if __has_builtin(__builtin_arm_get_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
443     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
444     return __builtin_arm_get_fpscr();
445   #else
446     uint32_t result;
447
448     __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
449     return(result);
450   #endif
451   #else
452     return(0U);
453   #endif
454 }
455
456 /**
457   \brief   Set FPSCR
458   \details Assigns the given value to the Floating Point Status/Control register.
459   \param [in] fpscr  Floating Point Status/Control value to set
460 */
461 __attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
462 {
463   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
464        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
465   #if __has_builtin(__builtin_arm_set_fpscr) || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
466     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
467     __builtin_arm_set_fpscr(fpscr);
468   #else
469     __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory");
470   #endif
471   #else
472     (void)fpscr;
473   #endif
474 }
475
476 /** \brief  Get CPSR Register
477     \return               CPSR Register value
478  */
479 __STATIC_INLINE uint32_t __get_CPSR(void)
480 {
481   uint32_t result;
482   __ASM volatile("MRS %0, cpsr" : "=r" (result) );
483   return(result);
484 }
485
486 /** \brief  Set CPSR Register
487     \param [in]    cpsr  CPSR value to set
488  */
489 __STATIC_INLINE void __set_CPSR(uint32_t cpsr)
490 {
491 __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
492 }
493
494 /** \brief  Get Mode
495     \return                Processor Mode
496  */
497 __STATIC_INLINE uint32_t __get_mode(void) {
498     return (__get_CPSR() & 0x1FU);
499 }
500
501 /** \brief  Set Mode
502     \param [in]    mode  Mode value to set
503  */
504 __STATIC_INLINE void __set_mode(uint32_t mode) {
505   __ASM volatile("MSR  cpsr_c, %0" : : "r" (mode) : "memory");
506 }
507
508 /** \brief  Get Stack Pointer
509     \return Stack Pointer value
510  */
511 __STATIC_INLINE uint32_t __get_SP()
512 {
513   uint32_t result;
514   __ASM volatile("MOV  %0, sp" : "=r" (result) : : "memory");
515   return result;
516 }
517
518 /** \brief  Set Stack Pointer
519     \param [in]    stack  Stack Pointer value to set
520  */
521 __STATIC_INLINE void __set_SP(uint32_t stack)
522 {
523   __ASM volatile("MOV  sp, %0" : : "r" (stack) : "memory");
524 }
525
526 /** \brief  Get USR/SYS Stack Pointer
527     \return USR/SYS Stack Pointer value
528  */
529 __STATIC_INLINE uint32_t __get_SP_usr()
530 {
531   uint32_t cpsr;
532   uint32_t result;
533   __ASM volatile(
534     "MRS     %0, cpsr   \n"
535     "CPS     #0x1F      \n" // no effect in USR mode
536     "MOV     %1, sp     \n"
537     "MSR     cpsr_c, %2 \n" // no effect in USR mode
538     "ISB" :  "=r"(cpsr), "=r"(result) : "r"(cpsr) : "memory"
539    );
540   return result;
541 }
542
543 /** \brief  Set USR/SYS Stack Pointer
544     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
545  */
546 __STATIC_INLINE void __set_SP_usr(uint32_t topOfProcStack)
547 {
548   uint32_t cpsr;
549   __ASM volatile(
550     "MRS     %0, cpsr   \n"
551     "CPS     #0x1F      \n" // no effect in USR mode
552     "MOV     sp, %1     \n"
553     "MSR     cpsr_c, %2 \n" // no effect in USR mode
554     "ISB" : "=r"(cpsr) : "r" (topOfProcStack), "r"(cpsr) : "memory"
555    );
556 }
557
558 /** \brief  Get FPEXC
559     \return               Floating Point Exception Control register value
560  */
561 __STATIC_INLINE uint32_t __get_FPEXC(void)
562 {
563 #if (__FPU_PRESENT == 1)
564   uint32_t result;
565   __ASM volatile("MRS %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_INLINE void __set_FPEXC(uint32_t fpexc)
576 {
577 #if (__FPU_PRESENT == 1)
578   __ASM volatile ("MSR 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_INLINE 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 */