Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / sparc32 / wof.S
1 /*
2  * Proll takes this from Sparclinux kernel, ruthlessly truncated
3  * because we have no user windows.
4  *
5  *   Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6  *
7  *   This program is free software; you can redistribute it and/or
8  *   modify it under the terms of the GNU General Public License
9  *   version 2 as published by the Free Software Foundation.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  *   MA  02110-1301, USA.
20  *   This program is free software; you can redistribute it and/or
21  *   modify it under the terms of the GNU General Public License V2
22  *   as published by the Free Software Foundation
23  */
24
25 // #include <asm/winmacro.h>
26 // #include <asm/asmmacro.h>
27
28 /* Reg_window offsets */
29 #define RW_L0     0x00
30 #define RW_L1     0x04
31 #define RW_L2     0x08
32 #define RW_L3     0x0c
33 #define RW_L4     0x10
34 #define RW_L5     0x14
35 #define RW_L6     0x18
36 #define RW_L7     0x1c
37 #define RW_I0     0x20
38 #define RW_I1     0x24
39 #define RW_I2     0x28
40 #define RW_I3     0x2c
41 #define RW_I4     0x30
42 #define RW_I5     0x34
43 #define RW_I6     0x38
44 #define RW_I7     0x3c
45
46 /* Store the register window onto the 8-byte aligned area starting
47  * at %reg.  It might be %sp, it might not, we don't care.
48  */
49 #define STORE_WINDOW(reg) \
50         std     %l0, [%reg + RW_L0]; \
51         std     %l2, [%reg + RW_L2]; \
52         std     %l4, [%reg + RW_L4]; \
53         std     %l6, [%reg + RW_L6]; \
54         std     %i0, [%reg + RW_I0]; \
55         std     %i2, [%reg + RW_I2]; \
56         std     %i4, [%reg + RW_I4]; \
57         std     %i6, [%reg + RW_I6];
58
59 /* We define macro's for registers which have a fixed
60  * meaning throughout this entire routine.  The 'T' in
61  * the comments mean that the register can only be
62  * accessed when in the 'trap' window, 'G' means
63  * accessible in any window.  Do not change these registers
64  * after they have been set, until you are ready to return
65  * from the trap.
66  */
67 #define t_psr       l0 /* %psr at trap time                     T */
68 #define t_pc        l1 /* PC for trap return                    T */
69 #define t_npc       l2 /* NPC for trap return                   T */
70 #define t_wim       l3 /* %wim at trap time                     T */
71 #define saved_g5    l5 /* Global save register                  T */
72 #define saved_g6    l6 /* Global save register                  T */
73
74 /* Now registers whose values can change within the handler.      */
75 #define twin_tmp    l4 /* Temp reg, only usable in trap window  T */
76 #define glob_tmp    g5 /* Global temporary reg, usable anywhere G */
77
78         .text
79         .align  4
80
81         /* BEGINNING OF PATCH INSTRUCTIONS */
82         /* On a 7-window Sparc the boot code patches spnwin_*
83          * instructions with the following ones.
84          */
85         .globl  spnwin_patch1_7win, spnwin_patch2_7win, spnwin_patch3_7win
86 spnwin_patch1_7win:     sll     %t_wim, 6, %glob_tmp
87 spnwin_patch2_7win:     and     %glob_tmp, 0x7f, %glob_tmp
88 spnwin_patch3_7win:     and     %twin_tmp, 0x7f, %twin_tmp
89         /* END OF PATCH INSTRUCTIONS */
90
91         /* The trap entry point has done the following:
92          *
93          * rd    %psr, %l0
94          * rd    %wim, %l3
95          * b     spill_window_entry
96          * nop
97          */
98
99         .globl  spill_window_entry
100         .globl  spnwin_patch1, spnwin_patch2
101 spill_window_entry:
102         /* LOCATION: Trap Window */
103
104         mov     %g5, %saved_g5          ! save away global temp register
105         mov     %g6, %saved_g6          ! save away 'current' ptr register
106
107         /* Compute what the new %wim will be if we save the
108          * window properly in this trap handler.
109          *
110          * newwim = ((%wim>>1) | (%wim<<(nwindows - 1)));
111          */
112                 srl     %t_wim, 0x1, %twin_tmp
113 spnwin_patch1:  sll     %t_wim, 7, %glob_tmp
114                 or      %glob_tmp, %twin_tmp, %glob_tmp
115 spnwin_patch2:  and     %glob_tmp, 0xff, %glob_tmp
116
117         /* Save into the window which must be saved and do it.
118          */
119         save    %g0, %g0, %g0           ! save into the window to stash away
120         wr      %glob_tmp, 0x0, %wim    ! set new %wim, this is safe now
121
122         /* LOCATION: Window to be saved */
123
124         STORE_WINDOW(sp)                ! stash the window
125         restore %g0, %g0, %g0           ! go back into trap window
126
127         /* LOCATION: Trap window */
128         mov     %saved_g5, %g5          ! restore %glob_tmp
129         mov     %saved_g6, %g6          ! restore %curptr
130         wr      %t_psr, 0x0, %psr       ! restore condition codes in %psr
131         nop; nop; nop                   ! waste some time
132         jmp     %t_pc                   ! Return from trap
133         rett    %t_npc                  ! we are done