]> begriffs open source - cmsis/blob - CMSIS/Core_A/Include/cmsis_gcc.h
Make CV execution optional
[cmsis] / CMSIS / Core_A / Include / cmsis_gcc.h
1 /**************************************************************************//**
2  * @file     cmsis_gcc.h
3  * @brief    CMSIS compiler GCC header file
4  * @version  V1.3.3
5  * @date     13. November 2022
6  ******************************************************************************/
7 /*
8  * Copyright (c) 2009-2022 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   CMSIS_DEPRECATED
59   #define CMSIS_DEPRECATED                       __attribute__((deprecated))
60 #endif
61 #ifndef   __USED
62   #define __USED                                 __attribute__((used))
63 #endif
64 #ifndef   __WEAK
65   #define __WEAK                                 __attribute__((weak))
66 #endif
67 #ifndef   __PACKED
68   #define __PACKED                               __attribute__((packed, aligned(1)))
69 #endif
70 #ifndef   __PACKED_STRUCT
71   #define __PACKED_STRUCT                        struct __attribute__((packed, aligned(1)))
72 #endif
73 #ifndef   __UNALIGNED_UINT16_WRITE
74   #pragma GCC diagnostic push
75   #pragma GCC diagnostic ignored "-Wpacked"
76   #pragma GCC diagnostic ignored "-Wattributes"
77   __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
78   #pragma GCC diagnostic pop
79   #define __UNALIGNED_UINT16_WRITE(addr, val)    (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
80 #endif
81 #ifndef   __UNALIGNED_UINT16_READ
82   #pragma GCC diagnostic push
83   #pragma GCC diagnostic ignored "-Wpacked"
84   #pragma GCC diagnostic ignored "-Wattributes"
85   __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
86   #pragma GCC diagnostic pop
87   #define __UNALIGNED_UINT16_READ(addr)          (((const struct T_UINT16_READ *)(const void *)(addr))->v)
88 #endif
89 #ifndef   __UNALIGNED_UINT32_WRITE
90   #pragma GCC diagnostic push
91   #pragma GCC diagnostic ignored "-Wpacked"
92   #pragma GCC diagnostic ignored "-Wattributes"
93   __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
94   #pragma GCC diagnostic pop
95   #define __UNALIGNED_UINT32_WRITE(addr, val)    (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
96 #endif
97 #ifndef   __UNALIGNED_UINT32_READ
98   #pragma GCC diagnostic push
99   #pragma GCC diagnostic ignored "-Wpacked"
100   #pragma GCC diagnostic ignored "-Wattributes"
101   __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
102   #pragma GCC diagnostic pop
103   #define __UNALIGNED_UINT32_READ(addr)          (((const struct T_UINT32_READ *)(const void *)(addr))->v)
104 #endif
105 #ifndef   __ALIGNED
106   #define __ALIGNED(x)                           __attribute__((aligned(x)))
107 #endif
108 #ifndef   __RESTRICT
109   #define __RESTRICT                             __restrict
110 #endif
111 #ifndef   __COMPILER_BARRIER
112   #define __COMPILER_BARRIER()                   __ASM volatile("":::"memory")
113 #endif
114
115
116 /* ##########################  Core Instruction Access  ######################### */
117 /**
118   \brief   No Operation
119   \details No Operation does nothing. This instruction can be used for code alignment purposes.
120  */
121 #define __NOP()                             __ASM volatile ("nop")
122
123 /**
124   \brief   Wait For Interrupt
125   \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
126  */
127 #define __WFI()                             __ASM volatile ("wfi":::"memory")
128
129
130 /**
131   \brief   Wait For Event
132   \details Wait For Event is a hint instruction that permits the processor to enter
133            a low-power state until one of a number of events occurs.
134  */
135 #define __WFE()                             __ASM volatile ("wfe":::"memory")
136
137
138 /**
139   \brief   Send Event
140   \details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
141  */
142 #define __SEV()                             __ASM volatile ("sev")
143
144
145 /**
146   \brief   Instruction Synchronization Barrier
147   \details Instruction Synchronization Barrier flushes the pipeline in the processor,
148            so that all instructions following the ISB are fetched from cache or memory,
149            after the instruction has been completed.
150  */
151 __STATIC_FORCEINLINE  void __ISB(void)
152 {
153   __ASM volatile ("isb 0xF":::"memory");
154 }
155
156
157 /**
158   \brief   Data Synchronization Barrier
159   \details Acts as a special kind of Data Memory Barrier.
160            It completes when all explicit memory accesses before this instruction complete.
161  */
162 __STATIC_FORCEINLINE  void __DSB(void)
163 {
164   __ASM volatile ("dsb 0xF":::"memory");
165 }
166
167
168 /**
169   \brief   Data Memory Barrier
170   \details Ensures the apparent order of the explicit memory operations before
171            and after the instruction, without ensuring their completion.
172  */
173 __STATIC_FORCEINLINE  void __DMB(void)
174 {
175   __ASM volatile ("dmb 0xF":::"memory");
176 }
177
178
179 /**
180   \brief   Reverse byte order (32 bit)
181   \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
182   \param [in]    value  Value to reverse
183   \return               Reversed value
184  */
185 __STATIC_FORCEINLINE  uint32_t __REV(uint32_t value)
186 {
187 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
188   return __builtin_bswap32(value);
189 #else
190   uint32_t result;
191
192   __ASM ("rev %0, %1" : "=r" (result) : "r" (value) );
193   return result;
194 #endif
195 }
196
197
198 /**
199   \brief   Reverse byte order (16 bit)
200   \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
201   \param [in]    value  Value to reverse
202   \return               Reversed value
203  */
204 __STATIC_FORCEINLINE uint32_t __REV16(uint32_t value)
205 {
206   uint32_t result;
207   __ASM ("rev16 %0, %1" : "=r" (result) : "r" (value));
208   return result;
209 }
210
211
212 /**
213   \brief   Reverse byte order (16 bit)
214   \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
215   \param [in]    value  Value to reverse
216   \return               Reversed value
217  */
218 __STATIC_FORCEINLINE  int16_t __REVSH(int16_t value)
219 {
220 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
221   return (int16_t)__builtin_bswap16(value);
222 #else
223   int16_t result;
224
225   __ASM ("revsh %0, %1" : "=r" (result) : "r" (value) );
226   return result;
227 #endif
228 }
229
230
231 /**
232   \brief   Rotate Right in unsigned value (32 bit)
233   \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
234   \param [in]    op1  Value to rotate
235   \param [in]    op2  Number of Bits to rotate
236   \return               Rotated value
237  */
238 __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
239 {
240   op2 %= 32U;
241   if (op2 == 0U)
242   {
243     return op1;
244   }
245   return (op1 >> op2) | (op1 << (32U - op2));
246 }
247
248
249 /**
250   \brief   Breakpoint
251   \details Causes the processor to enter Debug state.
252            Debug tools can use this to investigate system state when the instruction at a particular address is reached.
253   \param [in]    value  is ignored by the processor.
254                  If required, a debugger can use it to store additional information about the breakpoint.
255  */
256 #define __BKPT(value)   __ASM volatile ("bkpt "#value)
257
258
259 /**
260   \brief   Reverse bit order of value
261   \details Reverses the bit order of the given value.
262   \param [in]    value  Value to reverse
263   \return               Reversed value
264  */
265 __STATIC_FORCEINLINE  uint32_t __RBIT(uint32_t value)
266 {
267   uint32_t result;
268    __ASM ("rbit %0, %1" : "=r" (result) : "r" (value) );
269   return result;
270 }
271
272
273 /**
274   \brief   Count leading zeros
275   \details Counts the number of leading zeros of a data value.
276   \param [in]  value  Value to count the leading zeros
277   \return             number of leading zeros in value
278  */
279 __STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value)
280 {
281   /* Even though __builtin_clz produces a CLZ instruction on ARM, formally
282      __builtin_clz(0) is undefined behaviour, so handle this case specially.
283      This guarantees ARM-compatible results if happening to compile on a non-ARM
284      target, and ensures the compiler doesn't decide to activate any
285      optimisations using the logic "value was passed to __builtin_clz, so it
286      is non-zero".
287      ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a
288      single CLZ instruction.
289    */
290   if (value == 0U)
291   {
292     return 32U;
293   }
294   return __builtin_clz(value);
295 }
296
297 /**
298   \brief   LDR Exclusive (8 bit)
299   \details Executes a exclusive LDR instruction for 8 bit value.
300   \param [in]    ptr  Pointer to data
301   \return             value of type uint8_t at (*ptr)
302  */
303 __STATIC_FORCEINLINE  uint8_t __LDREXB(volatile uint8_t *addr)
304 {
305     uint32_t result;
306
307 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
308    __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
309 #else
310     /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
311        accepted by assembler. So has to use following less efficient pattern.
312     */
313    __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
314 #endif
315    return ((uint8_t) result);    /* Add explicit type cast here */
316 }
317
318
319 /**
320   \brief   LDR Exclusive (16 bit)
321   \details Executes a exclusive LDR instruction for 16 bit values.
322   \param [in]    ptr  Pointer to data
323   \return        value of type uint16_t at (*ptr)
324  */
325 __STATIC_FORCEINLINE  uint16_t __LDREXH(volatile uint16_t *addr)
326 {
327     uint32_t result;
328
329 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
330    __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
331 #else
332     /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
333        accepted by assembler. So has to use following less efficient pattern.
334     */
335    __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
336 #endif
337    return ((uint16_t) result);    /* Add explicit type cast here */
338 }
339
340
341 /**
342   \brief   LDR Exclusive (32 bit)
343   \details Executes a exclusive LDR instruction for 32 bit values.
344   \param [in]    ptr  Pointer to data
345   \return        value of type uint32_t at (*ptr)
346  */
347 __STATIC_FORCEINLINE  uint32_t __LDREXW(volatile uint32_t *addr)
348 {
349     uint32_t result;
350
351    __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
352    return(result);
353 }
354
355
356 /**
357   \brief   STR Exclusive (8 bit)
358   \details Executes a exclusive STR instruction for 8 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 __STREXB(uint8_t value, volatile uint8_t *addr)
365 {
366    uint32_t result;
367
368    __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
369    return(result);
370 }
371
372
373 /**
374   \brief   STR Exclusive (16 bit)
375   \details Executes a exclusive STR instruction for 16 bit values.
376   \param [in]  value  Value to store
377   \param [in]    ptr  Pointer to location
378   \return          0  Function succeeded
379   \return          1  Function failed
380  */
381 __STATIC_FORCEINLINE  uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
382 {
383    uint32_t result;
384
385    __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
386    return(result);
387 }
388
389
390 /**
391   \brief   STR Exclusive (32 bit)
392   \details Executes a exclusive STR instruction for 32 bit values.
393   \param [in]  value  Value to store
394   \param [in]    ptr  Pointer to location
395   \return          0  Function succeeded
396   \return          1  Function failed
397  */
398 __STATIC_FORCEINLINE  uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
399 {
400    uint32_t result;
401
402    __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
403    return(result);
404 }
405
406
407 /**
408   \brief   Remove the exclusive lock
409   \details Removes the exclusive lock which is created by LDREX.
410  */
411 __STATIC_FORCEINLINE  void __CLREX(void)
412 {
413   __ASM volatile ("clrex" ::: "memory");
414 }
415
416 /**
417   \brief   Signed Saturate
418   \details Saturates a signed value.
419   \param [in]  ARG1  Value to be saturated
420   \param [in]  ARG2  Bit position to saturate to (1..32)
421   \return             Saturated value
422  */
423 #define __SSAT(ARG1, ARG2) \
424 __extension__ \
425 ({                          \
426   int32_t __RES, __ARG1 = (ARG1); \
427   __ASM volatile ("ssat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) : "cc" ); \
428   __RES; \
429  })
430
431
432 /**
433   \brief   Unsigned Saturate
434   \details Saturates an unsigned value.
435   \param [in]  ARG1  Value to be saturated
436   \param [in]  ARG2  Bit position to saturate to (0..31)
437   \return             Saturated value
438  */
439 #define __USAT(ARG1, ARG2) \
440 __extension__ \
441 ({                          \
442   uint32_t __RES, __ARG1 = (ARG1); \
443   __ASM volatile ("usat %0, %1, %2" : "=r" (__RES) :  "I" (ARG2), "r" (__ARG1) : "cc" ); \
444   __RES; \
445  })
446
447 /* ###########################  Core Function Access  ########################### */
448 /** \ingroup  CMSIS_Core_FunctionInterface
449     \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
450   @{
451  */
452
453 /**
454   \brief   Enable IRQ Interrupts
455   \details Enables IRQ interrupts by clearing special-purpose register PRIMASK.
456            Can only be executed in Privileged modes.
457  */
458 __STATIC_FORCEINLINE void __enable_irq(void)
459 {
460   __ASM volatile ("cpsie i" : : : "memory");
461 }
462
463
464 /**
465   \brief   Disable IRQ Interrupts
466   \details Disables IRQ interrupts by setting special-purpose register PRIMASK.
467   Can only be executed in Privileged modes.
468  */
469 __STATIC_FORCEINLINE void __disable_irq(void)
470 {
471   __ASM volatile ("cpsid i" : : : "memory");
472 }
473
474 /**
475   \brief   Enable FIQ
476   \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK.
477            Can only be executed in Privileged modes.
478  */
479 __STATIC_FORCEINLINE void __enable_fault_irq(void)
480 {
481   __ASM volatile ("cpsie f" : : : "memory");
482 }
483
484
485 /**
486   \brief   Disable FIQ
487   \details Disables FIQ interrupts by setting special-purpose register FAULTMASK.
488            Can only be executed in Privileged modes.
489  */
490 __STATIC_FORCEINLINE void __disable_fault_irq(void)
491 {
492   __ASM volatile ("cpsid f" : : : "memory");
493 }
494
495 /**
496   \brief   Get FPSCR
497   \details Returns the current value of the Floating Point Status/Control register.
498   \return               Floating Point Status/Control register value
499  */
500 __STATIC_FORCEINLINE  uint32_t __get_FPSCR(void)
501 {
502   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
503        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
504   #if __has_builtin(__builtin_arm_get_fpscr) 
505   // Re-enable using built-in when GCC has been fixed
506   // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
507     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
508     return __builtin_arm_get_fpscr();
509   #else
510     uint32_t result;
511
512     __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
513     return(result);
514   #endif
515   #else
516     return(0U);
517   #endif
518 }
519
520
521 /**
522   \brief   Set FPSCR
523   \details Assigns the given value to the Floating Point Status/Control register.
524   \param [in]    fpscr  Floating Point Status/Control value to set
525  */
526 __STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr)
527 {
528   #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
529        (defined (__FPU_USED   ) && (__FPU_USED    == 1U))     )
530   #if __has_builtin(__builtin_arm_set_fpscr)
531   // Re-enable using built-in when GCC has been fixed
532   // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
533     /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
534     __builtin_arm_set_fpscr(fpscr);
535   #else
536     __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory");
537   #endif
538   #else
539     (void)fpscr;
540   #endif
541 }
542
543
544 /*@} end of CMSIS_Core_RegAccFunctions */
545
546
547 /* ###################  Compiler specific Intrinsics  ########################### */
548 /** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
549   Access to dedicated SIMD instructions
550   @{
551 */
552
553 __STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
554 {
555   uint32_t result;
556
557   __ASM ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
558   return(result);
559 }
560
561
562 __STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
563 {
564   uint32_t result;
565
566   __ASM ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
567   return(result);
568 }
569
570
571 __STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
572 {
573   uint32_t result;
574
575   __ASM ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
576   return(result);
577 }
578
579 __STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
580 {
581   uint32_t result;
582
583   __ASM ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
584   return(result);
585 }
586
587 __STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
588 {
589   uint32_t result;
590
591   __ASM ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
592   return(result);
593 }
594
595 __STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
596 {
597   uint32_t result;
598
599   __ASM ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
600   return(result);
601 }
602
603 __STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
604 {
605   uint32_t result;
606
607   __ASM ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
608   return(result);
609 }
610
611 __STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
612 {
613   uint32_t result;
614
615   __ASM ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
616   return(result);
617 }
618
619 __STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
620 {
621   uint32_t result;
622
623   __ASM ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
624   return(result);
625 }
626
627 __STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
628 {
629   uint32_t result;
630
631   __ASM ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
632   return(result);
633 }
634
635 __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1)
636 {
637   uint32_t result;
638
639   __ASM ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
640   return(result);
641 }
642
643 __STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
644 {
645   uint32_t result;
646
647   __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
648   return(result);
649 }
650
651 __STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
652 {
653   uint32_t result;
654
655   __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
656   return(result);
657 }
658
659 __STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
660 {
661   union llreg_u{
662     uint32_t w32[2];
663     uint64_t w64;
664   } llr;
665   llr.w64 = acc;
666
667 #ifndef __ARMEB__   /* Little endian */
668   __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
669 #else               /* Big endian */
670   __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
671 #endif
672
673   return(llr.w64);
674 }
675
676 __STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
677 {
678   union llreg_u{
679     uint32_t w32[2];
680     uint64_t w64;
681   } llr;
682   llr.w64 = acc;
683
684 #ifndef __ARMEB__   /* Little endian */
685   __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
686 #else               /* Big endian */
687   __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
688 #endif
689
690   return(llr.w64);
691 }
692
693 __STATIC_FORCEINLINE uint32_t __SMUSD  (uint32_t op1, uint32_t op2)
694 {
695   uint32_t result;
696
697   __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
698   return(result);
699 }
700
701 __STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
702 {
703   uint32_t result;
704
705   __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
706   return(result);
707 }
708
709 __STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
710 {
711   uint32_t result;
712
713   __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
714   return(result);
715 }
716
717 __STATIC_FORCEINLINE  int32_t __QADD( int32_t op1,  int32_t op2)
718 {
719   int32_t result;
720
721   __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
722   return(result);
723 }
724
725 __STATIC_FORCEINLINE  int32_t __QSUB( int32_t op1,  int32_t op2)
726 {
727   int32_t result;
728
729   __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
730   return(result);
731 }
732
733
734 __STATIC_FORCEINLINE uint32_t __SMUAD  (uint32_t op1, uint32_t op2)
735 {
736   uint32_t result;
737
738   __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
739   return(result);
740 }
741
742
743
744 #define __PKHBT(ARG1,ARG2,ARG3)          ( ((((uint32_t)(ARG1))          ) & 0x0000FFFFUL) |  \
745                                            ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL)  )
746
747 #define __PKHTB(ARG1,ARG2,ARG3)          ( ((((uint32_t)(ARG1))          ) & 0xFFFF0000UL) |  \
748                                            ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL)  )
749
750 __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
751 {
752  int32_t result;
753
754  __ASM ("smmla %0, %1, %2, %3" : "=r" (result): "r"  (op1), "r" (op2), "r" (op3) );
755  return(result);
756 }
757
758 __STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
759 {
760   uint32_t result;
761
762   __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
763   return(result);
764 }
765
766 /*@} end of group CMSIS_SIMD_intrinsics */
767
768
769
770 /** \defgroup CMSIS_Core_intrinsics CMSIS Core Intrinsics
771   Access to dedicated SIMD instructions
772   @{
773 */
774
775 /** \brief  Get CPSR Register
776     \return               CPSR Register value
777  */
778 __STATIC_FORCEINLINE uint32_t __get_CPSR(void)
779 {
780   uint32_t result;
781   __ASM volatile("MRS %0, cpsr" : "=r" (result) );
782   return(result);
783 }
784
785 /** \brief  Set CPSR Register
786     \param [in]    cpsr  CPSR value to set
787  */
788 __STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr)
789 {
790   __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc", "memory");
791 }
792
793 /** \brief  Get Mode
794     \return                Processor Mode
795  */
796 __STATIC_FORCEINLINE uint32_t __get_mode(void)
797 {
798   return (__get_CPSR() & 0x1FU);
799 }
800
801 /** \brief  Set Mode
802     \param [in]    mode  Mode value to set
803  */
804 __STATIC_FORCEINLINE void __set_mode(uint32_t mode)
805 {
806   __ASM volatile("MSR  cpsr_c, %0" : : "r" (mode) : "memory");
807 }
808
809 /** \brief  Get Stack Pointer
810     \return Stack Pointer value
811  */
812 __STATIC_FORCEINLINE uint32_t __get_SP(void)
813 {
814   uint32_t result;
815   __ASM volatile("MOV  %0, sp" : "=r" (result) : : "memory");
816   return result;
817 }
818
819 /** \brief  Set Stack Pointer
820     \param [in]    stack  Stack Pointer value to set
821  */
822 __STATIC_FORCEINLINE void __set_SP(uint32_t stack)
823 {
824   __ASM volatile("MOV  sp, %0" : : "r" (stack) : "memory");
825 }
826
827 /** \brief  Get USR/SYS Stack Pointer
828     \return USR/SYS Stack Pointer value
829  */
830 __STATIC_FORCEINLINE uint32_t __get_SP_usr(void)
831 {
832   uint32_t cpsr = __get_CPSR();
833   uint32_t result;
834   __ASM volatile(
835     "CPS     #0x1F  \n"
836     "MOV     %0, sp   " : "=r"(result) : : "memory"
837    );
838   __set_CPSR(cpsr);
839   __ISB();
840   return result;
841 }
842
843 /** \brief  Set USR/SYS Stack Pointer
844     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
845  */
846 __STATIC_FORCEINLINE void __set_SP_usr(uint32_t topOfProcStack)
847 {
848   uint32_t cpsr = __get_CPSR();
849   __ASM volatile(
850     "CPS     #0x1F  \n"
851     "MOV     sp, %0   " : : "r" (topOfProcStack) : "memory"
852    );
853   __set_CPSR(cpsr);
854   __ISB();
855 }
856
857 /** \brief  Get FPEXC
858     \return               Floating Point Exception Control register value
859  */
860 __STATIC_FORCEINLINE uint32_t __get_FPEXC(void)
861 {
862 #if (__FPU_PRESENT == 1)
863   uint32_t result;
864   __ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory");
865   return(result);
866 #else
867   return(0);
868 #endif
869 }
870
871 /** \brief  Set FPEXC
872     \param [in]    fpexc  Floating Point Exception Control value to set
873  */
874 __STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc)
875 {
876 #if (__FPU_PRESENT == 1)
877   __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
878 #endif
879 }
880
881 /*
882  * Include common core functions to access Coprocessor 15 registers
883  */
884
885 #define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
886 #define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
887 #define __get_CP64(cp, op1, Rt, CRm)         __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : "=r" (Rt) : : "memory" )
888 #define __set_CP64(cp, op1, Rt, CRm)         __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : : "r" (Rt) : "memory" )
889
890 #include "cmsis_cp15.h"
891
892 /** \brief  Enable Floating Point Unit
893
894   Critical section, called from undef handler, so systick is disabled
895  */
896 __STATIC_INLINE void __FPU_Enable(void)
897 {
898   // Permit access to VFP/NEON, registers by modifying CPACR
899   const uint32_t cpacr = __get_CPACR();
900   __set_CPACR(cpacr | 0x00F00000ul);
901   __ISB();
902
903   // Enable VFP/NEON
904   const uint32_t fpexc = __get_FPEXC();
905   __set_FPEXC(fpexc | 0x40000000ul);
906
907   __ASM volatile(
908     // Initialise VFP/NEON registers to 0
909     "        MOV     R2,#0             \n"
910
911     // Initialise D16 registers to 0
912     "        VMOV    D0, R2,R2         \n"
913     "        VMOV    D1, R2,R2         \n"
914     "        VMOV    D2, R2,R2         \n"
915     "        VMOV    D3, R2,R2         \n"
916     "        VMOV    D4, R2,R2         \n"
917     "        VMOV    D5, R2,R2         \n"
918     "        VMOV    D6, R2,R2         \n"
919     "        VMOV    D7, R2,R2         \n"
920     "        VMOV    D8, R2,R2         \n"
921     "        VMOV    D9, R2,R2         \n"
922     "        VMOV    D10,R2,R2         \n"
923     "        VMOV    D11,R2,R2         \n"
924     "        VMOV    D12,R2,R2         \n"
925     "        VMOV    D13,R2,R2         \n"
926     "        VMOV    D14,R2,R2         \n"
927     "        VMOV    D15,R2,R2         \n"
928
929 #if (defined(__ARM_NEON) && (__ARM_NEON == 1))
930     // Initialise D32 registers to 0
931     "        VMOV    D16,R2,R2         \n"
932     "        VMOV    D17,R2,R2         \n"
933     "        VMOV    D18,R2,R2         \n"
934     "        VMOV    D19,R2,R2         \n"
935     "        VMOV    D20,R2,R2         \n"
936     "        VMOV    D21,R2,R2         \n"
937     "        VMOV    D22,R2,R2         \n"
938     "        VMOV    D23,R2,R2         \n"
939     "        VMOV    D24,R2,R2         \n"
940     "        VMOV    D25,R2,R2         \n"
941     "        VMOV    D26,R2,R2         \n"
942     "        VMOV    D27,R2,R2         \n"
943     "        VMOV    D28,R2,R2         \n"
944     "        VMOV    D29,R2,R2         \n"
945     "        VMOV    D30,R2,R2         \n"
946     "        VMOV    D31,R2,R2         \n"
947 #endif
948     : : : "cc", "r2"
949   );
950
951   // Initialise FPSCR to a known state
952   const uint32_t fpscr = __get_FPSCR();
953   __set_FPSCR(fpscr & 0x00086060ul);
954 }
955
956 /*@} end of group CMSIS_Core_intrinsics */
957
958 #pragma GCC diagnostic pop
959
960 #endif /* __CMSIS_GCC_H */