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