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