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
1101:	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
1272:	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
2183:
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
2264:
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
2365:
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
2466:
247	subcc   %i1, 6, %g0		! syscall 6,  flush windows
248	bne 	1f
249	 nop
250
251	ba,a	_irqcall_flush_windows
252
2531:
254	ta	0			! halt
2559:					! 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);
263leonbare_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();
272leonbare_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();
281leonbare_flush_windows:
282        set 6,%o1
283        retl
284         ta 0x2
285
286