1 | /* |
---|
2 | * window.s |
---|
3 | * |
---|
4 | * This file contains the register window management routines for the |
---|
5 | * SPARC architecture. Trap handlers for the following capabilities |
---|
6 | * are included in this file: |
---|
7 | * |
---|
8 | * + Window Overflow |
---|
9 | * + Window Underflow |
---|
10 | * + Flushing All Windows |
---|
11 | * |
---|
12 | * COPYRIGHT: |
---|
13 | * |
---|
14 | * This file includes the window overflow and underflow handlers from |
---|
15 | * the file srt0.s provided with the binary distribution of the SPARC |
---|
16 | * Instruction Simulator (SIS) found at |
---|
17 | * ftp://ftp.estec.esa.nl/pub/ws/wsd/erc32. |
---|
18 | * |
---|
19 | * COPYRIGHT (c) 1995. European Space Agency. |
---|
20 | * |
---|
21 | * This terms of the RTEMS license apply to this file. |
---|
22 | * |
---|
23 | * $Id$ |
---|
24 | */ |
---|
25 | |
---|
26 | #include <asm.h> |
---|
27 | |
---|
28 | .seg "text" |
---|
29 | /* |
---|
30 | * Window overflow trap handler. |
---|
31 | * |
---|
32 | * On entry: |
---|
33 | * |
---|
34 | * l0 = psr (from trap table) |
---|
35 | * l1 = pc |
---|
36 | * l2 = npc |
---|
37 | */ |
---|
38 | |
---|
39 | PUBLIC(window_overflow_trap_handler) |
---|
40 | |
---|
41 | SYM(window_overflow_trap_handler): |
---|
42 | |
---|
43 | /* |
---|
44 | * Calculate new WIM by "rotating" the valid bits in the WIM right |
---|
45 | * by one position. The following shows how the bits move for a SPARC |
---|
46 | * cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8. |
---|
47 | * |
---|
48 | * OLD WIM = 76543210 |
---|
49 | * NEW WIM = 07654321 |
---|
50 | * |
---|
51 | * NOTE: New WIM must be stored in a global register since the |
---|
52 | * "save" instruction just prior to the load of the wim |
---|
53 | * register will result in the local register set changing. |
---|
54 | */ |
---|
55 | |
---|
56 | mov %wim, %l3 ! l3 = WIM |
---|
57 | mov %g1, %l7 ! save g1 |
---|
58 | srl %l3, 1, %g1 ! g1 = WIM >> 1 |
---|
59 | sll %l3, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l4 |
---|
60 | ! l4 = WIM << (Number Windows - 1) |
---|
61 | or %l4, %g1, %g1 ! g1 = (WIM >> 1) | |
---|
62 | ! (WIM << (Number Windows - 1)) |
---|
63 | |
---|
64 | save ! Get into window to be saved. |
---|
65 | mov %g1, %wim ! load new WIM |
---|
66 | nop; nop; nop ! 3 slot delay |
---|
67 | std %l0, [%sp + 0x00] ! save local register set |
---|
68 | std %l2, [%sp + 0x08] |
---|
69 | std %l4, [%sp + 0x10] |
---|
70 | std %l6, [%sp + 0x18] |
---|
71 | std %i0, [%sp + 0x20] ! save input register set |
---|
72 | std %i2, [%sp + 0x28] |
---|
73 | std %i4, [%sp + 0x30] |
---|
74 | std %i6, [%sp + 0x38] |
---|
75 | restore ! Go back to trap window. |
---|
76 | mov %l7, %g1 ! restore g1 |
---|
77 | jmp %l1 ! Re-execute save. |
---|
78 | rett %l2 |
---|
79 | |
---|
80 | /* |
---|
81 | * Window underflow trap handler. |
---|
82 | * |
---|
83 | * On entry: |
---|
84 | * |
---|
85 | * l0 = psr (from trap table) |
---|
86 | * l1 = pc |
---|
87 | * l2 = npc |
---|
88 | */ |
---|
89 | |
---|
90 | PUBLIC(window_underflow_trap_handler) |
---|
91 | |
---|
92 | SYM(window_underflow_trap_handler): |
---|
93 | |
---|
94 | /* |
---|
95 | * Calculate new WIM by "rotating" the valid bits in the WIM left |
---|
96 | * by one position. The following shows how the bits move for a SPARC |
---|
97 | * cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8. |
---|
98 | * |
---|
99 | * OLD WIM = 76543210 |
---|
100 | * NEW WIM = 07654321 |
---|
101 | * |
---|
102 | * NOTE: New WIM must be stored in a global register since the |
---|
103 | * "save" instruction just prior to the load of the wim |
---|
104 | * register will result in the local register set changing. |
---|
105 | */ |
---|
106 | |
---|
107 | mov %wim, %l3 ! Calculate new WIM |
---|
108 | sll %l3, 1, %l4 ! l4 = WIM << 1 |
---|
109 | srl %l3, SPARC_NUMBER_OF_REGISTER_WINDOWS-1, %l5 |
---|
110 | ! l5 = WIM >> (Number Windows-1) |
---|
111 | or %l5, %l4, %l5 ! l5 = (WIM << 1) | |
---|
112 | ! (WIM >> (Number Windows-1)) |
---|
113 | mov %l5, %wim ! load the new WIM |
---|
114 | nop; nop; nop |
---|
115 | restore ! Two restores to get into the |
---|
116 | restore ! window to restore |
---|
117 | ldd [%sp + 0x00], %l0 ! First the local register set |
---|
118 | ldd [%sp + 0x08], %l2 |
---|
119 | ldd [%sp + 0x10], %l4 |
---|
120 | ldd [%sp + 0x18], %l6 |
---|
121 | ldd [%sp + 0x20], %i0 ! Then the input registers |
---|
122 | ldd [%sp + 0x28], %i2 |
---|
123 | ldd [%sp + 0x30], %i4 |
---|
124 | ldd [%sp + 0x38], %i6 |
---|
125 | save ! Get back to the trap window. |
---|
126 | save |
---|
127 | jmp %l1 ! Re-execute restore. |
---|
128 | rett %l2 |
---|
129 | |
---|
130 | /* |
---|
131 | * Flush All Windows trap handler. |
---|
132 | * |
---|
133 | * Flush all windows with valid contents except the current one |
---|
134 | * and the one we will be returning to. |
---|
135 | * |
---|
136 | * In examining the set register windows, one may logically divide |
---|
137 | * the windows into sets (some of which may be empty) based on their |
---|
138 | * current status: |
---|
139 | * |
---|
140 | * + current (i.e. in use), |
---|
141 | * + used (i.e. a restore would not trap) |
---|
142 | * + invalid (i.e. 1 in corresponding bit in WIM) |
---|
143 | * + unused |
---|
144 | * |
---|
145 | * Either the used or unused set of windows may be empty. |
---|
146 | * |
---|
147 | * NOTE: We assume only one bit is set in the WIM at a time. |
---|
148 | * |
---|
149 | * Given a CWP of 5 and a WIM of 0x1, the registers are divided |
---|
150 | * into sets as follows: |
---|
151 | * |
---|
152 | * + 0 - invalid |
---|
153 | * + 1-4 - unused |
---|
154 | * + 5 - current |
---|
155 | * + 6-7 - used |
---|
156 | * |
---|
157 | * In this case, we only would save the used windows which we |
---|
158 | * will not be returning to -- 6. |
---|
159 | * |
---|
160 | * Register Usage while saving the windows: |
---|
161 | * g1 = current PSR |
---|
162 | * g2 = current wim |
---|
163 | * g3 = CWP |
---|
164 | * g4 = wim scratch |
---|
165 | * g5 = scratch |
---|
166 | * |
---|
167 | * On entry: |
---|
168 | * |
---|
169 | * l0 = psr (from trap table) |
---|
170 | * l1 = pc |
---|
171 | * l2 = npc |
---|
172 | */ |
---|
173 | |
---|
174 | PUBLIC(window_flush_trap_handler) |
---|
175 | |
---|
176 | SYM(window_flush_trap_handler): |
---|
177 | /* |
---|
178 | * Save the global registers we will be using |
---|
179 | */ |
---|
180 | |
---|
181 | mov %g1, %l3 |
---|
182 | mov %g2, %l4 |
---|
183 | mov %g3, %l5 |
---|
184 | mov %g4, %l6 |
---|
185 | mov %g5, %l7 |
---|
186 | |
---|
187 | mov %l0, %g1 ! g1 = psr |
---|
188 | mov %wim, %g2 ! g2 = wim |
---|
189 | and %l0, SPARC_PSR_CWP_MASK, %g3 ! g3 = CWP |
---|
190 | |
---|
191 | add %g3, 1, %g5 ! g5 = CWP + 1 |
---|
192 | and %g5, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g5 |
---|
193 | |
---|
194 | mov 1, %g4 |
---|
195 | sll %g4, %g5, %g4 ! g4 = WIM mask for CWP+1 invalid |
---|
196 | |
---|
197 | restore ! go back one register window |
---|
198 | |
---|
199 | save_frame_loop: |
---|
200 | sll %g4, 1, %g5 ! rotate the "wim" left 1 |
---|
201 | srl %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4 |
---|
202 | or %g4, %g5, %g4 ! g4 = wim if we do one restore |
---|
203 | |
---|
204 | /* |
---|
205 | * If a restore would not underflow, then continue. |
---|
206 | */ |
---|
207 | |
---|
208 | andcc %g4, %g2, %g0 ! Any windows to flush? |
---|
209 | bnz done_flushing ! No, then continue |
---|
210 | nop |
---|
211 | |
---|
212 | restore ! back one window |
---|
213 | |
---|
214 | /* |
---|
215 | * Now save the window just as if we overflowed to it. |
---|
216 | */ |
---|
217 | |
---|
218 | std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] |
---|
219 | std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] |
---|
220 | std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] |
---|
221 | std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] |
---|
222 | |
---|
223 | std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] |
---|
224 | std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] |
---|
225 | std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] |
---|
226 | std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] |
---|
227 | |
---|
228 | ba save_frame_loop |
---|
229 | nop |
---|
230 | |
---|
231 | done_flushing: |
---|
232 | |
---|
233 | add %g3, 2, %g3 ! calculate desired WIM |
---|
234 | and %g3, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g3 |
---|
235 | mov 1, %g4 |
---|
236 | sll %g4, %g3, %g4 ! g4 = new WIM |
---|
237 | mov %g4, %wim |
---|
238 | |
---|
239 | mov %g1, %psr ! restore PSR |
---|
240 | nop |
---|
241 | nop |
---|
242 | nop |
---|
243 | |
---|
244 | /* |
---|
245 | * Restore the global registers we used |
---|
246 | */ |
---|
247 | |
---|
248 | mov %l3, %g1 |
---|
249 | mov %l4, %g2 |
---|
250 | mov %l5, %g3 |
---|
251 | mov %l6, %g4 |
---|
252 | mov %l7, %g5 |
---|
253 | |
---|
254 | jmpl %l2, %g0 |
---|
255 | rett %l2 + 4 |
---|
256 | |
---|
257 | /* end of file */ |
---|