]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/GCC/ARM_CA53_64_BIT/portASM.S
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Source / portable / GCC / ARM_CA53_64_BIT / portASM.S
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29         .text\r
30 \r
31         /* Variables and functions. */\r
32         .extern ullMaxAPIPriorityMask\r
33         .extern pxCurrentTCB\r
34         .extern vTaskSwitchContext\r
35         .extern vApplicationIRQHandler\r
36         .extern ullPortInterruptNesting\r
37         .extern ullPortTaskHasFPUContext\r
38         .extern ullCriticalNesting\r
39         .extern ullPortYieldRequired\r
40         .extern ullICCEOIR\r
41         .extern ullICCIAR\r
42         .extern _freertos_vector_table\r
43 \r
44         .global FreeRTOS_IRQ_Handler\r
45         .global FreeRTOS_SWI_Handler\r
46         .global vPortRestoreTaskContext\r
47 \r
48 \r
49 .macro portSAVE_CONTEXT\r
50 \r
51         /* Switch to use the EL0 stack pointer. */\r
52         MSR     SPSEL, #0\r
53 \r
54         /* Save the entire context. */\r
55         STP     X0, X1, [SP, #-0x10]!\r
56         STP     X2, X3, [SP, #-0x10]!\r
57         STP     X4, X5, [SP, #-0x10]!\r
58         STP     X6, X7, [SP, #-0x10]!\r
59         STP     X8, X9, [SP, #-0x10]!\r
60         STP     X10, X11, [SP, #-0x10]!\r
61         STP     X12, X13, [SP, #-0x10]!\r
62         STP     X14, X15, [SP, #-0x10]!\r
63         STP     X16, X17, [SP, #-0x10]!\r
64         STP     X18, X19, [SP, #-0x10]!\r
65         STP     X20, X21, [SP, #-0x10]!\r
66         STP     X22, X23, [SP, #-0x10]!\r
67         STP     X24, X25, [SP, #-0x10]!\r
68         STP     X26, X27, [SP, #-0x10]!\r
69         STP     X28, X29, [SP, #-0x10]!\r
70         STP     X30, XZR, [SP, #-0x10]!\r
71 \r
72         /* Save the SPSR. */\r
73 #if defined( GUEST )\r
74         MRS             X3, SPSR_EL1\r
75         MRS             X2, ELR_EL1\r
76 #else\r
77         MRS             X3, SPSR_EL3\r
78         /* Save the ELR. */\r
79         MRS             X2, ELR_EL3\r
80 #endif\r
81 \r
82         STP     X2, X3, [SP, #-0x10]!\r
83 \r
84         /* Save the critical section nesting depth. */\r
85         LDR             X0, ullCriticalNestingConst\r
86         LDR             X3, [X0]\r
87 \r
88         /* Save the FPU context indicator. */\r
89         LDR             X0, ullPortTaskHasFPUContextConst\r
90         LDR             X2, [X0]\r
91 \r
92         /* Save the FPU context, if any (32 128-bit registers). */\r
93         CMP             X2, #0\r
94         B.EQ    1f\r
95         STP             Q0, Q1, [SP,#-0x20]!\r
96         STP             Q2, Q3, [SP,#-0x20]!\r
97         STP             Q4, Q5, [SP,#-0x20]!\r
98         STP             Q6, Q7, [SP,#-0x20]!\r
99         STP             Q8, Q9, [SP,#-0x20]!\r
100         STP             Q10, Q11, [SP,#-0x20]!\r
101         STP             Q12, Q13, [SP,#-0x20]!\r
102         STP             Q14, Q15, [SP,#-0x20]!\r
103         STP             Q16, Q17, [SP,#-0x20]!\r
104         STP             Q18, Q19, [SP,#-0x20]!\r
105         STP             Q20, Q21, [SP,#-0x20]!\r
106         STP             Q22, Q23, [SP,#-0x20]!\r
107         STP             Q24, Q25, [SP,#-0x20]!\r
108         STP             Q26, Q27, [SP,#-0x20]!\r
109         STP             Q28, Q29, [SP,#-0x20]!\r
110         STP             Q30, Q31, [SP,#-0x20]!\r
111 \r
112 1:\r
113         /* Store the critical nesting count and FPU context indicator. */\r
114         STP     X2, X3, [SP, #-0x10]!\r
115 \r
116         LDR     X0, pxCurrentTCBConst\r
117         LDR     X1, [X0]\r
118         MOV     X0, SP   /* Move SP into X0 for saving. */\r
119         STR     X0, [X1]\r
120 \r
121         /* Switch to use the ELx stack pointer. */\r
122         MSR     SPSEL, #1\r
123 \r
124         .endm\r
125 \r
126 ; /**********************************************************************/\r
127 \r
128 .macro portRESTORE_CONTEXT\r
129 \r
130         /* Switch to use the EL0 stack pointer. */\r
131         MSR     SPSEL, #0\r
132 \r
133         /* Set the SP to point to the stack of the task being restored. */\r
134         LDR             X0, pxCurrentTCBConst\r
135         LDR             X1, [X0]\r
136         LDR             X0, [X1]\r
137         MOV             SP, X0\r
138 \r
139         LDP     X2, X3, [SP], #0x10  /* Critical nesting and FPU context. */\r
140 \r
141         /* Set the PMR register to be correct for the current critical nesting\r
142         depth. */\r
143         LDR             X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */\r
144         MOV             X1, #255                                        /* X1 holds the unmask value. */\r
145         LDR             X4, ullICCPMRConst                      /* X4 holds the address of the ICCPMR constant. */\r
146         CMP             X3, #0\r
147         LDR             X5, [X4]                                        /* X5 holds the address of the ICCPMR register. */\r
148         B.EQ    1f\r
149         LDR             X6, ullMaxAPIPriorityMaskConst\r
150         LDR             X1, [X6]                                        /* X1 holds the mask value. */\r
151 1:\r
152         STR             W1, [X5]                                        /* Write the mask value to ICCPMR. */\r
153         DSB     SY                                                      /* _RB_Barriers probably not required here. */\r
154         ISB     SY\r
155         STR             X3, [X0]                                        /* Restore the task's critical nesting count. */\r
156 \r
157         /* Restore the FPU context indicator. */\r
158         LDR             X0, ullPortTaskHasFPUContextConst\r
159         STR             X2, [X0]\r
160 \r
161         /* Restore the FPU context, if any. */\r
162         CMP             X2, #0\r
163         B.EQ    1f\r
164         LDP             Q30, Q31, [SP], #0x20\r
165         LDP             Q28, Q29, [SP], #0x20\r
166         LDP             Q26, Q27, [SP], #0x20\r
167         LDP             Q24, Q25, [SP], #0x20\r
168         LDP             Q22, Q23, [SP], #0x20\r
169         LDP             Q20, Q21, [SP], #0x20\r
170         LDP             Q18, Q19, [SP], #0x20\r
171         LDP             Q16, Q17, [SP], #0x20\r
172         LDP             Q14, Q15, [SP], #0x20\r
173         LDP             Q12, Q13, [SP], #0x20\r
174         LDP             Q10, Q11, [SP], #0x20\r
175         LDP             Q8, Q9, [SP], #0x20\r
176         LDP             Q6, Q7, [SP], #0x20\r
177         LDP             Q4, Q5, [SP], #0x20\r
178         LDP             Q2, Q3, [SP], #0x20\r
179         LDP             Q0, Q1, [SP], #0x20\r
180 1:\r
181         LDP     X2, X3, [SP], #0x10  /* SPSR and ELR. */\r
182 \r
183 #if defined( GUEST )\r
184         /* Restore the SPSR. */\r
185         MSR             SPSR_EL1, X3\r
186         /* Restore the ELR. */\r
187         MSR             ELR_EL1, X2\r
188 #else\r
189         /* Restore the SPSR. */\r
190         MSR             SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */\r
191         /* Restore the ELR. */\r
192         MSR             ELR_EL3, X2\r
193 #endif\r
194 \r
195         LDP     X30, XZR, [SP], #0x10\r
196         LDP     X28, X29, [SP], #0x10\r
197         LDP     X26, X27, [SP], #0x10\r
198         LDP     X24, X25, [SP], #0x10\r
199         LDP     X22, X23, [SP], #0x10\r
200         LDP     X20, X21, [SP], #0x10\r
201         LDP     X18, X19, [SP], #0x10\r
202         LDP     X16, X17, [SP], #0x10\r
203         LDP     X14, X15, [SP], #0x10\r
204         LDP     X12, X13, [SP], #0x10\r
205         LDP     X10, X11, [SP], #0x10\r
206         LDP     X8, X9, [SP], #0x10\r
207         LDP     X6, X7, [SP], #0x10\r
208         LDP     X4, X5, [SP], #0x10\r
209         LDP     X2, X3, [SP], #0x10\r
210         LDP     X0, X1, [SP], #0x10\r
211 \r
212         /* Switch to use the ELx stack pointer.  _RB_ Might not be required. */\r
213         MSR     SPSEL, #1\r
214 \r
215         ERET\r
216 \r
217         .endm\r
218 \r
219 \r
220 /******************************************************************************\r
221  * FreeRTOS_SWI_Handler handler is used to perform a context switch.\r
222  *****************************************************************************/\r
223 .align 8\r
224 .type FreeRTOS_SWI_Handler, %function\r
225 FreeRTOS_SWI_Handler:\r
226         /* Save the context of the current task and select a new task to run. */\r
227         portSAVE_CONTEXT\r
228 #if defined( GUEST )\r
229         MRS             X0, ESR_EL1\r
230 #else\r
231         MRS             X0, ESR_EL3\r
232 #endif\r
233 \r
234         LSR             X1, X0, #26\r
235 \r
236 #if defined( GUEST )\r
237         CMP             X1, #0x15       /* 0x15 = SVC instruction. */\r
238 #else\r
239         CMP             X1, #0x17       /* 0x17 = SMC instruction. */\r
240 #endif\r
241         B.NE    FreeRTOS_Abort\r
242         BL              vTaskSwitchContext\r
243 \r
244         portRESTORE_CONTEXT\r
245 \r
246 FreeRTOS_Abort:\r
247         /* Full ESR is in X0, exception class code is in X1. */\r
248         B               .\r
249 \r
250 /******************************************************************************\r
251  * vPortRestoreTaskContext is used to start the scheduler.\r
252  *****************************************************************************/\r
253 .align 8\r
254 .type vPortRestoreTaskContext, %function\r
255 vPortRestoreTaskContext:\r
256 .set freertos_vector_base,      _freertos_vector_table\r
257 \r
258         /* Install the FreeRTOS interrupt handlers. */\r
259         LDR             X1, =freertos_vector_base\r
260 #if defined( GUEST )\r
261         MSR             VBAR_EL1, X1\r
262 #else\r
263         MSR             VBAR_EL3, X1\r
264 #endif\r
265         DSB             SY\r
266         ISB             SY\r
267 \r
268         /* Start the first task. */\r
269         portRESTORE_CONTEXT\r
270 \r
271 \r
272 /******************************************************************************\r
273  * FreeRTOS_IRQ_Handler handles IRQ entry and exit.\r
274  *****************************************************************************/\r
275 .align 8\r
276 .type FreeRTOS_IRQ_Handler, %function\r
277 FreeRTOS_IRQ_Handler:\r
278         /* Save volatile registers. */\r
279         STP             X0, X1, [SP, #-0x10]!\r
280         STP             X2, X3, [SP, #-0x10]!\r
281         STP             X4, X5, [SP, #-0x10]!\r
282         STP             X6, X7, [SP, #-0x10]!\r
283         STP             X8, X9, [SP, #-0x10]!\r
284         STP             X10, X11, [SP, #-0x10]!\r
285         STP             X12, X13, [SP, #-0x10]!\r
286         STP             X14, X15, [SP, #-0x10]!\r
287         STP             X16, X17, [SP, #-0x10]!\r
288         STP             X18, X19, [SP, #-0x10]!\r
289         STP             X29, X30, [SP, #-0x10]!\r
290 \r
291         /* Save the SPSR and ELR. */\r
292 #if defined( GUEST )\r
293         MRS             X3, SPSR_EL1\r
294         MRS             X2, ELR_EL1\r
295 #else\r
296         MRS             X3, SPSR_EL3\r
297         MRS             X2, ELR_EL3\r
298 #endif\r
299         STP     X2, X3, [SP, #-0x10]!\r
300 \r
301         /* Increment the interrupt nesting counter. */\r
302         LDR             X5, ullPortInterruptNestingConst\r
303         LDR             X1, [X5]        /* Old nesting count in X1. */\r
304         ADD             X6, X1, #1\r
305         STR             X6, [X5]        /* Address of nesting count variable in X5. */\r
306 \r
307         /* Maintain the interrupt nesting information across the function call. */\r
308         STP             X1, X5, [SP, #-0x10]!\r
309 \r
310         /* Read value from the interrupt acknowledge register, which is stored in W0\r
311         for future parameter and interrupt clearing use. */\r
312         LDR     X2, ullICCIARConst\r
313         LDR             X3, [X2]\r
314         LDR             W0, [X3]        /* ICCIAR in W0 as parameter. */\r
315 \r
316         /* Maintain the ICCIAR value across the function call. */\r
317         STP             X0, X1, [SP, #-0x10]!\r
318 \r
319         /* Call the C handler. */\r
320         BL vApplicationIRQHandler\r
321 \r
322         /* Disable interrupts. */\r
323         MSR     DAIFSET, #2\r
324         DSB             SY\r
325         ISB             SY\r
326 \r
327         /* Restore the ICCIAR value. */\r
328         LDP             X0, X1, [SP], #0x10\r
329 \r
330         /* End IRQ processing by writing ICCIAR to the EOI register. */\r
331         LDR     X4, ullICCEOIRConst\r
332         LDR             X4, [X4]\r
333         STR             W0, [X4]\r
334 \r
335         /* Restore the critical nesting count. */\r
336         LDP             X1, X5, [SP], #0x10\r
337         STR             X1, [X5]\r
338 \r
339         /* Has interrupt nesting unwound? */\r
340         CMP             X1, #0\r
341         B.NE    Exit_IRQ_No_Context_Switch\r
342 \r
343         /* Is a context switch required? */\r
344         LDR             X0, ullPortYieldRequiredConst\r
345         LDR             X1, [X0]\r
346         CMP             X1, #0\r
347         B.EQ    Exit_IRQ_No_Context_Switch\r
348 \r
349         /* Reset ullPortYieldRequired to 0. */\r
350         MOV             X2, #0\r
351         STR             X2, [X0]\r
352 \r
353         /* Restore volatile registers. */\r
354         LDP     X4, X5, [SP], #0x10  /* SPSR and ELR. */\r
355 #if defined( GUEST )\r
356         MSR             SPSR_EL1, X5\r
357         MSR             ELR_EL1, X4\r
358 #else\r
359         MSR             SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */\r
360         MSR             ELR_EL3, X4\r
361 #endif\r
362         DSB             SY\r
363         ISB             SY\r
364 \r
365         LDP             X29, X30, [SP], #0x10\r
366         LDP             X18, X19, [SP], #0x10\r
367         LDP             X16, X17, [SP], #0x10\r
368         LDP             X14, X15, [SP], #0x10\r
369         LDP             X12, X13, [SP], #0x10\r
370         LDP             X10, X11, [SP], #0x10\r
371         LDP             X8, X9, [SP], #0x10\r
372         LDP             X6, X7, [SP], #0x10\r
373         LDP             X4, X5, [SP], #0x10\r
374         LDP             X2, X3, [SP], #0x10\r
375         LDP             X0, X1, [SP], #0x10\r
376 \r
377         /* Save the context of the current task and select a new task to run. */\r
378         portSAVE_CONTEXT\r
379         BL vTaskSwitchContext\r
380         portRESTORE_CONTEXT\r
381 \r
382 Exit_IRQ_No_Context_Switch:\r
383         /* Restore volatile registers. */\r
384         LDP     X4, X5, [SP], #0x10  /* SPSR and ELR. */\r
385 #if defined( GUEST )\r
386         MSR             SPSR_EL1, X5\r
387         MSR             ELR_EL1, X4\r
388 #else\r
389         MSR             SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */\r
390         MSR             ELR_EL3, X4\r
391 #endif\r
392         DSB             SY\r
393         ISB             SY\r
394 \r
395         LDP             X29, X30, [SP], #0x10\r
396         LDP             X18, X19, [SP], #0x10\r
397         LDP             X16, X17, [SP], #0x10\r
398         LDP             X14, X15, [SP], #0x10\r
399         LDP             X12, X13, [SP], #0x10\r
400         LDP             X10, X11, [SP], #0x10\r
401         LDP             X8, X9, [SP], #0x10\r
402         LDP             X6, X7, [SP], #0x10\r
403         LDP             X4, X5, [SP], #0x10\r
404         LDP             X2, X3, [SP], #0x10\r
405         LDP             X0, X1, [SP], #0x10\r
406 \r
407         ERET\r
408 \r
409 \r
410 \r
411 \r
412 .align 8\r
413 pxCurrentTCBConst: .dword pxCurrentTCB\r
414 ullCriticalNestingConst: .dword ullCriticalNesting\r
415 ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext\r
416 \r
417 ullICCPMRConst: .dword ullICCPMR\r
418 ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask\r
419 vApplicationIRQHandlerConst: .word vApplicationIRQHandler\r
420 ullPortInterruptNestingConst: .dword ullPortInterruptNesting\r
421 ullPortYieldRequiredConst: .dword ullPortYieldRequired\r
422 ullICCIARConst: .dword ullICCIAR\r
423 ullICCEOIRConst: .dword ullICCEOIR\r
424 \r
425 \r
426 \r
427 .end\r
428 \r
429 \r
430 \r
431 \r
432 \r