1 /*
2  * Copyright (c) 2009-2024 Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #ifndef __CMSIS_GCC_A_H
20 #define __CMSIS_GCC_A_H
21 
22 #ifndef __CMSIS_GCC_H
23   #error "This file must not be included directly"
24 #endif
25 
26 /* ignore some GCC warnings */
27 #pragma GCC diagnostic push
28 #pragma GCC diagnostic ignored "-Wsign-conversion"
29 #pragma GCC diagnostic ignored "-Wconversion"
30 #pragma GCC diagnostic ignored "-Wunused-parameter"
31 
32 
33 /** \defgroup CMSIS_Core_intrinsics CMSIS Core Intrinsics
34   Access to dedicated SIMD instructions
35   @{
36 */
37 
38 /** \brief  Get CPSR Register
39     \return               CPSR Register value
40  */
__get_CPSR(void)41 __STATIC_FORCEINLINE uint32_t __get_CPSR(void)
42 {
43   uint32_t result;
44   __ASM volatile("MRS %0, cpsr" : "=r" (result) );
45   return(result);
46 }
47 
48 /** \brief  Set CPSR Register
49     \param [in]    cpsr  CPSR value to set
50  */
__set_CPSR(uint32_t cpsr)51 __STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr)
52 {
53   __ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "cc", "memory");
54 }
55 
56 /** \brief  Get Mode
57     \return                Processor Mode
58  */
__get_mode(void)59 __STATIC_FORCEINLINE uint32_t __get_mode(void)
60 {
61   return (__get_CPSR() & 0x1FU);
62 }
63 
64 /** \brief  Set Mode
65     \param [in]    mode  Mode value to set
66  */
__set_mode(uint32_t mode)67 __STATIC_FORCEINLINE void __set_mode(uint32_t mode)
68 {
69   __ASM volatile("MSR  cpsr_c, %0" : : "r" (mode) : "memory");
70 }
71 
72 /** \brief  Get Stack Pointer
73     \return Stack Pointer value
74  */
__get_SP(void)75 __STATIC_FORCEINLINE uint32_t __get_SP(void)
76 {
77   uint32_t result;
78   __ASM volatile("MOV  %0, sp" : "=r" (result) : : "memory");
79   return result;
80 }
81 
82 /** \brief  Set Stack Pointer
83     \param [in]    stack  Stack Pointer value to set
84  */
__set_SP(uint32_t stack)85 __STATIC_FORCEINLINE void __set_SP(uint32_t stack)
86 {
87   __ASM volatile("MOV  sp, %0" : : "r" (stack) : "memory");
88 }
89 
90 /** \brief  Get USR/SYS Stack Pointer
91     \return USR/SYS Stack Pointer value
92  */
__get_SP_usr(void)93 __STATIC_FORCEINLINE uint32_t __get_SP_usr(void)
94 {
95   uint32_t cpsr = __get_CPSR();
96   uint32_t result;
97   __ASM volatile(
98     "CPS     #0x1F  \n"
99     "MOV     %0, sp   " : "=r"(result) : : "memory"
100    );
101   __set_CPSR(cpsr);
102   __ISB();
103   return result;
104 }
105 
106 /** \brief  Set USR/SYS Stack Pointer
107     \param [in]    topOfProcStack  USR/SYS Stack Pointer value to set
108  */
__set_SP_usr(uint32_t topOfProcStack)109 __STATIC_FORCEINLINE void __set_SP_usr(uint32_t topOfProcStack)
110 {
111   uint32_t cpsr = __get_CPSR();
112   __ASM volatile(
113     "CPS     #0x1F  \n"
114     "MOV     sp, %0   " : : "r" (topOfProcStack) : "memory"
115    );
116   __set_CPSR(cpsr);
117   __ISB();
118 }
119 
120 /** \brief  Get FPEXC
121     \return               Floating Point Exception Control register value
122  */
__get_FPEXC(void)123 __STATIC_FORCEINLINE uint32_t __get_FPEXC(void)
124 {
125 #if (__FPU_PRESENT == 1)
126   uint32_t result;
127   __ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory");
128   return(result);
129 #else
130   return(0);
131 #endif
132 }
133 
134 /** \brief  Set FPEXC
135     \param [in]    fpexc  Floating Point Exception Control value to set
136  */
__set_FPEXC(uint32_t fpexc)137 __STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc)
138 {
139 #if (__FPU_PRESENT == 1)
140   __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
141 #endif
142 }
143 
144 /*
145  * Include common core functions to access Coprocessor 15 registers
146  */
147 
148 #define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
149 #define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
150 #define __get_CP64(cp, op1, Rt, CRm)         __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : "=r" (Rt) : : "memory" )
151 #define __set_CP64(cp, op1, Rt, CRm)         __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm  : : "r" (Rt) : "memory" )
152 
153 #include "cmsis_cp15.h"
154 
155 /** \brief  Enable Floating Point Unit
156 
157   Critical section, called from undef handler, so systick is disabled
158  */
__FPU_Enable(void)159 __STATIC_INLINE void __FPU_Enable(void)
160 {
161   // Permit access to VFP/NEON, registers by modifying CPACR
162   const uint32_t cpacr = __get_CPACR();
163   __set_CPACR(cpacr | 0x00F00000ul);
164   __ISB();
165 
166   // Enable VFP/NEON
167   const uint32_t fpexc = __get_FPEXC();
168   __set_FPEXC(fpexc | 0x40000000ul);
169 
170   __ASM volatile(
171     // Initialise VFP/NEON registers to 0
172     "        MOV     R2,#0             \n"
173 
174     // Initialise D16 registers to 0
175     "        VMOV    D0, R2,R2         \n"
176     "        VMOV    D1, R2,R2         \n"
177     "        VMOV    D2, R2,R2         \n"
178     "        VMOV    D3, R2,R2         \n"
179     "        VMOV    D4, R2,R2         \n"
180     "        VMOV    D5, R2,R2         \n"
181     "        VMOV    D6, R2,R2         \n"
182     "        VMOV    D7, R2,R2         \n"
183     "        VMOV    D8, R2,R2         \n"
184     "        VMOV    D9, R2,R2         \n"
185     "        VMOV    D10,R2,R2         \n"
186     "        VMOV    D11,R2,R2         \n"
187     "        VMOV    D12,R2,R2         \n"
188     "        VMOV    D13,R2,R2         \n"
189     "        VMOV    D14,R2,R2         \n"
190     "        VMOV    D15,R2,R2         \n"
191 
192 #if (defined(__ARM_NEON) && (__ARM_NEON == 1))
193     // Initialise D32 registers to 0
194     "        VMOV    D16,R2,R2         \n"
195     "        VMOV    D17,R2,R2         \n"
196     "        VMOV    D18,R2,R2         \n"
197     "        VMOV    D19,R2,R2         \n"
198     "        VMOV    D20,R2,R2         \n"
199     "        VMOV    D21,R2,R2         \n"
200     "        VMOV    D22,R2,R2         \n"
201     "        VMOV    D23,R2,R2         \n"
202     "        VMOV    D24,R2,R2         \n"
203     "        VMOV    D25,R2,R2         \n"
204     "        VMOV    D26,R2,R2         \n"
205     "        VMOV    D27,R2,R2         \n"
206     "        VMOV    D28,R2,R2         \n"
207     "        VMOV    D29,R2,R2         \n"
208     "        VMOV    D30,R2,R2         \n"
209     "        VMOV    D31,R2,R2         \n"
210 #endif
211     : : : "cc", "r2"
212   );
213 
214   // Initialise FPSCR to a known state
215   const uint32_t fpscr = __get_FPSCR();
216   __set_FPSCR(fpscr & 0x00086060ul);
217 }
218 
219 /*@} end of group CMSIS_Core_intrinsics */
220 
221 #pragma GCC diagnostic pop
222 
223 #endif /* __CMSIS_GCC_A_H */
224