xref: /nrf52832-nimble/rt-thread/libcpu/arc/em/contex_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
1/*
2 * Copyright (c) 2018, Synopsys, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6#define __ASSEMBLY__
7#include "inc/arc/arc.h"
8#include "inc/arc/arc_asm_common.h"
9
10.global rt_interrupt_enter; .type rt_interrupt_enter, %function
11.global rt_interrupt_leave; .type rt_interrupt_leave, %function
12.global context_switch_reqflg; .type context_switch_reqflg, %object
13.global rt_interrupt_from_thread; .type rt_interrupt_from_thread, %object
14.global rt_interrupt_to_thread; .type rt_interrupt_to_thread, %object
15
16	.text
17	.align 4
18dispatcher:
19	st sp, [r0]
20	ld sp, [r1]
21	pop r0
22	j [r0]
23
24/* return routine when task dispatch happened in task context */
25dispatch_r:
26	RESTORE_NONSCRATCH_REGS
27	j	[blink]
28
29/*
30 * rt_base_t rt_hw_interrupt_disable();
31 */
32.global rt_hw_interrupt_disable
33.type rt_hw_interrupt_disable, %function
34rt_hw_interrupt_disable:
35 	clri r0
36 	j [blink]
37
38
39/*
40 * void rt_hw_interrupt_enable(rt_base_t level);
41 */
42.global rt_hw_interrupt_enable
43.type rt_hw_interrupt_enable, %function
44rt_hw_interrupt_enable:
45	seti r0
46	j [blink]
47
48
49.global rt_hw_context_switch_interrupt
50.type rt_hw_context_switch_interrupt, %function
51rt_hw_context_switch_interrupt:
52	st r0, [rt_interrupt_from_thread]
53	st r1, [rt_interrupt_to_thread]
54	mov r0, 1
55	st r0, [context_switch_reqflg]
56	j [blink]
57
58
59/*
60 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
61 * r0 --> from
62 * r1 --> to
63 */
64.global rt_hw_context_switch
65.type rt_hw_context_switch, %function
66rt_hw_context_switch:
67	SAVE_NONSCRATCH_REGS
68	mov r2, dispatch_r
69	push r2
70	b dispatcher
71
72
73/*
74 * void rt_hw_context_switch_to(rt_uint32 to);
75 * r0 --> to
76 */
77.global rt_hw_context_switch_to
78.type rt_hw_context_switch_to, %function
79rt_hw_context_switch_to:
80	ld sp, [r0]
81	pop r0
82	j [r0]
83
84.global start_r
85.type start_r, %function
86start_r:
87	pop blink;
88	pop r1
89	pop r2
90	pop r0
91
92	j_s.d [r1]
93	kflag r2
94
95/****** exceptions and interrupts handing ******/
96/****** entry for exception handling ******/
97	.global exc_entry_cpu
98	.align 4
99exc_entry_cpu:
100
101	EXCEPTION_PROLOGUE
102
103	mov	blink,	sp
104	mov	r3, sp		/* as exception handler's para(p_excinfo) */
105
106	ld	r0, [exc_nest_count]
107	add	r1, r0, 1
108	st	r1, [exc_nest_count]
109	cmp	r0, 0
110	bne	exc_handler_1
111/* change to exception stack if interrupt happened in task context */
112	mov	sp, _e_stack
113exc_handler_1:
114	PUSH	blink
115
116	lr	r0, [AUX_ECR]
117	lsr	r0, r0, 16
118	mov	r1, exc_int_handler_table
119	ld.as	r2, [r1, r0]
120
121	mov	r0, r3
122	jl	[r2]
123
124/* interrupts are not allowed */
125ret_exc:
126	POP	sp
127	mov	r1, exc_nest_count
128	ld	r0, [r1]
129	sub	r0, r0, 1
130	cmp	r0, 0
131	bne.d	ret_exc_1
132	st	r0, [r1]
133
134	ld	r0, [context_switch_reqflg]
135	cmp	r0, 0
136	bne	ret_exc_2
137ret_exc_1:	/* return from non-task context, interrupts or exceptions are nested */
138	EXCEPTION_EPILOGUE
139	rtie
140
141/* there is a dispatch request */
142ret_exc_2:
143	/* clear dispatch request */
144	mov	r0, 0
145	st	r0, [context_switch_reqflg]
146
147	SAVE_CALLEE_REGS	/* save callee save registers */
148
149	/* clear exception bit to do exception exit by SW */
150	lr	r0, [AUX_STATUS32]
151	bclr	r0, r0, AUX_STATUS_BIT_AE
152	kflag	r0
153
154	mov	r1, ret_exc_r	/* save return address */
155	PUSH	r1
156
157	ld 	r0, [rt_interrupt_from_thread]
158	ld 	r1, [rt_interrupt_to_thread]
159	b	dispatcher
160
161ret_exc_r:
162	/* recover exception status */
163	lr	r0, [AUX_STATUS32]
164	bset	r0, r0, AUX_STATUS_BIT_AE
165	kflag	r0
166
167	RESTORE_CALLEE_REGS
168	EXCEPTION_EPILOGUE
169	rtie
170
171/****** entry for normal interrupt exception handling ******/
172	.global exc_entry_int	/* entry for interrupt handling */
173	.align 4
174exc_entry_int:
175#if ARC_FEATURE_FIRQ == 1
176/*  check whether it is P0 interrupt */
177#if ARC_FEATURE_RGF_NUM_BANKS > 1
178	lr	r0, [AUX_IRQ_ACT]
179	btst	r0, 0
180	jnz	exc_entry_firq
181#else
182	PUSH	r10
183	lr	r10, [AUX_IRQ_ACT]
184	btst	r10, 0
185	POP	r10
186	jnz	exc_entry_firq
187#endif
188#endif
189	INTERRUPT_PROLOGUE
190
191	mov	blink, sp
192
193	clri	/* disable interrupt */
194	ld	r3, [exc_nest_count]
195	add	r2, r3, 1
196	st	r2, [exc_nest_count]
197	seti	/* enable higher priority interrupt */
198
199	cmp	r3, 0
200	bne	irq_handler_1
201/* change to exception stack if interrupt happened in task context */
202	mov	sp, _e_stack
203irq_handler_1:
204	PUSH	blink
205
206	jl 	rt_interrupt_enter
207
208	lr	r0, [AUX_IRQ_CAUSE]
209	sr	r0, [AUX_IRQ_SELECT]
210	mov	r1, exc_int_handler_table
211	ld.as	r2, [r1, r0]	/* r2 = exc_int_handler_table + irqno *4 */
212/* handle software triggered interrupt */
213	lr	r3, [AUX_IRQ_HINT]
214	cmp	r3, r0
215	bne.d irq_hint_handled
216	xor	r3, r3, r3
217	sr	r3, [AUX_IRQ_HINT]
218irq_hint_handled:
219	lr	r3, [AUX_IRQ_PRIORITY]
220	PUSH	r3		/* save irq priority */
221
222	jl	[r2]		/* jump to interrupt handler */
223	jl	rt_interrupt_leave
224ret_int:
225	clri			/* disable interrupt */
226	POP	r3		/* irq priority */
227	POP	sp
228	mov	r1, exc_nest_count
229	ld	r0, [r1]
230	sub	r0, r0, 1
231	cmp	r0, 0
232	bne.d	ret_int_1
233	st	r0, [r1]
234
235	ld	r0, [context_switch_reqflg]
236	cmp	r0, 0
237	bne	ret_int_2
238ret_int_1:	/* return from non-task context */
239	INTERRUPT_EPILOGUE
240	rtie
241/* there is a dispatch request */
242ret_int_2:
243	/* clear dispatch request */
244	mov	r0, 0
245	st	r0, [context_switch_reqflg]
246
247	/* interrupt return by SW */
248	lr	r10, [AUX_IRQ_ACT]
249	PUSH	r10
250	bclr	r10, r10, r3	/* clear related bits in IRQ_ACT */
251	sr	r10, [AUX_IRQ_ACT]
252
253	SAVE_CALLEE_REGS	/* save callee save registers */
254	mov	r1, ret_int_r	/* save return address */
255	PUSH	r1
256
257	ld 	r0, [rt_interrupt_from_thread]
258	ld 	r1, [rt_interrupt_to_thread]
259	b	dispatcher
260
261ret_int_r:
262	RESTORE_CALLEE_REGS
263	/* recover AUX_IRQ_ACT to restore the interrup status */
264	POPAX	AUX_IRQ_ACT
265	INTERRUPT_EPILOGUE
266	rtie