]> begriffs open source - freertos/blob - portable/ThirdParty/GCC/ARC_v1/arc_support.s
SMP version (#401)
[freertos] / portable / ThirdParty / GCC / ARC_v1 / arc_support.s
1 /*
2  * FreeRTOS Kernel V202110.00
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         lr r0, [AUX_STATUS32]
105         bclr r0, r0, AUX_STATUS_BIT_SC
106         flag r0
107         jl      vPortSetStackCheck
108         lr r0, [AUX_STATUS32]
109         bset r0, r0, AUX_STATUS_BIT_SC
110         flag r0
111 #endif
112         POP     r0              /* get critical nesting */
113         st      r0, [ulCriticalNesting]
114         POP     r0              /* get return address  */
115         j       [r0]
116
117 /*
118  *  task startup routine
119  *
120  */
121         .text
122         .global start_r
123         .align 4
124 start_r:
125         seti    /* unlock cpu */
126         mov     blink, vPortEndTask     /* set return address */
127         POP     r1                      /* get task function body */
128         POP     r0                      /* get task parameters */
129         j       [r1]
130
131 /****** exceptions and interrupts handing ******/
132 /****** entry for exception handling ******/
133         .global exc_entry_cpu
134         .align 4
135 exc_entry_cpu:
136
137         EXCEPTION_PROLOGUE
138
139
140         mov     blink,  sp
141         mov     r3, sp          /* as exception handler's para(p_excinfo) */
142
143         ld      r1, [exc_nest_count]
144         add     r1, r1, 1
145         st      r1, [exc_nest_count]
146         brne    r1, 0, exc_handler_1
147 /* change to exception stack if interrupt happened in task context */
148         mov     sp, _e_stack
149 exc_handler_1:
150         PUSH    blink
151
152 /* find the exception cause */
153 #if ARC_FEATURE_CORE_700
154         lr      r0, [AUX_ECR]
155         lsr     r0, r0, 16
156         bmsk    r0, r0, 7
157 #endif
158         mov     r1, exc_int_handler_table
159         ld.as   r2, [r1, r0]
160
161         mov     r0, r3
162         jl      [r2]            /* !!!!jump to exception handler where interrupts are not allowed! */
163
164 /* interrupts are not allowed */
165 ret_exc:
166         POP     sp
167         mov     r1, exc_nest_count
168         ld      r0, [r1]
169         sub     r0, r0, 1
170         st      r0, [r1]
171         brne    r0, 0, ret_exc_1  /* nested exception case */
172         lr      r1, [AUX_IRQ_LV12]
173         brne    r1, 0, ret_exc_1  /* nested or pending interrupt case */
174
175         ld      r0, [context_switch_reqflg]
176         brne    r0, 0, ret_exc_2
177 ret_exc_1:      /* return from non-task context, interrupts or exceptions are nested */
178
179         EXCEPTION_EPILOGUE
180 #if ARC_FEATURE_CORE_600
181         rtie ilink2
182 #else
183         rtie
184 #endif
185
186 /* there is a dispatch request */
187 ret_exc_2:
188         /* clear dispatch request */
189         mov     r0, 0
190         st      r0, [context_switch_reqflg]
191
192         ld      r0, [pxCurrentTCB]
193         breq    r0, 0, ret_exc_1
194
195         SAVE_CALLEE_REGS        /* save callee save registers */
196
197         lr      r0, [AUX_STATUS32]
198         bclr    r0, r0, AUX_STATUS_BIT_AE       /* clear exception bit */
199         flag    r0
200
201         mov     r1, ret_exc_r   /* save return address */
202         PUSH    r1
203
204         bl      dispatcher      /* r0->pxCurrentTCB */
205
206 ret_exc_r:
207         /* recover exception status */
208         lr      r0, [AUX_STATUS32]
209         bset    r0, r0, AUX_STATUS_BIT_AE
210         flag    r0
211
212         RESTORE_CALLEE_REGS     /* recover registers */
213         EXCEPTION_EPILOGUE
214 #if ARC_FEATURE_CORE_600
215         rtie ilink2
216 #else
217         rtie
218 #endif
219
220 /****** entry for normal interrupt exception handling ******/
221         .global exc_entry_int   /* entry for interrupt handling */
222         .align 4
223 exc_entry_int:
224
225         INTERRUPT_PROLOGUE
226
227         mov     blink, sp
228
229         /* disable interrupt */
230         push r0
231         lr  r0, [AUX_STATUS32]
232         push r0
233     bclr r0, r0, AUX_STATUS_BIT_E1
234     bclr r0, r0, AUX_STATUS_BIT_E2
235     flag r0
236         ld      r3, [exc_nest_count]
237         add     r2, r3, 1
238         st      r2, [exc_nest_count]
239         /* enable interrupt */
240         pop r0
241         flag r0
242         pop r0
243
244         brne    r3, 0, irq_handler_1
245 /* change to exception stack if interrupt happened in task context */
246         mov     sp, _e_stack
247 #if ARC_FEATURE_STACK_CHECK
248         lr r0, [AUX_STATUS32]
249         bclr r0, r0, AUX_STATUS_BIT_SC
250         flag r0
251 #endif
252 irq_handler_1:
253         PUSH    blink
254
255 /* critical area */
256 #if ARC_FEATURE_CORE_700
257         lr      r0, [AUX_IRQ_CAUSE1]
258 #endif
259         mov     r1, exc_int_handler_table
260         ld.as   r2, [r1, r0]    /* r2 = exc_int_handler_table + irqno *4 */
261 /* handle software triggered interrupt */
262         lr      r3, [AUX_IRQ_HINT]
263         cmp     r3, r0
264         bne.d irq_hint_handled
265         xor     r3, r3, r3
266         sr      r3, [AUX_IRQ_HINT]
267 irq_hint_handled:
268
269         jl      [r2]            /* jump to interrupt handler */
270 /* no interrupts are allowed from here */
271 ret_int:
272         clri    /* disable interrupt */
273
274         POP     sp
275         mov     r1, exc_nest_count
276         ld      r0, [r1]
277         sub     r0, r0, 1
278         st      r0, [r1]
279 /* if there are multi-bits set in IRQ_LV12, it's still in nest interrupt */
280         lr      r1, [AUX_IRQ_LV12]
281
282         ld      r0, [context_switch_reqflg]
283         brne    r0, 0, ret_int_2
284 ret_int_1:      /* return from non-task context */
285         INTERRUPT_EPILOGUE
286 #if ARC_FEATURE_CORE_600
287 /* TODO: series 600 IRQ6 and IRQ7 uses ilink2 */
288         rtie ilink1
289 #else
290         rtie
291 #endif
292 /* there is a dispatch request */
293 ret_int_2:
294         /* clear dispatch request */
295         mov     r0, 0
296         st      r0, [context_switch_reqflg]
297
298         ld      r0, [pxCurrentTCB]
299         breq    r0, 0, ret_int_1
300
301 /* r1 has old AUX_IRQ_LV12 */
302         PUSH    r1
303 /* clear related bits in IRQ_ACT manually to simulate a irq return  */
304
305         SAVE_CALLEE_REGS        /* save callee save registers */
306         mov     r1, ret_int_r   /* save return address */
307         PUSH    r1
308
309         bl      dispatcher      /* r0->pxCurrentTCB */
310
311 ret_int_r:
312         RESTORE_CALLEE_REGS     /* recover registers */
313         POPAX   AUX_IRQ_LV12
314         INTERRUPT_EPILOGUE
315 #if ARC_FEATURE_CORE_600
316         rtie ilink1
317 #else
318         rtie
319 #endif
320
321 /** @endcond */