]> begriffs open source - freertos/blob - portable/GCC/MicroBlazeV9/portasm.S
Update SMP branch readme for port migration (#999)
[freertos] / portable / GCC / MicroBlazeV9 / portasm.S
1 /*
2  * FreeRTOS SMP Kernel V202110.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /* FreeRTOS includes. */
29 #include "FreeRTOSConfig.h"
30
31 /* Xilinx library includes. */
32 #include "microblaze_exceptions_g.h"
33 #include "xparameters.h"
34
35 /* The context is oversized to allow functions called from the ISR to write
36 back into the caller stack. */
37 #if( XPAR_MICROBLAZE_USE_FPU != 0 )
38         #define portCONTEXT_SIZE 136
39         #define portMINUS_CONTEXT_SIZE -136
40 #else
41         #define portCONTEXT_SIZE 132
42         #define portMINUS_CONTEXT_SIZE -132
43 #endif
44
45 /* Offsets from the stack pointer at which saved registers are placed. */
46 #define portR31_OFFSET  4
47 #define portR30_OFFSET  8
48 #define portR29_OFFSET  12
49 #define portR28_OFFSET  16
50 #define portR27_OFFSET  20
51 #define portR26_OFFSET  24
52 #define portR25_OFFSET  28
53 #define portR24_OFFSET  32
54 #define portR23_OFFSET  36
55 #define portR22_OFFSET  40
56 #define portR21_OFFSET  44
57 #define portR20_OFFSET  48
58 #define portR19_OFFSET  52
59 #define portR18_OFFSET  56
60 #define portR17_OFFSET  60
61 #define portR16_OFFSET  64
62 #define portR15_OFFSET  68
63 #define portR14_OFFSET  72
64 #define portR13_OFFSET  76
65 #define portR12_OFFSET  80
66 #define portR11_OFFSET  84
67 #define portR10_OFFSET  88
68 #define portR9_OFFSET   92
69 #define portR8_OFFSET   96
70 #define portR7_OFFSET   100
71 #define portR6_OFFSET   104
72 #define portR5_OFFSET   108
73 #define portR4_OFFSET   112
74 #define portR3_OFFSET   116
75 #define portR2_OFFSET   120
76 #define portCRITICAL_NESTING_OFFSET 124
77 #define portMSR_OFFSET 128
78 #define portFSR_OFFSET 132
79
80         .extern pxCurrentTCB
81         .extern XIntc_DeviceInterruptHandler
82         .extern vTaskSwitchContext
83         .extern uxCriticalNesting
84         .extern pulISRStack
85         .extern ulTaskSwitchRequested
86         .extern vPortExceptionHandler
87         .extern pulStackPointerOnFunctionEntry
88
89         .global _interrupt_handler
90         .global VPortYieldASM
91         .global vPortStartFirstTask
92         .global vPortExceptionHandlerEntry
93
94
95 .macro portSAVE_CONTEXT
96
97         /* Make room for the context on the stack. */
98         addik r1, r1, portMINUS_CONTEXT_SIZE
99
100         /* Stack general registers. */
101         swi r31, r1, portR31_OFFSET
102         swi r30, r1, portR30_OFFSET
103         swi r29, r1, portR29_OFFSET
104         swi r28, r1, portR28_OFFSET
105         swi r27, r1, portR27_OFFSET
106         swi r26, r1, portR26_OFFSET
107         swi r25, r1, portR25_OFFSET
108         swi r24, r1, portR24_OFFSET
109         swi r23, r1, portR23_OFFSET
110         swi r22, r1, portR22_OFFSET
111         swi r21, r1, portR21_OFFSET
112         swi r20, r1, portR20_OFFSET
113         swi r19, r1, portR19_OFFSET
114         swi r18, r1, portR18_OFFSET
115         swi r17, r1, portR17_OFFSET
116         swi r16, r1, portR16_OFFSET
117         swi r15, r1, portR15_OFFSET
118         /* R14 is saved later as it needs adjustment if a yield is performed. */
119         swi r13, r1, portR13_OFFSET
120         swi r12, r1, portR12_OFFSET
121         swi r11, r1, portR11_OFFSET
122         swi r10, r1, portR10_OFFSET
123         swi r9, r1, portR9_OFFSET
124         swi r8, r1, portR8_OFFSET
125         swi r7, r1, portR7_OFFSET
126         swi r6, r1, portR6_OFFSET
127         swi r5, r1, portR5_OFFSET
128         swi r4, r1, portR4_OFFSET
129         swi r3, r1, portR3_OFFSET
130         swi r2, r1, portR2_OFFSET
131
132         /* Stack the critical section nesting value. */
133         lwi r18, r0, uxCriticalNesting
134         swi r18, r1, portCRITICAL_NESTING_OFFSET
135
136         /* Stack MSR. */
137         mfs r18, rmsr
138         swi r18, r1, portMSR_OFFSET
139
140         #if( XPAR_MICROBLAZE_USE_FPU != 0 )
141                 /* Stack FSR. */
142                 mfs r18, rfsr
143                 swi r18, r1, portFSR_OFFSET
144         #endif
145
146         /* Save the top of stack value to the TCB. */
147         lwi r3, r0, pxCurrentTCB
148         sw      r1, r0, r3
149
150         .endm
151
152 .macro portRESTORE_CONTEXT
153
154         /* Load the top of stack value from the TCB. */
155         lwi r18, r0, pxCurrentTCB
156         lw      r1, r0, r18
157
158         /* Restore the general registers. */
159         lwi r31, r1, portR31_OFFSET
160         lwi r30, r1, portR30_OFFSET
161         lwi r29, r1, portR29_OFFSET
162         lwi r28, r1, portR28_OFFSET
163         lwi r27, r1, portR27_OFFSET
164         lwi r26, r1, portR26_OFFSET
165         lwi r25, r1, portR25_OFFSET
166         lwi r24, r1, portR24_OFFSET
167         lwi r23, r1, portR23_OFFSET
168         lwi r22, r1, portR22_OFFSET
169         lwi r21, r1, portR21_OFFSET
170         lwi r20, r1, portR20_OFFSET
171         lwi r19, r1, portR19_OFFSET
172         lwi r17, r1, portR17_OFFSET
173         lwi r16, r1, portR16_OFFSET
174         lwi r15, r1, portR15_OFFSET
175         lwi r14, r1, portR14_OFFSET
176         lwi r13, r1, portR13_OFFSET
177         lwi r12, r1, portR12_OFFSET
178         lwi r11, r1, portR11_OFFSET
179         lwi r10, r1, portR10_OFFSET
180         lwi r9, r1, portR9_OFFSET
181         lwi r8, r1, portR8_OFFSET
182         lwi r7, r1, portR7_OFFSET
183         lwi r6, r1, portR6_OFFSET
184         lwi r5, r1, portR5_OFFSET
185         lwi r4, r1, portR4_OFFSET
186         lwi r3, r1, portR3_OFFSET
187         lwi r2, r1, portR2_OFFSET
188
189         /* Reload the rmsr from the stack. */
190         lwi r18, r1, portMSR_OFFSET
191         mts rmsr, r18
192
193         #if( XPAR_MICROBLAZE_USE_FPU != 0 )
194                 /* Reload the FSR from the stack. */
195                 lwi r18, r1, portFSR_OFFSET
196                 mts rfsr, r18
197         #endif
198
199         /* Load the critical nesting value. */
200         lwi r18, r1, portCRITICAL_NESTING_OFFSET
201         swi r18, r0, uxCriticalNesting
202
203         /* Test the critical nesting value.  If it is non zero then the task last
204         exited the running state using a yield.  If it is zero, then the task
205         last exited the running state through an interrupt. */
206         xori r18, r18, 0
207         bnei r18, exit_from_yield
208
209         /* r18 was being used as a temporary.  Now restore its true value from the
210         stack. */
211         lwi r18, r1, portR18_OFFSET
212
213         /* Remove the stack frame. */
214         addik r1, r1, portCONTEXT_SIZE
215
216         /* Return using rtid so interrupts are re-enabled as this function is
217         exited. */
218         rtid r14, 0
219         or r0, r0, r0
220
221         .endm
222
223 /* This function is used to exit portRESTORE_CONTEXT() if the task being
224 returned to last left the Running state by calling taskYIELD() (rather than
225 being preempted by an interrupt). */
226         .text
227         .align  4
228 exit_from_yield:
229
230         /* r18 was being used as a temporary.  Now restore its true value from the
231         stack. */
232         lwi r18, r1, portR18_OFFSET
233
234         /* Remove the stack frame. */
235         addik r1, r1, portCONTEXT_SIZE
236
237         /* Return to the task. */
238         rtsd r14, 0
239         or r0, r0, r0
240
241
242         .text
243         .align  4
244 _interrupt_handler:
245
246         portSAVE_CONTEXT
247
248         /* Stack the return address. */
249         swi r14, r1, portR14_OFFSET
250
251         /* Switch to the ISR stack. */
252         lwi r1, r0, pulISRStack
253
254         /* The parameter to the interrupt handler. */
255         ori r5, r0, configINTERRUPT_CONTROLLER_TO_USE
256
257         /* Execute any pending interrupts. */
258         bralid r15, XIntc_DeviceInterruptHandler
259         or r0, r0, r0
260
261         /* See if a new task should be selected to execute. */
262         lwi r18, r0, ulTaskSwitchRequested
263         or r18, r18, r0
264
265         /* If ulTaskSwitchRequested is already zero, then jump straight to
266         restoring the task that is already in the Running state. */
267         beqi r18, task_switch_not_requested
268
269         /* Set ulTaskSwitchRequested back to zero as a task switch is about to be
270         performed. */
271         swi r0, r0, ulTaskSwitchRequested
272
273         /* ulTaskSwitchRequested was not 0 when tested.  Select the next task to
274         execute. */
275         bralid r15, vTaskSwitchContext
276         or r0, r0, r0
277
278 task_switch_not_requested:
279
280         /* Restore the context of the next task scheduled to execute. */
281         portRESTORE_CONTEXT
282
283
284         .text
285         .align  4
286 VPortYieldASM:
287
288         portSAVE_CONTEXT
289
290         /* Modify the return address so a return is done to the instruction after
291         the call to VPortYieldASM. */
292         addi r14, r14, 8
293         swi r14, r1, portR14_OFFSET
294
295         /* Switch to use the ISR stack. */
296         lwi r1, r0, pulISRStack
297
298         /* Select the next task to execute. */
299         bralid r15, vTaskSwitchContext
300         or r0, r0, r0
301
302         /* Restore the context of the next task scheduled to execute. */
303         portRESTORE_CONTEXT
304
305         .text
306         .align  4
307 vPortStartFirstTask:
308
309         portRESTORE_CONTEXT
310
311
312
313 #if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
314
315         .text
316         .align 4
317 vPortExceptionHandlerEntry:
318
319         /* Take a copy of the stack pointer before vPortExecptionHandler is called,
320         storing its value prior to the function stack frame being created. */
321         swi r1, r0, pulStackPointerOnFunctionEntry
322         bralid r15, vPortExceptionHandler
323         or r0, r0, r0
324
325 #endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */
326
327
328