xref: /nrf52832-nimble/rt-thread/libcpu/nios/nios_ii/context_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
1/*
2 * File      : context_gcc.S
3 * This file is part of RT-Thread RTOS
4 * COPYRIGHT (C) 2006-2011, RT-Thread Development Team
5 *
6 * The license and distribution terms for this file may be
7 * found in the file LICENSE in this distribution or at
8 * http://www.rt-thread.org/license/LICENSE
9 *
10 * Change Logs:
11 * Date           Author       Notes
12 * 2011-02-14     aozima       first implementation for Nios II.
13 * 2011-02-20     aozima       fix context&switch bug.
14 */
15
16/**
17 * @addtogroup NIOS_II
18 */
19/*@{*/
20
21.text
22
23.set noat
24
25/*
26 * rt_base_t rt_hw_interrupt_disable();
27 */
28.global rt_hw_interrupt_disable
29.type rt_hw_interrupt_disable, %function
30rt_hw_interrupt_disable:
31    rdctl r2, status       /* return status */
32    wrctl status, zero     /* disable interrupt */
33    ret
34
35/*
36 * void rt_hw_interrupt_enable(rt_base_t level);
37 */
38.global rt_hw_interrupt_enable
39.type rt_hw_interrupt_enable, %function
40rt_hw_interrupt_enable:
41    wrctl status, r4       /* enable interrupt by argument */
42    ret
43
44/* void rt_hw_context_switch_interrupt_do(void) */
45.global rt_hw_context_switch_interrupt_do
46.type rt_hw_context_switch_interrupt_do, %function
47rt_hw_context_switch_interrupt_do:
48    /* save from thread */
49    addi sp,sp,-72
50
51    /* frist save r2,so that save status */
52    stw r2,   4(sp)
53
54    /* save status */
55    /* when the interrupt happen,the interrupt is enable */
56    movi r2, 1
57    stw  r2, 68(sp)  /* status */
58
59    stw r3,   8(sp)
60    stw r4,  12(sp)
61
62    /* get & save from thread pc */
63    ldw r4,%gprel(rt_current_thread_entry)(gp)
64    stw r4,   0(sp)  /* thread pc */
65
66    stw r5,  16(sp)
67    stw r6,  20(sp)
68    stw r7,  24(sp)
69
70    stw r16, 28(sp)
71    stw r17, 32(sp)
72    stw r18, 36(sp)
73    stw r19, 40(sp)
74    stw r20, 44(sp)
75    stw r21, 48(sp)
76    stw r22, 52(sp)
77    stw r23, 56(sp)
78
79    stw fp,  60(sp)
80    stw ra,  64(sp)
81
82    /* save from thread sp */
83    /* rt_interrupt_from_thread = &from_thread->sp */
84    ldw r4, %gprel(rt_interrupt_from_thread)(gp)
85    /* *r4(from_thread->sp) = sp */
86    stw sp, (r4)
87
88    /* clear rt_thread_switch_interrupt_flag */
89    /* rt_thread_switch_interrupt_flag = 0 */
90    stw zero,%gprel(rt_thread_switch_interrupt_flag)(gp)
91
92    /* load to thread sp */
93    /* r4 = rt_interrupt_to_thread(&to_thread->sp) */
94    ldw r4, %gprel(rt_interrupt_to_thread)(gp)
95    /* sp = to_thread->sp */
96    ldw sp, (r4)
97
98    ldw r2,  68(sp)  /* status */
99    wrctl estatus, r2
100
101    ldw ea,   0(sp)  /* thread pc */
102    ldw r2,   4(sp)
103    ldw r3,   8(sp)
104    ldw r4,  12(sp)
105    ldw r5,  16(sp)
106    ldw r6,  20(sp)
107    ldw r7,  24(sp)
108
109    ldw r16, 28(sp)
110    ldw r17, 32(sp)
111    ldw r18, 36(sp)
112    ldw r19, 40(sp)
113    ldw r20, 44(sp)
114    ldw r21, 48(sp)
115    ldw r22, 52(sp)
116    ldw r23, 56(sp)
117
118    ldw fp,  60(sp)
119    ldw ra,  64(sp)
120
121    addi sp, sp, 72
122
123    /* estatus --> status,ea --> pc */
124    eret
125
126/*
127 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
128 * r4: from
129 * r5: to
130 */
131.global rt_hw_context_switch
132.type rt_hw_context_switch, %function
133rt_hw_context_switch:
134    /* save from thread */
135    addi sp,sp,-72
136
137    /* frist save r2,so that save status */
138    stw r2,   4(sp)
139
140    /* save status */
141    rdctl r2, status
142    stw r2,  68(sp)  /* status */
143
144    stw ra,   0(sp)  /* return from rt_hw_context_switch */
145    stw r3,   8(sp)
146    stw r4,  12(sp)
147    stw r5,  16(sp)
148    stw r6,  20(sp)
149    stw r7,  24(sp)
150
151    stw r16, 28(sp)
152    stw r17, 32(sp)
153    stw r18, 36(sp)
154    stw r19, 40(sp)
155    stw r20, 44(sp)
156    stw r21, 48(sp)
157    stw r22, 52(sp)
158    stw r23, 56(sp)
159
160    stw fp,  60(sp)
161    stw ra,  64(sp)
162
163    /* save form thread sp */
164    /* from_thread->sp(r4) = sp */
165    stw sp, (r4)
166
167    /* update rt_interrupt_from_thread */
168    /* rt_interrupt_from_thread = r4(from_thread->sp) */
169    stw r4,%gprel(rt_interrupt_from_thread)(gp)
170
171    /* update rt_interrupt_to_thread */
172    /* rt_interrupt_to_thread = r5 */
173    stw r5,%gprel(rt_interrupt_to_thread)(gp)
174
175    /* get to thread sp */
176    /* sp = rt_interrupt_to_thread(r5:to_thread->sp) */
177    ldw sp, (r5)
178
179    ldw r2,  68(sp)  /* status */
180    wrctl estatus, r2
181
182    ldw ea, 0(sp)    /* thread pc */
183
184    ldw r2,   4(sp)
185    ldw r3,   8(sp)
186    ldw r4,  12(sp)
187    ldw r5,  16(sp)
188    ldw r6,  20(sp)
189    ldw r7,  24(sp)
190
191    ldw r16, 28(sp)
192    ldw r17, 32(sp)
193    ldw r18, 36(sp)
194    ldw r19, 40(sp)
195    ldw r20, 44(sp)
196    ldw r21, 48(sp)
197    ldw r22, 52(sp)
198    ldw r23, 56(sp)
199
200    ldw fp,  60(sp)
201    ldw ra,  64(sp)
202
203    addi sp, sp, 72
204
205    /* estatus --> status,ea --> pc */
206    eret
207
208/*
209 * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
210 * r4: from
211 * r5: to
212 */
213.global rt_hw_context_switch_interrupt
214.type rt_hw_context_switch_interrupt, %function
215rt_hw_context_switch_interrupt:
216    /* if( rt_thread_switch_interrupt_flag != 0 ) _from_thread_not_change */
217    ldw r2,%gprel(rt_thread_switch_interrupt_flag)(gp)
218    bne r2,zero,_from_thread_not_change
219
220_from_thread_change:
221    /* save ea -> rt_current_thread_entry */
222    addi ea,ea,-4
223    stw ea,%gprel(rt_current_thread_entry)(gp)
224
225    /* set rt_thread_switch_interrupt_flag to 1 */
226    movi r2, 1
227    stw r2,%gprel(rt_thread_switch_interrupt_flag)(gp)
228
229    /* update rt_interrupt_from_thread */
230    stw r4,%gprel(rt_interrupt_from_thread)(gp)
231
232_from_thread_not_change:
233    /* update rt_interrupt_to_thread */
234    stw r5,%gprel(rt_interrupt_to_thread)(gp)
235
236    ret
237
238/*
239 * void rt_hw_context_switch_to(rt_uint32 to);
240 * r4: to
241 */
242.global rt_hw_context_switch_to
243.type rt_hw_context_switch_to, %function
244rt_hw_context_switch_to:
245    /* save to thread */
246    stw r4,%gprel(rt_interrupt_to_thread)(gp)
247
248    /* get sp */
249    ldw sp, (r4) // sp = *r4
250
251    ldw r2,  68(sp)  /* status */
252    wrctl estatus, r2
253
254    ldw ea, 0(sp)    /* thread entry */
255
256    ldw r2,   4(sp)
257    ldw r3,   8(sp)
258    ldw r4,  12(sp)
259    ldw r5,  16(sp)
260    ldw r6,  20(sp)
261    ldw r7,  24(sp)
262
263    ldw r16, 28(sp)
264    ldw r17, 32(sp)
265    ldw r18, 36(sp)
266    ldw r19, 40(sp)
267    ldw r20, 44(sp)
268    ldw r21, 48(sp)
269    ldw r22, 52(sp)
270    ldw r23, 56(sp)
271
272    ldw fp,  60(sp)
273    ldw ra,  64(sp)
274
275    addi sp, sp, 72
276
277    /* estatus --> status,ea --> pc */
278    eret
279
280/*@}*/
281