]> begriffs open source - freertos/blob - portable/GCC/MicroBlazeV9/portasm.S
FreeRTOS MPU: Remove MPU region number check (#1261)
[freertos] / portable / GCC / MicroBlazeV9 / portasm.S
1 /*
2  * FreeRTOS Kernel <DEVELOPMENT BRANCH>
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 #include "microblaze_instructions.h"
37 /* The context is oversized to allow functions called from the ISR to write
38 back into the caller stack. */
39 #if defined (__arch64__)
40 #if( XPAR_MICROBLAZE_USE_FPU != 0 )
41         #define portCONTEXT_SIZE 272
42         #define portMINUS_CONTEXT_SIZE -272
43 #else
44         #define portCONTEXT_SIZE 264
45         #define portMINUS_CONTEXT_SIZE -264
46 #endif
47 #else
48 #if( XPAR_MICROBLAZE_USE_FPU != 0 )
49         #define portCONTEXT_SIZE 136
50         #define portMINUS_CONTEXT_SIZE -136
51 #else
52         #define portCONTEXT_SIZE 132
53         #define portMINUS_CONTEXT_SIZE -132
54 #endif
55 #endif
56
57 /* Offsets from the stack pointer at which saved registers are placed. */
58 #if defined (__arch64__)
59 #define portR31_OFFSET  8
60 #define portR30_OFFSET  16
61 #define portR29_OFFSET  24
62 #define portR28_OFFSET  32
63 #define portR27_OFFSET  40
64 #define portR26_OFFSET  48
65 #define portR25_OFFSET  56
66 #define portR24_OFFSET  64
67 #define portR23_OFFSET  72
68 #define portR22_OFFSET  80
69 #define portR21_OFFSET  88
70 #define portR20_OFFSET  96
71 #define portR19_OFFSET  104
72 #define portR18_OFFSET  112
73 #define portR17_OFFSET  120
74 #define portR16_OFFSET  128
75 #define portR15_OFFSET  136
76 #define portR14_OFFSET  144
77 #define portR13_OFFSET  152
78 #define portR12_OFFSET  160
79 #define portR11_OFFSET  168
80 #define portR10_OFFSET  176
81 #define portR9_OFFSET   184
82 #define portR8_OFFSET   192
83 #define portR7_OFFSET   200
84 #define portR6_OFFSET   208
85 #define portR5_OFFSET   216
86 #define portR4_OFFSET   224
87 #define portR3_OFFSET   232
88 #define portR2_OFFSET   240
89 #define portCRITICAL_NESTING_OFFSET 248
90 #define portMSR_OFFSET 256
91 #define portFSR_OFFSET 264
92 #else
93 #define portR31_OFFSET  4
94 #define portR30_OFFSET  8
95 #define portR29_OFFSET  12
96 #define portR28_OFFSET  16
97 #define portR27_OFFSET  20
98 #define portR26_OFFSET  24
99 #define portR25_OFFSET  28
100 #define portR24_OFFSET  32
101 #define portR23_OFFSET  36
102 #define portR22_OFFSET  40
103 #define portR21_OFFSET  44
104 #define portR20_OFFSET  48
105 #define portR19_OFFSET  52
106 #define portR18_OFFSET  56
107 #define portR17_OFFSET  60
108 #define portR16_OFFSET  64
109 #define portR15_OFFSET  68
110 #define portR14_OFFSET  72
111 #define portR13_OFFSET  76
112 #define portR12_OFFSET  80
113 #define portR11_OFFSET  84
114 #define portR10_OFFSET  88
115 #define portR9_OFFSET   92
116 #define portR8_OFFSET   96
117 #define portR7_OFFSET   100
118 #define portR6_OFFSET   104
119 #define portR5_OFFSET   108
120 #define portR4_OFFSET   112
121 #define portR3_OFFSET   116
122 #define portR2_OFFSET   120
123 #define portCRITICAL_NESTING_OFFSET 124
124 #define portMSR_OFFSET 128
125 #define portFSR_OFFSET 132
126
127 #endif
128
129     .extern pxCurrentTCB
130     .extern XIntc_DeviceInterruptHandler
131     .extern vTaskSwitchContext
132     .extern uxCriticalNesting
133     .extern pulISRStack
134     .extern ulTaskSwitchRequested
135     .extern vPortExceptionHandler
136     .extern pulStackPointerOnFunctionEntry
137
138     .global _interrupt_handler
139     .global VPortYieldASM
140     .global vPortStartFirstTask
141     .global vPortExceptionHandlerEntry
142
143
144 .macro portSAVE_CONTEXT
145
146         /* Make room for the context on the stack. */
147         ADDLIK r1, r1, portMINUS_CONTEXT_SIZE
148
149         /* Stack general registers. */
150         SI r31, r1, portR31_OFFSET
151         SI r30, r1, portR30_OFFSET
152         SI r29, r1, portR29_OFFSET
153         SI r28, r1, portR28_OFFSET
154         SI r27, r1, portR27_OFFSET
155         SI r26, r1, portR26_OFFSET
156         SI r25, r1, portR25_OFFSET
157         SI r24, r1, portR24_OFFSET
158         SI r23, r1, portR23_OFFSET
159         SI r22, r1, portR22_OFFSET
160         SI r21, r1, portR21_OFFSET
161         SI r20, r1, portR20_OFFSET
162         SI r19, r1, portR19_OFFSET
163         SI r18, r1, portR18_OFFSET
164         SI r17, r1, portR17_OFFSET
165         SI r16, r1, portR16_OFFSET
166         SI r15, r1, portR15_OFFSET
167         /* R14 is saved later as it needs adjustment if a yield is performed. */
168         SI r13, r1, portR13_OFFSET
169         SI r12, r1, portR12_OFFSET
170         SI r11, r1, portR11_OFFSET
171         SI r10, r1, portR10_OFFSET
172         SI r9, r1, portR9_OFFSET
173         SI r8, r1, portR8_OFFSET
174         SI r7, r1, portR7_OFFSET
175         SI r6, r1, portR6_OFFSET
176         SI r5, r1, portR5_OFFSET
177         SI r4, r1, portR4_OFFSET
178         SI r3, r1, portR3_OFFSET
179         SI r2, r1, portR2_OFFSET
180
181         /* Stack the critical section nesting value. */
182         LI r18, r0, uxCriticalNesting
183         SI r18, r1, portCRITICAL_NESTING_OFFSET
184
185         /* Stack MSR. */
186         mfs r18, rmsr
187         SI r18, r1, portMSR_OFFSET
188
189         #if( XPAR_MICROBLAZE_USE_FPU != 0 )
190                 /* Stack FSR. */
191                 mfs r18, rfsr
192                 SI r18, r1, portFSR_OFFSET
193         #endif
194
195 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
196     /* Save the stack limits */
197     mfs r18, rslr
198     swi r18, r1, portSLR_OFFSET
199     mfs r18, rshr
200     swi r18, r1, portSHR_OFFSET
201 #endif
202
203         /* Save the top of stack value to the TCB. */
204         LI r3, r0, pxCurrentTCB
205         STORE   r1, r0, r3
206
207     .endm
208
209 .macro portRESTORE_CONTEXT
210
211         /* Load the top of stack value from the TCB. */
212         LI r18, r0, pxCurrentTCB
213         LOAD    r1, r0, r18
214
215 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
216     /* Restore the stack limits -- must not load from r1 (Stack Pointer)
217     because if the address of load or store instruction is out of range,
218     it will trigger Stack Protection Violation exception. */
219     or  r18, r0, r1
220     lwi r12, r18, portSLR_OFFSET
221     mts rslr, r12
222     lwi r12, r18, portSHR_OFFSET
223     mts rshr, r12
224 #endif
225
226         /* Restore the general registers. */
227         LI r31, r1, portR31_OFFSET
228         LI r30, r1, portR30_OFFSET
229         LI r29, r1, portR29_OFFSET
230         LI r28, r1, portR28_OFFSET
231         LI r27, r1, portR27_OFFSET
232         LI r26, r1, portR26_OFFSET
233         LI r25, r1, portR25_OFFSET
234         LI r24, r1, portR24_OFFSET
235         LI r23, r1, portR23_OFFSET
236         LI r22, r1, portR22_OFFSET
237         LI r21, r1, portR21_OFFSET
238         LI r20, r1, portR20_OFFSET
239         LI r19, r1, portR19_OFFSET
240         LI r17, r1, portR17_OFFSET
241         LI r16, r1, portR16_OFFSET
242         LI r15, r1, portR15_OFFSET
243         LI r14, r1, portR14_OFFSET
244         LI r13, r1, portR13_OFFSET
245         LI r12, r1, portR12_OFFSET
246         LI r11, r1, portR11_OFFSET
247         LI r10, r1, portR10_OFFSET
248         LI r9, r1, portR9_OFFSET
249         LI r8, r1, portR8_OFFSET
250         LI r7, r1, portR7_OFFSET
251         LI r6, r1, portR6_OFFSET
252         LI r5, r1, portR5_OFFSET
253         LI r4, r1, portR4_OFFSET
254         LI r3, r1, portR3_OFFSET
255         LI r2, r1, portR2_OFFSET
256
257         /* Reload the rmsr from the stack. */
258         LI r18, r1, portMSR_OFFSET
259         mts rmsr, r18
260
261         #if( XPAR_MICROBLAZE_USE_FPU != 0 )
262                 /* Reload the FSR from the stack. */
263                 LI r18, r1, portFSR_OFFSET
264                 mts rfsr, r18
265         #endif
266
267         /* Load the critical nesting value. */
268         LI r18, r1, portCRITICAL_NESTING_OFFSET
269         SI r18, r0, uxCriticalNesting
270
271         /* Test the critical nesting value.  If it is non zero then the task last
272         exited the running state using a yield.  If it is zero, then the task
273         last exited the running state through an interrupt. */
274         XORI r18, r18, 0
275         BNEI r18, exit_from_yield
276
277         /* r18 was being used as a temporary.  Now restore its true value from the
278         stack. */
279         LI r18, r1, portR18_OFFSET
280
281         /* Remove the stack frame. */
282         ADDLIK r1, r1, portCONTEXT_SIZE
283
284         /* Return using rtid so interrupts are re-enabled as this function is
285         exited. */
286         rtid r14, 0
287         OR r0, r0, r0
288
289         .endm
290
291 /* This function is used to exit portRESTORE_CONTEXT() if the task being
292 returned to last left the Running state by calling taskYIELD() (rather than
293 being preempted by an interrupt). */
294         .text
295 #ifdef __arch64__
296         .align  8
297 #else
298         .align  4
299 #endif
300
301 exit_from_yield:
302
303         /* r18 was being used as a temporary.  Now restore its true value from the
304         stack. */
305         LI r18, r1, portR18_OFFSET
306
307         /* Remove the stack frame. */
308         ADDLIK r1, r1, portCONTEXT_SIZE
309
310         /* Return to the task. */
311         rtsd r14, 0
312         OR r0, r0, r0
313
314
315         .text
316
317 #ifdef __arch64__
318         .align  8
319 #else
320         .align  4
321 #endif
322
323 _interrupt_handler:
324
325     portSAVE_CONTEXT
326
327         /* Stack the return address. */
328         SI r14, r1, portR14_OFFSET
329
330         /* Switch to the ISR stack. */
331         LI r1, r0, pulISRStack
332
333 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
334     ori r18, r0, _stack_end
335     mts rslr, r18
336     ori r18, r0, _stack
337     mts rshr, r18
338 #endif
339
340         /* The parameter to the interrupt handler. */
341         ORI r5, r0, configINTERRUPT_CONTROLLER_TO_USE
342
343         /* Execute any pending interrupts. */
344         BRALID r15, XIntc_DeviceInterruptHandler
345         OR r0, r0, r0
346
347         /* See if a new task should be selected to execute. */
348         LI r18, r0, ulTaskSwitchRequested
349         OR r18, r18, r0
350
351         /* If ulTaskSwitchRequested is already zero, then jump straight to
352         restoring the task that is already in the Running state. */
353         BEQI r18, task_switch_not_requested
354
355         /* Set ulTaskSwitchRequested back to zero as a task switch is about to be
356         performed. */
357         SI r0, r0, ulTaskSwitchRequested
358
359         /* ulTaskSwitchRequested was not 0 when tested.  Select the next task to
360         execute. */
361         BRALID r15, vTaskSwitchContext
362         OR r0, r0, r0
363
364 task_switch_not_requested:
365
366     /* Restore the context of the next task scheduled to execute. */
367     portRESTORE_CONTEXT
368
369
370         .text
371 #ifdef __arch64__
372         .align  8
373 #else
374         .align  4
375 #endif
376
377 VPortYieldASM:
378
379     portSAVE_CONTEXT
380
381         /* Modify the return address so a return is done to the instruction after
382         the call to VPortYieldASM. */
383         ADDI r14, r14, 8
384         SI r14, r1, portR14_OFFSET
385
386         /* Switch to use the ISR stack. */
387         LI r1, r0, pulISRStack
388
389 #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
390     ori r18, r0, _stack_end
391     mts rslr, r18
392     ori r18, r0, _stack
393     mts rshr, r18
394 #endif
395
396         /* Select the next task to execute. */
397         BRALID r15, vTaskSwitchContext
398         OR r0, r0, r0
399
400     /* Restore the context of the next task scheduled to execute. */
401     portRESTORE_CONTEXT
402
403         .text
404 #ifdef __arch64__
405         .align  8
406 #else
407         .align  4
408 #endif
409
410 vPortStartFirstTask:
411
412     portRESTORE_CONTEXT
413
414
415
416 #if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 )
417
418         .text
419 #ifdef __arch64__
420         .align 8
421 #else
422         .align  4
423 #endif
424
425 vPortExceptionHandlerEntry:
426
427         /* Take a copy of the stack pointer before vPortExecptionHandler is called,
428         storing its value prior to the function stack frame being created. */
429         SI r1, r0, pulStackPointerOnFunctionEntry
430         BRALID r15, vPortExceptionHandler
431         OR r0, r0, r0
432
433 #endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */