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
|
/*
* Window fill (underflow) trap, based on code from Sparclinux.
*
* Copyright (C) 1995 David S. Miller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
// #include <psr.h>
// #include <asi.h>
/* Reg_window offsets */
#define RW_L0 0x00
#define RW_L1 0x04
#define RW_L2 0x08
#define RW_L3 0x0c
#define RW_L4 0x10
#define RW_L5 0x14
#define RW_L6 0x18
#define RW_L7 0x1c
#define RW_I0 0x20
#define RW_I1 0x24
#define RW_I2 0x28
#define RW_I3 0x2c
#define RW_I4 0x30
#define RW_I5 0x34
#define RW_I6 0x38
#define RW_I7 0x3c
/* Load a register window from the area beginning at %reg. */
#define LOAD_WINDOW(reg) \
ldd [%reg + RW_L0], %l0; \
ldd [%reg + RW_L2], %l2; \
ldd [%reg + RW_L4], %l4; \
ldd [%reg + RW_L6], %l6; \
ldd [%reg + RW_I0], %i0; \
ldd [%reg + RW_I2], %i2; \
ldd [%reg + RW_I4], %i4; \
ldd [%reg + RW_I6], %i6;
#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */
/* Just like the overflow handler we define macros for registers
* with fixed meanings in this routine.
*/
#define t_psr l0
#define t_pc l1
#define t_npc l2
#define t_wim l3
/* Don't touch the above registers or else you die horribly... */
/* Now macros for the available scratch registers in this routine. */
#define twin_tmp1 l4
#define twin_tmp2 l5
.text
.align 4
/* The trap entry point has executed the following:
*
* rd %psr, %l0
* rd %wim, %l3
* b fill_window_entry
* andcc %l0, PSR_PS, %g0
*/
/* To get an idea of what has just happened to cause this
* trap take a look at this diagram:
*
* 1 2 3 4 <-- Window number
* ----------
* T O W I <-- Symbolic name
*
* O == the window that execution was in when
* the restore was attempted
*
* T == the trap itself has save'd us into this
* window
*
* W == this window is the one which is now invalid
* and must be made valid plus loaded from the
* stack
*
* I == this window will be the invalid one when we
* are done and return from trap if successful
*/
/* BEGINNING OF PATCH INSTRUCTIONS */
/* On 7-window Sparc the boot code patches fnwin_patch1
* with the following instruction.
*/
.globl fnwin_patch1_7win, fnwin_patch2_7win
fnwin_patch1_7win: srl %t_wim, 6, %twin_tmp2
fnwin_patch2_7win: and %twin_tmp1, 0x7f, %twin_tmp1
/* END OF PATCH INSTRUCTIONS */
.globl fill_window_entry, fnwin_patch1, fnwin_patch2
fill_window_entry:
/* LOCATION: Window 'T' */
/* Compute what the new %wim is going to be if we retrieve
* the proper window off of the stack.
*/
sll %t_wim, 1, %twin_tmp1
fnwin_patch1: srl %t_wim, 7, %twin_tmp2
or %twin_tmp1, %twin_tmp2, %twin_tmp1
fnwin_patch2: and %twin_tmp1, 0xff, %twin_tmp1
wr %twin_tmp1, 0x0, %wim /* Make window 'I' invalid */
restore %g0, %g0, %g0 /* Restore to window 'O' */
/* Trapped from kernel, we trust that the kernel does not
* 'over restore' sorta speak and just grab the window
* from the stack and return. Easy enough.
*/
/* LOCATION: Window 'O' */
restore %g0, %g0, %g0
WRITE_PAUSE
/* LOCATION: Window 'W' */
LOAD_WINDOW(sp) /* Load it up */
/* Spin the wheel... */
save %g0, %g0, %g0
save %g0, %g0, %g0
/* I'd like to buy a vowel please... */
/* LOCATION: Window 'T' */
/* Now preserve the condition codes in %psr, pause, and
* return from trap. This is the simplest case of all.
*/
wr %t_psr, 0x0, %psr
WRITE_PAUSE
jmp %t_pc
rett %t_npc
|