]> begriffs open source - freertos/blob - portable/ThirdParty/GCC/ARC_EM_HS/arc_support.s
Update History.txt and fix versioning in asm files (#177)
[freertos] / portable / ThirdParty / GCC / ARC_EM_HS / arc_support.s
1 /*
2  * FreeRTOS Kernel V10.4.1
3  * Copyright (C) 2020 Synopsys, 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 /**
29  * \file
30  * \ingroup OS_FREERTOS
31  * \brief  freertos support for arc processor
32  *      like task dispatcher, interrupt handler
33  */
34 /** @cond OS_FREERTOS_ASM_ARC_SUPPORT */
35
36 /*
37  * core-dependent part in assemble language (for arc)
38  */
39 #define __ASSEMBLY__
40 #include "arc/arc.h"
41 #include "arc/arc_asm_common.h"
42
43 /*
44  *  task dispatcher
45  *
46  */
47         .text
48         .align 4
49         .global dispatch
50 dispatch:
51 /*
52  *  the pre-conditions of this routine are task context, CPU is
53  *  locked, dispatch is enabled.
54  */
55         SAVE_NONSCRATCH_REGS            /* save callee save registers */
56         mov     r1, dispatch_r
57         PUSH    r1                      /* save return address */
58         ld      r0, [pxCurrentTCB]
59         bl      dispatcher
60
61 /* return routine when task dispatch happened in task context */
62 dispatch_r:
63         RESTORE_NONSCRATCH_REGS         /* recover registers */
64         j       [blink]
65
66 /*
67  *  start dispatch
68  */
69         .global start_dispatch
70         .align 4
71 start_dispatch:
72 /*
73  *  this routine is called in the non-task context during the startup of the kernel
74  *  , and all the interrupts are locked.
75  *
76  *  when the dispatcher is called, the cpu is locked, no nest exception (CPU exception/interrupt).
77  *  In target_initialize, all interrupt priority mask should be cleared, cpu should be
78  *  locked, the interrupts outside the kernel such as fiq can be
79  *  enabled.
80  */
81         clri
82         mov     r0, 0
83         st      r0, [exc_nest_count]
84         b       dispatcher_0
85 /*
86  *  dispatcher
87  */
88 dispatcher:
89         ld      r1, [ulCriticalNesting]
90         PUSH    r1                      /* save critical nesting */
91         st      sp, [r0]                /* save stack pointer of current task, r0->pxCurrentTCB */
92         jl      vTaskSwitchContext      /* change the value of pxCurrentTCB */
93 /*
94  *  before dispatcher is called, task context | cpu locked | dispatch enabled
95  *  should be satisfied. In this routine, the processor will jump
96  *  into the entry of next to run task
97  *
98  *  i.e. kernel mode, IRQ disabled, dispatch enabled
99  */
100 dispatcher_0:
101         ld      r1, [pxCurrentTCB]
102         ld      sp, [r1]        /* recover task stack */
103 #if ARC_FEATURE_STACK_CHECK
104 #if ARC_FEATURE_SEC_PRESENT
105         lr r0, [AUX_SEC_STAT]
106         bclr r0, r0, AUX_SEC_STAT_BIT_SSC
107         sflag r0
108 #else
109         lr r0, [AUX_STATUS32]
110         bclr r0, r0, AUX_STATUS_BIT_SC
111         kflag r0
112 #endif
113         jl      vPortSetStackCheck
114 #if ARC_FEATURE_SEC_PRESENT
115         lr r0, [AUX_SEC_STAT]
116         bset r0, r0, AUX_SEC_STAT_BIT_SSC
117         sflag r0
118 #else
119         lr r0, [AUX_STATUS32]
120         bset r0, r0, AUX_STATUS_BIT_SC
121         kflag r0
122 #endif
123 #endif
124         POP     r0              /* get critical nesting */
125         st      r0, [ulCriticalNesting]
126         POP     r0              /* get return address  */
127         j       [r0]
128
129 /*
130  *  task startup routine
131  *
132  */
133         .text
134         .global start_r
135         .align 4
136 start_r:
137         seti    /* unlock cpu */
138         mov     blink, vPortEndTask     /* set return address */
139         POP     r1                      /* get task function body */
140         POP     r0                      /* get task parameters */
141         j       [r1]
142
143 /****** exceptions and interrupts handing ******/
144 /****** entry for exception handling ******/
145         .global exc_entry_cpu
146         .align 4
147 exc_entry_cpu:
148
149         EXCEPTION_PROLOGUE
150
151         mov     blink,  sp
152         mov     r3, sp          /* as exception handler's para(p_excinfo) */
153
154         ld      r0, [exc_nest_count]
155         add     r1, r0, 1
156         st      r1, [exc_nest_count]
157         brne    r0, 0, exc_handler_1
158 /* change to exception stack if interrupt happened in task context */
159         mov     sp, _e_stack
160 exc_handler_1:
161         PUSH    blink
162
163         lr      r0, [AUX_ECR]
164         lsr     r0, r0, 16
165         mov     r1, exc_int_handler_table
166         ld.as   r2, [r1, r0]
167
168         mov     r0, r3
169         jl      [r2]            /* !!!!jump to exception handler where interrupts are not allowed! */
170
171 /* interrupts are not allowed */
172 ret_exc:
173         POP     sp
174         mov     r1, exc_nest_count
175         ld      r0, [r1]
176         sub     r0, r0, 1
177         st      r0, [r1]
178         brne    r0, 0, ret_exc_1 /* nest exception case */
179         lr      r1, [AUX_IRQ_ACT] /* nest interrupt case */
180         brne    r1, 0, ret_exc_1
181
182         ld      r0, [context_switch_reqflg]
183         brne    r0, 0, ret_exc_2
184 ret_exc_1:      /* return from non-task context, interrupts or exceptions are nested */
185
186         EXCEPTION_EPILOGUE
187         rtie
188
189 /* there is a dispatch request */
190 ret_exc_2:
191         /* clear dispatch request */
192         mov     r0, 0
193         st      r0, [context_switch_reqflg]
194
195         ld      r0, [pxCurrentTCB]
196         breq    r0, 0, ret_exc_1
197
198         SAVE_CALLEE_REGS        /* save callee save registers */
199
200         lr      r0, [AUX_STATUS32]
201         bclr    r0, r0, AUX_STATUS_BIT_AE       /* clear exception bit */
202         kflag   r0
203
204         mov     r1, ret_exc_r   /* save return address */
205         PUSH    r1
206
207         bl      dispatcher      /* r0->pxCurrentTCB */
208
209 ret_exc_r:
210         /* recover exception status */
211         lr      r0, [AUX_STATUS32]
212         bset    r0, r0, AUX_STATUS_BIT_AE
213         kflag   r0
214
215         RESTORE_CALLEE_REGS     /* recover registers */
216         EXCEPTION_EPILOGUE
217         rtie
218
219 /****** entry for normal interrupt exception handling ******/
220         .global exc_entry_int   /* entry for interrupt handling */
221         .align 4
222 exc_entry_int:
223 #if ARC_FEATURE_FIRQ == 1
224 #if ARC_FEATURE_RGF_NUM_BANKS > 1
225         lr      r0, [AUX_IRQ_ACT]                       /*  check whether it is P0 interrupt */
226         btst    r0, 0
227         jnz     exc_entry_firq
228 #else
229         PUSH    r10
230         lr      r10, [AUX_IRQ_ACT]
231         btst    r10, 0
232         POP     r10
233         jnz     exc_entry_firq
234 #endif
235 #endif
236         INTERRUPT_PROLOGUE
237
238         mov     blink, sp
239
240         clri    /* disable interrupt */
241         ld      r3, [exc_nest_count]
242         add     r2, r3, 1
243         st      r2, [exc_nest_count]
244         seti    /* enable higher priority interrupt */
245
246         brne    r3, 0, irq_handler_1
247 /* change to exception stack if interrupt happened in task context */
248         mov     sp, _e_stack
249 #if ARC_FEATURE_STACK_CHECK
250 #if ARC_FEATURE_SEC_PRESENT
251         lr r0, [AUX_SEC_STAT]
252         bclr r0, r0, AUX_SEC_STAT_BIT_SSC
253         sflag r0
254 #else
255         lr r0, [AUX_STATUS32]
256         bclr r0, r0, AUX_STATUS_BIT_SC
257         kflag r0
258 #endif
259 #endif
260 irq_handler_1:
261         PUSH    blink
262
263         lr      r0, [AUX_IRQ_CAUSE]
264         mov     r1, exc_int_handler_table
265         ld.as   r2, [r1, r0]    /* r2 = exc_int_handler_table + irqno *4 */
266 /* handle software triggered interrupt */
267         lr      r3, [AUX_IRQ_HINT]
268         cmp     r3, r0
269         bne.d irq_hint_handled
270         xor     r3, r3, r3
271         sr      r3, [AUX_IRQ_HINT]
272 irq_hint_handled:
273
274         jl      [r2]            /* jump to interrupt handler */
275 /* no interrupts are allowed from here */
276 ret_int:
277         clri    /* disable interrupt */
278
279         POP     sp
280         mov     r1, exc_nest_count
281         ld      r0, [r1]
282         sub     r0, r0, 1
283         st      r0, [r1]
284 /* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */
285         lr      r0, [AUX_IRQ_CAUSE]
286         sr      r0, [AUX_IRQ_SELECT]
287         lr      r3, [AUX_IRQ_PRIORITY]
288         lr      r1, [AUX_IRQ_ACT]
289         bclr    r2, r1, r3
290         brne    r2, 0, ret_int_1
291
292         ld      r0, [context_switch_reqflg]
293         brne    r0, 0, ret_int_2
294 ret_int_1:      /* return from non-task context */
295         INTERRUPT_EPILOGUE
296         rtie
297 /* there is a dispatch request */
298 ret_int_2:
299         /* clear dispatch request */
300         mov     r0, 0
301         st      r0, [context_switch_reqflg]
302
303         ld      r0, [pxCurrentTCB]
304         breq    r0, 0, ret_int_1
305
306 /* r1 has old AUX_IRQ_ACT */
307         PUSH    r1
308 /* clear related bits in IRQ_ACT manually to simulate a irq return  */
309         sr      r2, [AUX_IRQ_ACT]
310
311         SAVE_CALLEE_REGS        /* save callee save registers */
312         mov     r1, ret_int_r   /* save return address */
313         PUSH    r1
314
315         bl      dispatcher      /* r0->pxCurrentTCB */
316
317 ret_int_r:
318         RESTORE_CALLEE_REGS     /* recover registers */
319         POPAX   AUX_IRQ_ACT
320         INTERRUPT_EPILOGUE
321         rtie
322
323 #if ARC_FEATURE_FIRQ == 1
324         .global exc_entry_firq
325         .align 4
326 exc_entry_firq:
327 #if ARC_FEATURE_STACK_CHECK && ARC_FEATURE_RGF_NUM_BANKS > 1
328 #if ARC_FEATURE_SEC_PRESENT
329         lr r0, [AUX_SEC_STAT]
330         bclr r0, r0, AUX_SEC_STAT_BIT_SSC
331         sflag r0
332 #else
333         lr r0, [AUX_STATUS32]
334         bclr r0, r0, AUX_STATUS_BIT_SC
335         kflag r0
336 #endif
337 #endif
338         SAVE_FIQ_EXC_REGS
339
340         mov     blink, sp
341
342         ld      r3, [exc_nest_count]
343         add     r2, r3, 1
344         st      r2, [exc_nest_count]
345
346         brne    r3, 0, firq_handler_1
347 #if ARC_FEATURE_STACK_CHECK && ARC_FEATURE_RGF_NUM_BANKS == 1
348 #if ARC_FEATURE_SEC_PRESENT
349         lr r0, [AUX_SEC_STAT]
350         bclr r0, r0, AUX_SEC_STAT_BIT_SSC
351         sflag r0
352 #else
353         lr r0, [AUX_STATUS32]
354         bclr r0, r0, AUX_STATUS_BIT_SC
355         kflag r0
356 #endif
357 #endif
358 /* change to exception stack if interrupt happened in task context */
359         mov     sp, _e_stack
360 firq_handler_1:
361         PUSH    blink
362
363         lr      r0, [AUX_IRQ_CAUSE]
364         mov     r1, exc_int_handler_table
365         ld.as   r2, [r1, r0]    /* r2 = exc_int_handler_table + irqno *4 */
366 /* handle software triggered interrupt */
367         lr      r3, [AUX_IRQ_HINT]
368         brne    r3, r0, firq_hint_handled
369         xor     r3, r3, r3
370         sr      r3, [AUX_IRQ_HINT]
371 firq_hint_handled:
372
373         jl      [r2]            /* jump to interrupt handler */
374 /* no interrupts are allowed from here */
375 ret_firq:
376         clri
377         POP     sp
378
379         mov     r1, exc_nest_count
380         ld      r0, [r1]
381         sub     r0, r0, 1
382         st      r0, [r1]
383 /* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */
384         lr      r1, [AUX_IRQ_ACT]
385         bclr    r1, r1, 0
386         brne    r1, 0, ret_firq_1
387
388         ld      r0, [context_switch_reqflg]
389         brne    r0, 0, ret_firq_2
390 ret_firq_1:     /* return from non-task context */
391         RESTORE_FIQ_EXC_REGS
392         rtie
393 /* there is a dispatch request */
394 ret_firq_2:
395         /* clear dispatch request */
396         mov     r0, 0
397         st      r0, [context_switch_reqflg]
398
399         ld      r0, [pxCurrentTCB]
400         breq    r0, 0, ret_firq_1
401
402 /* reconstruct the interruptted context
403  * When ARC_FEATURE_RGF_BANKED_REGS >= 16 (16, 32), sp is banked
404  * so need to restore the fast irq stack.
405  */
406 #if ARC_FEATURE_RGF_BANKED_REGS >= 16
407         RESTORE_LP_REGS
408 #if ARC_FEATURE_CODE_DENSITY
409         RESTORE_CODE_DENSITY
410 #endif
411         RESTORE_R58_R59
412 #endif
413
414 /* when BANKED_REGS == 16, r4-r9 wiil be also saved in fast irq stack
415  * so pop them out
416  */
417 #if  ARC_FEATURE_RGF_BANKED_REGS == 16 && !defined(ARC_FEATURE_RF16)
418         POP             r9
419         POP             r8
420         POP             r7
421         POP             r6
422         POP             r5
423         POP             r4
424 #endif
425
426 /* for other cases, unbanked regs are already in interrupted context's stack,
427  * so just need to save and pop the banked regs
428  */
429
430 /* save the interruptted context */
431 #if ARC_FEATURE_RGF_BANKED_REGS > 0
432 /* switch back to bank0  */
433         lr r0, [AUX_STATUS32]
434         bic     r0, r0, 0x70000
435         kflag   r0
436 #endif
437
438 #if ARC_FEATURE_RGF_BANKED_REGS == 4
439 /* r4 - r12, gp, fp, r30, blink already saved */
440         PUSH    r0
441         PUSH    r1
442         PUSH    r2
443         PUSH    r3
444 #elif ARC_FEATURE_RGF_BANKED_REGS == 8
445 /* r4 - r9, r0, r11 gp, fp, r30, blink already saved */
446         PUSH    r0
447         PUSH    r1
448         PUSH    r2
449         PUSH    r3
450         PUSH    r12
451 #elif ARC_FEATURE_RGF_BANKED_REGS >= 16
452 /* nothing is saved, */
453         SAVE_R0_TO_R12
454
455         SAVE_R58_R59
456         PUSH    gp
457         PUSH    fp
458         PUSH    r30             /* general purpose */
459         PUSH    blink
460
461 #if ARC_FEATURE_CODE_DENSITY
462         SAVE_CODE_DENSITY
463 #endif
464         SAVE_LP_REGS
465 #endif
466         PUSH    ilink
467         lr      r0, [AUX_STATUS32_P0]
468         PUSH    r0
469         lr      r0, [AUX_IRQ_ACT]
470         PUSH    r0
471         bclr    r0, r0, 0
472         sr      r0, [AUX_IRQ_ACT]
473
474         SAVE_CALLEE_REGS        /* save callee save registers */
475
476         mov     r1, ret_firq_r  /* save return address */
477         PUSH    r1
478         ld      r0, [pxCurrentTCB]
479         bl      dispatcher      /* r0->pxCurrentTCB */
480
481 ret_firq_r:
482         RESTORE_CALLEE_REGS     /* recover registers */
483         POPAX   AUX_IRQ_ACT
484         POPAX   AUX_STATUS32_P0
485         POP     ilink
486
487 #if ARC_FEATURE_RGF_NUM_BANKS > 1
488 #if ARC_FEATURE_RGF_BANKED_REGS == 4
489 /* r4 - r12, gp, fp, r30, blink already saved */
490         POP     r3
491         POP     r2
492         POP     r1
493         POP     r0
494         RESTORE_FIQ_EXC_REGS
495 #elif ARC_FEATURE_RGF_BANKED_REGS == 8
496 /* r4 - r9, gp, fp, r30, blink already saved */
497         POP     r12
498         POP     r3
499         POP     r2
500         POP     r1
501         POP     r0
502         RESTORE_FIQ_EXC_REGS
503 #elif ARC_FEATURE_RGF_BANKED_REGS >= 16
504         RESTORE_LP_REGS
505 #if ARC_FEATURE_CODE_DENSITY
506         RESTORE_CODE_DENSITY
507 #endif
508         POP     blink
509         POP     r30
510         POP     fp
511         POP     gp
512
513         RESTORE_R58_R59
514         RESTORE_R0_TO_R12
515 #endif /* ARC_FEATURE_RGF_BANKED_REGS  */
516 #else
517         RESTORE_FIQ_EXC_REGS
518 #endif /* ARC_FEATURE_RGF_NUM_BANKS */
519         rtie
520 #endif
521 /** @endcond */