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