Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / sparc32 / wuf.S
1 /*
2  * Window fill (underflow) trap, based on code from Sparclinux.
3  *
4  * Copyright (C) 1995 David S. Miller
5  *
6  *   This program is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU General Public License
8  *   version 2 as published by the Free Software Foundation.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  *   MA  02110-1301, USA.
19  */
20
21 // #include <psr.h>
22 // #include <asi.h>
23
24 /* Reg_window offsets */
25 #define RW_L0     0x00
26 #define RW_L1     0x04
27 #define RW_L2     0x08
28 #define RW_L3     0x0c
29 #define RW_L4     0x10
30 #define RW_L5     0x14
31 #define RW_L6     0x18
32 #define RW_L7     0x1c
33 #define RW_I0     0x20
34 #define RW_I1     0x24
35 #define RW_I2     0x28
36 #define RW_I3     0x2c
37 #define RW_I4     0x30
38 #define RW_I5     0x34
39 #define RW_I6     0x38
40 #define RW_I7     0x3c
41
42 /* Load a register window from the area beginning at %reg. */
43 #define LOAD_WINDOW(reg) \
44         ldd     [%reg + RW_L0], %l0; \
45         ldd     [%reg + RW_L2], %l2; \
46         ldd     [%reg + RW_L4], %l4; \
47         ldd     [%reg + RW_L6], %l6; \
48         ldd     [%reg + RW_I0], %i0; \
49         ldd     [%reg + RW_I2], %i2; \
50         ldd     [%reg + RW_I4], %i4; \
51         ldd     [%reg + RW_I6], %i6;
52
53 #define WRITE_PAUSE     nop; nop; nop; /* Have to do this after %wim/%psr chg */
54
55 /* Just like the overflow handler we define macros for registers
56  * with fixed meanings in this routine.
57  */
58 #define t_psr       l0
59 #define t_pc        l1
60 #define t_npc       l2
61 #define t_wim       l3
62 /* Don't touch the above registers or else you die horribly... */
63
64 /* Now macros for the available scratch registers in this routine. */
65 #define twin_tmp1    l4
66 #define twin_tmp2    l5
67
68         .text
69         .align  4
70
71         /* The trap entry point has executed the following:
72          *
73          * rd    %psr, %l0
74          * rd    %wim, %l3
75          * b     fill_window_entry
76          * andcc %l0, PSR_PS, %g0
77          */
78
79         /* To get an idea of what has just happened to cause this
80          * trap take a look at this diagram:
81          *
82          *      1  2  3  4     <--  Window number
83          *      ----------
84          *      T  O  W  I     <--  Symbolic name
85          *
86          *      O == the window that execution was in when
87          *           the restore was attempted
88          *
89          *      T == the trap itself has save'd us into this
90          *           window
91          *
92          *      W == this window is the one which is now invalid
93          *           and must be made valid plus loaded from the
94          *           stack
95          *
96          *      I == this window will be the invalid one when we
97          *           are done and return from trap if successful
98          */
99
100         /* BEGINNING OF PATCH INSTRUCTIONS */
101
102         /* On 7-window Sparc the boot code patches fnwin_patch1
103          * with the following instruction.
104          */
105         .globl  fnwin_patch1_7win, fnwin_patch2_7win
106 fnwin_patch1_7win:      srl     %t_wim, 6, %twin_tmp2
107 fnwin_patch2_7win:      and     %twin_tmp1, 0x7f, %twin_tmp1
108         /* END OF PATCH INSTRUCTIONS */
109
110
111         .globl  fill_window_entry, fnwin_patch1, fnwin_patch2
112 fill_window_entry:
113         /* LOCATION: Window 'T' */
114
115         /* Compute what the new %wim is going to be if we retrieve
116          * the proper window off of the stack.
117          */
118                 sll     %t_wim, 1, %twin_tmp1
119 fnwin_patch1:   srl     %t_wim, 7, %twin_tmp2
120                 or      %twin_tmp1, %twin_tmp2, %twin_tmp1
121 fnwin_patch2:   and     %twin_tmp1, 0xff, %twin_tmp1
122
123         wr      %twin_tmp1, 0x0, %wim   /* Make window 'I' invalid */
124
125         restore %g0, %g0, %g0           /* Restore to window 'O' */
126
127         /* Trapped from kernel, we trust that the kernel does not
128          * 'over restore' sorta speak and just grab the window
129          * from the stack and return.  Easy enough.
130          */
131         /* LOCATION: Window 'O' */
132
133         restore %g0, %g0, %g0
134         WRITE_PAUSE
135
136         /* LOCATION: Window 'W' */
137
138         LOAD_WINDOW(sp)                 /* Load it up */
139
140         /* Spin the wheel... */
141         save    %g0, %g0, %g0
142         save    %g0, %g0, %g0
143         /* I'd like to buy a vowel please... */
144
145         /* LOCATION: Window 'T' */
146
147         /* Now preserve the condition codes in %psr, pause, and
148          * return from trap.  This is the simplest case of all.
149          */
150         wr      %t_psr, 0x0, %psr
151         WRITE_PAUSE
152
153         jmp     %t_pc
154         rett    %t_npc