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