context_gcc.S
6.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#include "context.h"
#define SPRG0 0x110 /* Special Purpose Register General 0 */
#define SPRG1 0x111 /* Special Purpose Register General 1 */
.globl rt_hw_interrupt_disable
.globl rt_hw_interrupt_enable
.globl rt_hw_context_switch
.globl rt_hw_context_switch_to
.globl rt_hw_context_switch_interrupt
.globl rt_hw_systemcall_entry
/*
* rt_base_t rt_hw_interrupt_disable();
* return the interrupt status and disable interrupt
*/
#if 0
rt_hw_interrupt_disable:
mfmsr r3 /* Disable interrupts */
li r4,0
ori r4,r4,MSR_EE
andc r4,r4,r3
SYNC /* Some chip revs need this... */
mtmsr r4
SYNC
blr
#else
rt_hw_interrupt_disable:
addis r4, r0, 0xFFFD
ori r4, r4, 0x7FFF
mfmsr r3
and r4, r4, 3 /* Clear bits 14 and 16, corresponding to... */
mtmsr r4 /* ...critical and non-critical interrupts */
blr
#endif
/*
* void rt_hw_interrupt_enable(rt_base_t level);
* restore interrupt
*/
rt_hw_interrupt_enable:
mtmsr r3
SYNC
blr
/*
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
* r3 --> from
* r4 --> to
*
* r1: stack pointer
*/
rt_hw_systemcall_entry:
mtspr SPRG0,r3 /* save r3 to SPRG0 */
mtspr SPRG1,r4 /* save r4 to SPRG1 */
lis r3,rt_thread_switch_interrput_flag@h
ori r3,r3,rt_thread_switch_interrput_flag@l
lwz r4,0(r3)
cmpi cr0,0,r4,0x0 /* whether is 0 */
beq _no_switch /* no switch, exit */
li r4,0x0 /* set rt_thread_switch_interrput_flag to 0 */
stw r4,0(r3)
/* load from thread to r3 */
lis r3,rt_interrupt_from_thread@h /* set rt_interrupt_from_thread */
ori r3,r3,rt_interrupt_from_thread@l
lwz r3,0(r3)
cmpi cr0,0,r3,0x0 /* whether is 0 */
beq _restore /* it's first switch, goto _restore */
/* save r1:sp to thread[from] stack pointer */
subi r1, r1, STACK_FRAME_SIZE
stw r1, 0(r3)
/* restore r3, r4 from SPRG */
mfspr r3,SPRG0
mfspr r4,SPRG0
/* save registers */
stw r0,GPR0(r1) /* save general purpose registers 0 */
stmw r2,GPR2(r1) /* save general purpose registers 2-31 */
mfusprg0 r0 /* save usprg0 */
stw r0,USPRG0(r1)
mfcr r0, /* save cr */
stw r0,CR(r1)
mfxer r0 /* save xer */
stw r0,XER(r1)
mfctr r0 /* save ctr */
stw r0,CTR(r1)
mflr r0 /* save lr */
stw r0, LR(r1)
mfsrr0 r0 /* save SRR0 and SRR1 */
stw r0,SRR0(r1)
mfsrr1 r0
stw r0,SRR1(r1)
_restore:
/* get thread[to] stack pointer */
lis r4,rt_interrupt_to_thread@h
ori r4,r4,rt_interrupt_to_thread@l
lwz r1,0(r4)
lwz r1,0(r1)
lwz r0,SRR1(r1) /* restore SRR1 and SRR0 */
mtsrr1 r0
lwz r0,SRR0(r1)
mtsrr0 r0
lwz r0,LR(r1) /* restore lr */
mtlr r0
lwz r0,CTR(r1) /* restore ctr */
mtctr r0
lwz r0,XER(r1) /* restore xer */
mtxer r0
lwz r0,CR(r1) /* restore cr */
mtcr r0
lwz r0,USPRG0(r1) /* restore usprg0 */
// mtusprg0 r0
lmw r2, GPR2(r1) /* restore general register */
lwz r0,GPR0(r1)
addi r1, r1, STACK_FRAME_SIZE
/* RFI will restore status register and thus the correct priority*/
rfi
_no_switch:
/* restore r3, r4 from SPRG */
mfspr r3,SPRG0
mfspr r4,SPRG0
rfi
/* void rt_hw_context_switch_to(to); */
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
/* set rt_thread_switch_interrput_flag = 1 */
lis r5,rt_thread_switch_interrput_flag@h
ori r5,r5,rt_thread_switch_interrput_flag@l
li r6, 0x01
stw r6,0(r5)
/* set rt_interrupt_from_thread = 0 */
lis r5,rt_interrupt_from_thread@h
ori r5,r5,rt_interrupt_from_thread@l
li r6, 0x00
stw r6,0(r5)
/* set rt_interrupt_from_thread = to */
lis r5,rt_interrupt_to_thread@h
ori r5,r5,rt_interrupt_to_thread@l
stw r3,0(r5)
/* trigger a system call */
sc
blr
/* void rt_hw_context_switch(from, to); */
.globl rt_hw_context_switch
rt_hw_context_switch:
/* compare rt_thread_switch_interrupt_flag and set it */
lis r5,rt_thread_switch_interrput_flag@h
ori r5,r5,rt_thread_switch_interrput_flag@l
lwz r6,0(r5)
cmpi cr0,0,r6,0x1 /* whether is 1 */
beq _reswitch /* set already, goto _reswitch */
li r6,0x1 /* set rt_thread_switch_interrput_flag to 1*/
stw r6,0(r5)
/* set rt_interrupt_from_thread to 'from' */
lis r5,rt_interrupt_from_thread@h
ori r5,r5,rt_interrupt_from_thread@l
stw r3,0(r5)
_reswitch:
/* set rt_interrupt_to_thread to 'to' */
lis r6,rt_interrupt_to_thread@h
ori r6,r6,rt_interrupt_to_thread@l
stw r4,0(r6)
/* trigger a system call */
sc
blr
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
/* compare rt_thread_switch_interrupt_flag and set it */
lis r5,rt_thread_switch_interrput_flag@h
ori r5,r5,rt_thread_switch_interrput_flag@l
lwz r6,0(r5)
cmpi cr0,0,r6,0x1 /* whether is 1 */
beq _int_reswitch /* set already, goto _reswitch */
li r6,0x1 /* set rt_thread_switch_interrput_flag to 1*/
stw r6,0(r5)
/* set rt_interrupt_from_thread to 'from' */
lis r5,rt_interrupt_from_thread@h
ori r5,r5,rt_interrupt_from_thread@l
stw r3,0(r5)
_int_reswitch:
/* set rt_interrupt_to_thread to 'to' */
lis r6,rt_interrupt_to_thread@h
ori r6,r6,rt_interrupt_to_thread@l
stw r4,0(r6)
blr