1 | /* |
---|
2 | * Copyright (c) 2011 Aeroflex Gaisler |
---|
3 | * |
---|
4 | * BSD license: |
---|
5 | * |
---|
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
---|
7 | * of this software and associated documentation files (the "Software"), to deal |
---|
8 | * in the Software without restriction, including without limitation the rights |
---|
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
---|
10 | * copies of the Software, and to permit persons to whom the Software is |
---|
11 | * furnished to do so, subject to the following conditions: |
---|
12 | * |
---|
13 | * The above copyright notice and this permission notice shall be included in |
---|
14 | * all copies or substantial portions of the Software. |
---|
15 | * |
---|
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
---|
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
---|
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
---|
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
---|
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
---|
22 | * THE SOFTWARE. |
---|
23 | */ |
---|
24 | |
---|
25 | |
---|
26 | #include <asm-leon/leon.h> |
---|
27 | #include <asm-leon/leonstack.h> |
---|
28 | #include <asm-leon/asmmacro.h> |
---|
29 | |
---|
30 | .seg "data" |
---|
31 | .global _lb_spillglobals, _lb_issideflush |
---|
32 | .align 4 |
---|
33 | _lb_spillglobals: |
---|
34 | .word 0 |
---|
35 | .word 0 |
---|
36 | .word 0 |
---|
37 | .word 0 |
---|
38 | .word 0 |
---|
39 | .word 0 |
---|
40 | .word 0 |
---|
41 | _lb_issideflush: |
---|
42 | .word 0 /* off: 28 */ |
---|
43 | |
---|
44 | .seg "text" |
---|
45 | |
---|
46 | /* =============================================== */ |
---|
47 | |
---|
48 | #define _SV save %sp, -SF_REGS_SZ, %sp |
---|
49 | #define _RS restore |
---|
50 | |
---|
51 | /* ------- */ |
---|
52 | .weak _flush_windows |
---|
53 | .set _flush_windows,__flush_windows |
---|
54 | .weak _flush_windows_svt |
---|
55 | .set _flush_windows_svt,__flush_windows_svt |
---|
56 | /* ------- */ |
---|
57 | !.global _flush_windows,_flush_windows_svt |
---|
58 | __flush_windows_svt: |
---|
59 | rd %wim, %l3 |
---|
60 | |
---|
61 | __flush_windows: |
---|
62 | SAVE_ALL |
---|
63 | |
---|
64 | #ifndef _FLAT |
---|
65 | |
---|
66 | set _lb_issideflush, %l3 |
---|
67 | st %l0, [%l3] /* mark as inside flush */ |
---|
68 | |
---|
69 | wr %l0, SPARC_PSR_ET_MASK, %psr |
---|
70 | nop; nop; nop |
---|
71 | |
---|
72 | _SV; _SV; _SV; _SV; _SV; _SV; _SV; |
---|
73 | _RS; _RS; _RS; _RS; _RS; _RS; _RS; |
---|
74 | |
---|
75 | set _lb_issideflush, %l3 |
---|
76 | st %g0, [%l3] /* mark as outside flush */ |
---|
77 | |
---|
78 | /* Advance over the trap instruction. */ |
---|
79 | ld [%sp + SF_REGS_SZ + PT_NPC], %l1 |
---|
80 | add %l1, 0x4, %l2 |
---|
81 | st %l1, [%sp + SF_REGS_SZ + PT_PC] |
---|
82 | st %l2, [%sp + SF_REGS_SZ + PT_NPC] |
---|
83 | #endif |
---|
84 | |
---|
85 | RESTORE_ALL |
---|
86 | |
---|
87 | /* =============================================== */ |
---|
88 | |
---|
89 | _irqcall_flush_windows: |
---|
90 | #ifndef _FLAT |
---|
91 | set _lb_spillglobals,%l4 |
---|
92 | st %g1,[%l4+0] |
---|
93 | st %g4,[%l4+4] |
---|
94 | st %l0,[%l4+16] |
---|
95 | st %l1,[%l4+20] |
---|
96 | st %l2,[%l4+24] |
---|
97 | st %l4,[%l4+28] /* mark as inside flush */ |
---|
98 | |
---|
99 | restore |
---|
100 | |
---|
101 | mov %psr, %g1 |
---|
102 | or %g1, SPARC_PSR_PIL_MASK, %g1 |
---|
103 | wr %g1, SPARC_PSR_ET_MASK, %psr /* disable irq, enable traps */ |
---|
104 | nop |
---|
105 | nop |
---|
106 | nop |
---|
107 | |
---|
108 | sethi %hi(_nwindows_min1), %g4 /* flush registers */ |
---|
109 | ld [%g4+%lo(_nwindows_min1)], %g4 |
---|
110 | 1: save /* NWINDOWS-1 times */ |
---|
111 | sub %g4,1,%g4 |
---|
112 | |
---|
113 | /*****************/ |
---|
114 | andncc %g4,0xff,%g0 |
---|
115 | be .lab1 |
---|
116 | nop |
---|
117 | nop |
---|
118 | |
---|
119 | .lab1: /*****************/ |
---|
120 | |
---|
121 | cmp %g4,%g0 |
---|
122 | bne 1b |
---|
123 | nop |
---|
124 | |
---|
125 | sethi %hi(_nwindows_min1), %g4 |
---|
126 | ld [%g4+%lo(_nwindows_min1)], %g4 |
---|
127 | 2: restore /* NWINDOWS-1 times */ |
---|
128 | |
---|
129 | /*****************/ |
---|
130 | andncc %g4,0xff,%g0 |
---|
131 | be .lab2 |
---|
132 | nop |
---|
133 | nop |
---|
134 | |
---|
135 | .lab2: /*****************/ |
---|
136 | |
---|
137 | sub %g4,1,%g4 |
---|
138 | cmp %g4,%g0 |
---|
139 | bne 2b |
---|
140 | nop |
---|
141 | |
---|
142 | save |
---|
143 | |
---|
144 | set _lb_spillglobals,%l4 |
---|
145 | ld [%l4+4], %g4 |
---|
146 | ld [%l4+0], %g1 |
---|
147 | ld [%l4+16],%l0 |
---|
148 | ld [%l4+20],%l1 |
---|
149 | ld [%l4+24],%l2 |
---|
150 | st %g0,[%l4+28] /* clean inside flush mark */ |
---|
151 | |
---|
152 | #endif |
---|
153 | |
---|
154 | wr %l0, 0, %psr /* restore psr */ |
---|
155 | nop |
---|
156 | nop |
---|
157 | nop |
---|
158 | |
---|
159 | jmpl %l2, %g0 |
---|
160 | rett %l2 + 4 |
---|
161 | |
---|
162 | /* =============================================== */ |
---|
163 | |
---|
164 | /* ------- */ |
---|
165 | .weak _irqcall_disableirq |
---|
166 | .set _irqcall_disableirq,__irqcall_disableirq |
---|
167 | .weak _irqcall_disableirq_svt |
---|
168 | .set _irqcall_disableirq_svt,__irqcall_disableirq_svt |
---|
169 | /* ------- */ |
---|
170 | |
---|
171 | __irqcall_disableirq: |
---|
172 | __irqcall_disableirq_svt: |
---|
173 | or %l0, SPARC_PSR_PIL_MASK, %l0 |
---|
174 | mov %l0, %psr |
---|
175 | nop; nop; nop |
---|
176 | jmpl %l2, %g0 |
---|
177 | rett %l2 + 4 |
---|
178 | |
---|
179 | /* =============================================== */ |
---|
180 | |
---|
181 | /* |
---|
182 | * system call (ta 0x2): |
---|
183 | * 2: irq_disable: |
---|
184 | * o1 = 2 |
---|
185 | * 3: irq_enable: |
---|
186 | * o0 = old_flags |
---|
187 | * o1 = 3 |
---|
188 | * 4: enter supervisor mode (from user mode): |
---|
189 | * o1 = 4 |
---|
190 | * 5: enter user mode: |
---|
191 | * o1 = 5 |
---|
192 | * 6: flush windows |
---|
193 | * |
---|
194 | * On entry: |
---|
195 | * |
---|
196 | * l0 = psr (from trap table) |
---|
197 | * l1 = pc |
---|
198 | * l2 = npc |
---|
199 | * i0 = system call id |
---|
200 | */ |
---|
201 | |
---|
202 | /* ------- */ |
---|
203 | .weak _irqcall |
---|
204 | .set _irqcall,__irqcall |
---|
205 | .weak _irqcall_svt |
---|
206 | .set _irqcall_svt,__irqcall_svt |
---|
207 | /* ------- */ |
---|
208 | !.global _irqcall,_irqcall_svt |
---|
209 | __irqcall_svt: |
---|
210 | __irqcall: |
---|
211 | |
---|
212 | subcc %i1, 2, %g0 ! syscall 2, disable interrupts |
---|
213 | bne 3f |
---|
214 | or %l0, 0x0f00, %l4 ! set PIL=15 |
---|
215 | mov %l4, %psr |
---|
216 | or %l0, SPARC_PSR_ET_MASK, %i0 ! return old psr with ET=1 |
---|
217 | ba,a 9f |
---|
218 | 3: |
---|
219 | subcc %i1, 3, %g0 ! syscall 3, enable interrupts |
---|
220 | bne 4f |
---|
221 | and %i0, SPARC_PSR_PIL_MASK, %l4 |
---|
222 | andn %l0, SPARC_PSR_PIL_MASK, %l5 |
---|
223 | or %l5, %l4, %l4 |
---|
224 | mov %l4, %psr |
---|
225 | ba,a 9f |
---|
226 | 4: |
---|
227 | subcc %i1, 4, %g0 ! syscall 4, enter supervisor |
---|
228 | bne 5f |
---|
229 | |
---|
230 | mov %psr, %l4 |
---|
231 | or %l4,SPARC_PSR_PS_MASK,%l4 |
---|
232 | mov %l4, %psr ! set previous supervisor %psr |
---|
233 | nop; nop; nop |
---|
234 | ba,a 9f |
---|
235 | |
---|
236 | 5: |
---|
237 | subcc %i1, 5, %g0 ! syscall 5, enter user |
---|
238 | bne 6f |
---|
239 | |
---|
240 | mov %psr, %l4 |
---|
241 | andn %l4,SPARC_PSR_PS_MASK,%l4 |
---|
242 | mov %l4, %psr ! clear previous supervisor %psr, return to user mode |
---|
243 | nop; nop; nop |
---|
244 | ba,a 9f |
---|
245 | |
---|
246 | 6: |
---|
247 | subcc %i1, 6, %g0 ! syscall 6, flush windows |
---|
248 | bne 1f |
---|
249 | nop |
---|
250 | |
---|
251 | ba,a _irqcall_flush_windows |
---|
252 | |
---|
253 | 1: |
---|
254 | ta 0 ! halt |
---|
255 | 9: ! leave |
---|
256 | jmpl %l2, %g0 |
---|
257 | rett %l2 + 4 |
---|
258 | |
---|
259 | /* =============================================== */ |
---|
260 | |
---|
261 | /* call _irqcall through trap */ |
---|
262 | .global leonbare_enable_traps !void leonbare_enable_traps(unsigned long old_flags); |
---|
263 | leonbare_enable_traps: |
---|
264 | set 3,%o1 |
---|
265 | retl |
---|
266 | ta 0x2 |
---|
267 | |
---|
268 | /* =============================================== */ |
---|
269 | |
---|
270 | /* call _irqcall through trap */ |
---|
271 | .global leonbare_disable_traps !unsigned long leonbare_disable_traps(); |
---|
272 | leonbare_disable_traps: |
---|
273 | set 2,%o1 |
---|
274 | retl |
---|
275 | ta 0x2 |
---|
276 | |
---|
277 | /* =============================================== */ |
---|
278 | |
---|
279 | /* flush all windows */ |
---|
280 | .global leonbare_flush_windows !void leonbare_flush_windows(); |
---|
281 | leonbare_flush_windows: |
---|
282 | set 6,%o1 |
---|
283 | retl |
---|
284 | ta 0x2 |
---|
285 | |
---|