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
|
/*
* Proll takes this from Sparclinux kernel, ruthlessly truncated
* because we have no user windows.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*
* 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.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License V2
* as published by the Free Software Foundation
*/
// #include <asm/winmacro.h>
// #include <asm/asmmacro.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
/* Store the register window onto the 8-byte aligned area starting
* at %reg. It might be %sp, it might not, we don't care.
*/
#define STORE_WINDOW(reg) \
std %l0, [%reg + RW_L0]; \
std %l2, [%reg + RW_L2]; \
std %l4, [%reg + RW_L4]; \
std %l6, [%reg + RW_L6]; \
std %i0, [%reg + RW_I0]; \
std %i2, [%reg + RW_I2]; \
std %i4, [%reg + RW_I4]; \
std %i6, [%reg + RW_I6];
/* We define macro's for registers which have a fixed
* meaning throughout this entire routine. The 'T' in
* the comments mean that the register can only be
* accessed when in the 'trap' window, 'G' means
* accessible in any window. Do not change these registers
* after they have been set, until you are ready to return
* from the trap.
*/
#define t_psr l0 /* %psr at trap time T */
#define t_pc l1 /* PC for trap return T */
#define t_npc l2 /* NPC for trap return T */
#define t_wim l3 /* %wim at trap time T */
#define saved_g5 l5 /* Global save register T */
#define saved_g6 l6 /* Global save register T */
/* Now registers whose values can change within the handler. */
#define twin_tmp l4 /* Temp reg, only usable in trap window T */
#define glob_tmp g5 /* Global temporary reg, usable anywhere G */
.text
.align 4
/* BEGINNING OF PATCH INSTRUCTIONS */
/* On a 7-window Sparc the boot code patches spnwin_*
* instructions with the following ones.
*/
.globl spnwin_patch1_7win, spnwin_patch2_7win, spnwin_patch3_7win
spnwin_patch1_7win: sll %t_wim, 6, %glob_tmp
spnwin_patch2_7win: and %glob_tmp, 0x7f, %glob_tmp
spnwin_patch3_7win: and %twin_tmp, 0x7f, %twin_tmp
/* END OF PATCH INSTRUCTIONS */
/* The trap entry point has done the following:
*
* rd %psr, %l0
* rd %wim, %l3
* b spill_window_entry
* nop
*/
.globl spill_window_entry
.globl spnwin_patch1, spnwin_patch2
spill_window_entry:
/* LOCATION: Trap Window */
mov %g5, %saved_g5 ! save away global temp register
mov %g6, %saved_g6 ! save away 'current' ptr register
/* Compute what the new %wim will be if we save the
* window properly in this trap handler.
*
* newwim = ((%wim>>1) | (%wim<<(nwindows - 1)));
*/
srl %t_wim, 0x1, %twin_tmp
spnwin_patch1: sll %t_wim, 7, %glob_tmp
or %glob_tmp, %twin_tmp, %glob_tmp
spnwin_patch2: and %glob_tmp, 0xff, %glob_tmp
/* Save into the window which must be saved and do it.
*/
save %g0, %g0, %g0 ! save into the window to stash away
wr %glob_tmp, 0x0, %wim ! set new %wim, this is safe now
/* LOCATION: Window to be saved */
STORE_WINDOW(sp) ! stash the window
restore %g0, %g0, %g0 ! go back into trap window
/* LOCATION: Trap window */
mov %saved_g5, %g5 ! restore %glob_tmp
mov %saved_g6, %g6 ! restore %curptr
wr %t_psr, 0x0, %psr ! restore condition codes in %psr
nop; nop; nop ! waste some time
jmp %t_pc ! Return from trap
rett %t_npc ! we are done
|