1 | /* |
---|
2 | * Copyright (c) 2015 embedded brains GmbH. All rights reserved. |
---|
3 | * |
---|
4 | * embedded brains GmbH |
---|
5 | * Dornierstr. 4 |
---|
6 | * 82178 Puchheim |
---|
7 | * Germany |
---|
8 | * <rtems@embedded-brains.de> |
---|
9 | * |
---|
10 | * The license and distribution terms for this file may be |
---|
11 | * found in the file LICENSE in this distribution or at |
---|
12 | * http://www.rtems.org/license/LICENSE. |
---|
13 | */ |
---|
14 | |
---|
15 | #ifdef HAVE_CONFIG_H |
---|
16 | #include "config.h" |
---|
17 | #endif |
---|
18 | |
---|
19 | #include <rtems/asm.h> |
---|
20 | #include <rtems/score/cpu.h> |
---|
21 | |
---|
22 | #define FRAME_OFFSET_BUFFER (CPU_MINIMUM_STACK_FRAME_SIZE) |
---|
23 | #define FRAME_OFFSET_L0 (FRAME_OFFSET_BUFFER + 0x04) |
---|
24 | #define FRAME_OFFSET_L1 (FRAME_OFFSET_L0 + 0x04) |
---|
25 | #define FRAME_OFFSET_L2 (FRAME_OFFSET_L1 + 0x04) |
---|
26 | #define FRAME_OFFSET_L3 (FRAME_OFFSET_L2 + 0x04) |
---|
27 | #define FRAME_OFFSET_L4 (FRAME_OFFSET_L3 + 0x04) |
---|
28 | #define FRAME_OFFSET_L5 (FRAME_OFFSET_L4 + 0x04) |
---|
29 | #define FRAME_OFFSET_L6 (FRAME_OFFSET_L5 + 0x04) |
---|
30 | #define FRAME_OFFSET_L7 (FRAME_OFFSET_L6 + 0x04) |
---|
31 | #define FRAME_OFFSET_I0 (FRAME_OFFSET_L7 + 0x04) |
---|
32 | #define FRAME_OFFSET_I1 (FRAME_OFFSET_I0 + 0x04) |
---|
33 | #define FRAME_OFFSET_I2 (FRAME_OFFSET_I1 + 0x04) |
---|
34 | #define FRAME_OFFSET_I3 (FRAME_OFFSET_I2 + 0x04) |
---|
35 | #define FRAME_OFFSET_I4 (FRAME_OFFSET_I3 + 0x04) |
---|
36 | #define FRAME_OFFSET_I5 (FRAME_OFFSET_I4 + 0x04) |
---|
37 | #define FRAME_OFFSET_I6 (FRAME_OFFSET_I5 + 0x04) |
---|
38 | #define FRAME_OFFSET_I7 (FRAME_OFFSET_I6 + 0x04) |
---|
39 | #define FRAME_OFFSET_SP (FRAME_OFFSET_I7 + 0x04) |
---|
40 | #define FRAME_END (FRAME_OFFSET_SP + 0x04) |
---|
41 | #define FRAME_SIZE \ |
---|
42 | ((FRAME_END + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1)) |
---|
43 | |
---|
44 | .macro check_register reg |
---|
45 | sub %g1, 1, %g1 |
---|
46 | cmp %g1, \reg |
---|
47 | bne restore_registers |
---|
48 | nop |
---|
49 | .endm |
---|
50 | |
---|
51 | .macro check_float_register reg |
---|
52 | sub %g1, 1, %g1 |
---|
53 | st \reg, [%sp + FRAME_OFFSET_BUFFER] |
---|
54 | ld [%sp + FRAME_OFFSET_BUFFER], %o1 |
---|
55 | cmp %g1, %o1 |
---|
56 | bne restore_registers |
---|
57 | nop |
---|
58 | .endm |
---|
59 | |
---|
60 | .macro check_fsr_register reg |
---|
61 | st \reg, [%sp + FRAME_OFFSET_BUFFER] |
---|
62 | ld [%sp + FRAME_OFFSET_BUFFER], %o1 |
---|
63 | sub %g1, 1, %g1 |
---|
64 | clr %g3 |
---|
65 | sethi %hi(0xCF800000), %g3 |
---|
66 | or %g3, %lo(0x0FFF), %g3 |
---|
67 | and %g1, %g3, %g3 |
---|
68 | and %o1, %g3, %o1 |
---|
69 | cmp %o1, %g3 |
---|
70 | bne restore_registers |
---|
71 | nop |
---|
72 | .endm |
---|
73 | |
---|
74 | .macro write_register reg |
---|
75 | add %g1, 1, %g1 |
---|
76 | mov %g1, \reg |
---|
77 | .endm |
---|
78 | |
---|
79 | .macro write_float_register reg |
---|
80 | add %g1, 1, %g1 |
---|
81 | st %g1, [%sp + FRAME_OFFSET_BUFFER] |
---|
82 | ld [%sp + FRAME_OFFSET_BUFFER], \reg |
---|
83 | .endm |
---|
84 | |
---|
85 | .macro write_fsr_register reg |
---|
86 | st \reg, [%sp + FRAME_OFFSET_BUFFER] |
---|
87 | ld [%sp + FRAME_OFFSET_BUFFER], %o1 |
---|
88 | add %g1, 1, %g1 |
---|
89 | clr %g3 |
---|
90 | |
---|
91 | /* |
---|
92 | * FSR is masked with undefined, reserved or system-specific values |
---|
93 | * (e.g. FPU architecture version, FP queue). |
---|
94 | */ |
---|
95 | sethi %hi(0xCF800000), %g3 |
---|
96 | or %g3, %lo(0x0FFF), %g3 |
---|
97 | and %g1, %g3, %g3 |
---|
98 | or %o1, %g3, %g3 |
---|
99 | st %g3, [%sp + FRAME_OFFSET_BUFFER] |
---|
100 | ld [%sp + FRAME_OFFSET_BUFFER], \reg |
---|
101 | .endm |
---|
102 | |
---|
103 | .align 4 |
---|
104 | PUBLIC(_CPU_Context_validate) |
---|
105 | SYM(_CPU_Context_validate): |
---|
106 | |
---|
107 | /* |
---|
108 | * g2 checks if the Floating Point Unit in the Processor Status |
---|
109 | * Register (PSR) is set. |
---|
110 | */ |
---|
111 | mov %psr, %g2 |
---|
112 | sethi %hi(SPARC_PSR_EF_MASK), %g3 |
---|
113 | and %g2, %g3, %g2 |
---|
114 | |
---|
115 | /* g1 is used to save the original pattern */ |
---|
116 | mov %o0, %g1 |
---|
117 | |
---|
118 | /* g4 establishes window counter */ |
---|
119 | clr %g4 |
---|
120 | |
---|
121 | add %sp, -FRAME_SIZE, %sp |
---|
122 | |
---|
123 | st %l0, [%sp + FRAME_OFFSET_L0] |
---|
124 | st %l1, [%sp + FRAME_OFFSET_L1] |
---|
125 | st %l2, [%sp + FRAME_OFFSET_L2] |
---|
126 | st %l3, [%sp + FRAME_OFFSET_L3] |
---|
127 | st %l4, [%sp + FRAME_OFFSET_L4] |
---|
128 | st %l5, [%sp + FRAME_OFFSET_L5] |
---|
129 | st %l6, [%sp + FRAME_OFFSET_L6] |
---|
130 | st %l7, [%sp + FRAME_OFFSET_L7] |
---|
131 | st %i0, [%sp + FRAME_OFFSET_I0] |
---|
132 | st %i1, [%sp + FRAME_OFFSET_I1] |
---|
133 | st %i2, [%sp + FRAME_OFFSET_I2] |
---|
134 | st %i3, [%sp + FRAME_OFFSET_I3] |
---|
135 | st %i4, [%sp + FRAME_OFFSET_I4] |
---|
136 | st %i5, [%sp + FRAME_OFFSET_I5] |
---|
137 | st %i6, [%sp + FRAME_OFFSET_I6] |
---|
138 | st %i7, [%sp + FRAME_OFFSET_I7] |
---|
139 | st %sp, [%sp + FRAME_OFFSET_SP] |
---|
140 | |
---|
141 | cmp %g4, 0 |
---|
142 | bne write_locals_and_outputs |
---|
143 | nop |
---|
144 | be check_for_fp |
---|
145 | nop |
---|
146 | |
---|
147 | new_check_cycle: |
---|
148 | clr %g4 |
---|
149 | sub %g1, 1, %g1 |
---|
150 | |
---|
151 | /* Write pattern values into registers */ |
---|
152 | |
---|
153 | check_for_fp: |
---|
154 | cmp %g2, 0 |
---|
155 | be write_y |
---|
156 | nop |
---|
157 | |
---|
158 | write_fsr_register %fsr |
---|
159 | write_float_register %f0 |
---|
160 | write_float_register %f1 |
---|
161 | write_float_register %f2 |
---|
162 | write_float_register %f3 |
---|
163 | write_float_register %f4 |
---|
164 | write_float_register %f5 |
---|
165 | write_float_register %f6 |
---|
166 | write_float_register %f7 |
---|
167 | write_float_register %f8 |
---|
168 | write_float_register %f9 |
---|
169 | write_float_register %f10 |
---|
170 | write_float_register %f11 |
---|
171 | write_float_register %f12 |
---|
172 | write_float_register %f13 |
---|
173 | write_float_register %f14 |
---|
174 | write_float_register %f15 |
---|
175 | write_float_register %f16 |
---|
176 | write_float_register %f17 |
---|
177 | write_float_register %f18 |
---|
178 | write_float_register %f19 |
---|
179 | write_float_register %f20 |
---|
180 | write_float_register %f21 |
---|
181 | write_float_register %f22 |
---|
182 | write_float_register %f23 |
---|
183 | write_float_register %f24 |
---|
184 | write_float_register %f25 |
---|
185 | write_float_register %f26 |
---|
186 | write_float_register %f27 |
---|
187 | write_float_register %f28 |
---|
188 | write_float_register %f29 |
---|
189 | write_float_register %f30 |
---|
190 | write_float_register %f31 |
---|
191 | |
---|
192 | write_y: |
---|
193 | write_register %y |
---|
194 | |
---|
195 | write_register %i0 |
---|
196 | write_register %i1 |
---|
197 | write_register %i2 |
---|
198 | write_register %i3 |
---|
199 | write_register %i4 |
---|
200 | write_register %i5 |
---|
201 | /* Don't write register $i6 => frame pointer */ |
---|
202 | /* Don't write register $i7 => return address */ |
---|
203 | b write_locals_and_outputs |
---|
204 | nop |
---|
205 | |
---|
206 | switch_to_next_window: |
---|
207 | save %sp, -FRAME_SIZE, %sp |
---|
208 | |
---|
209 | write_locals_and_outputs: |
---|
210 | /* l0 is used as a scratch register */ |
---|
211 | write_register %l1 |
---|
212 | write_register %l2 |
---|
213 | write_register %l3 |
---|
214 | write_register %l4 |
---|
215 | write_register %l5 |
---|
216 | write_register %l6 |
---|
217 | write_register %l7 |
---|
218 | write_register %o1 |
---|
219 | write_register %o2 |
---|
220 | write_register %o3 |
---|
221 | write_register %o4 |
---|
222 | write_register %o5 |
---|
223 | /* Don't write register $o6 => stack pointer */ |
---|
224 | /* Don't write register $o7 => return address */ |
---|
225 | |
---|
226 | add %g4, 1, %g4 |
---|
227 | cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS |
---|
228 | bne switch_to_next_window |
---|
229 | nop |
---|
230 | |
---|
231 | /* Dummy increment to set up reverse mechanism for checking process */ |
---|
232 | add %g1, 1, %g1 |
---|
233 | clr %g4 |
---|
234 | |
---|
235 | /* Checking begins here */ |
---|
236 | window_checking: |
---|
237 | cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS |
---|
238 | be y_checking |
---|
239 | nop |
---|
240 | |
---|
241 | further_checking: |
---|
242 | cmp %g4, 0 |
---|
243 | bne goto_local_registers |
---|
244 | nop |
---|
245 | |
---|
246 | /* Check normal registers */ |
---|
247 | check_register %o5 |
---|
248 | check_register %o4 |
---|
249 | check_register %o3 |
---|
250 | check_register %o2 |
---|
251 | check_register %o1 |
---|
252 | |
---|
253 | goto_local_registers: |
---|
254 | check_register %l7 |
---|
255 | check_register %l6 |
---|
256 | check_register %l5 |
---|
257 | check_register %l4 |
---|
258 | check_register %l3 |
---|
259 | check_register %l2 |
---|
260 | check_register %l1 |
---|
261 | |
---|
262 | check_register %i5 |
---|
263 | check_register %i4 |
---|
264 | check_register %i3 |
---|
265 | check_register %i2 |
---|
266 | check_register %i1 |
---|
267 | /* |
---|
268 | For the last window i0 also needs to be checked as this variable |
---|
269 | is not overwritten by the outputs of another window. |
---|
270 | */ |
---|
271 | add %g4, 1, %g4 |
---|
272 | cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS |
---|
273 | bne dont_check_i0 |
---|
274 | nop |
---|
275 | check_register %i0 |
---|
276 | b y_checking |
---|
277 | nop |
---|
278 | |
---|
279 | dont_check_i0: |
---|
280 | restore |
---|
281 | |
---|
282 | ba window_checking |
---|
283 | nop |
---|
284 | |
---|
285 | /* Check Y register */ |
---|
286 | y_checking: |
---|
287 | mov %y, %o1 |
---|
288 | check_register %o1 |
---|
289 | cmp %g2, 0 |
---|
290 | be new_check_cycle |
---|
291 | nop |
---|
292 | |
---|
293 | /* Check floating point registers */ |
---|
294 | check_float_register %f31 |
---|
295 | check_float_register %f30 |
---|
296 | check_float_register %f29 |
---|
297 | check_float_register %f28 |
---|
298 | check_float_register %f27 |
---|
299 | check_float_register %f26 |
---|
300 | check_float_register %f25 |
---|
301 | check_float_register %f24 |
---|
302 | check_float_register %f23 |
---|
303 | check_float_register %f22 |
---|
304 | check_float_register %f21 |
---|
305 | check_float_register %f20 |
---|
306 | check_float_register %f19 |
---|
307 | check_float_register %f18 |
---|
308 | check_float_register %f17 |
---|
309 | check_float_register %f16 |
---|
310 | check_float_register %f15 |
---|
311 | check_float_register %f14 |
---|
312 | check_float_register %f13 |
---|
313 | check_float_register %f12 |
---|
314 | check_float_register %f11 |
---|
315 | check_float_register %f10 |
---|
316 | check_float_register %f9 |
---|
317 | check_float_register %f8 |
---|
318 | check_float_register %f7 |
---|
319 | check_float_register %f6 |
---|
320 | check_float_register %f5 |
---|
321 | check_float_register %f4 |
---|
322 | check_float_register %f3 |
---|
323 | check_float_register %f2 |
---|
324 | check_float_register %f1 |
---|
325 | check_float_register %f0 |
---|
326 | check_fsr_register %fsr |
---|
327 | |
---|
328 | be new_check_cycle |
---|
329 | nop |
---|
330 | |
---|
331 | /****** RESTORE STARTS HERE *******/ |
---|
332 | |
---|
333 | /* Restore non-volatile registers */ |
---|
334 | |
---|
335 | restore_registers: |
---|
336 | and %g4, (SPARC_NUMBER_OF_REGISTER_WINDOWS - 1), %g4 |
---|
337 | cmp %g4, 0 |
---|
338 | be real_restore |
---|
339 | nop |
---|
340 | restore |
---|
341 | sub %g4, 1, %g4 |
---|
342 | bne restore_registers |
---|
343 | nop |
---|
344 | |
---|
345 | real_restore: |
---|
346 | ld [%sp + FRAME_OFFSET_L0], %l0 |
---|
347 | ld [%sp + FRAME_OFFSET_L1], %l1 |
---|
348 | ld [%sp + FRAME_OFFSET_L2], %l2 |
---|
349 | ld [%sp + FRAME_OFFSET_L3], %l3 |
---|
350 | ld [%sp + FRAME_OFFSET_L4], %l4 |
---|
351 | ld [%sp + FRAME_OFFSET_L5], %l5 |
---|
352 | ld [%sp + FRAME_OFFSET_L6], %l6 |
---|
353 | ld [%sp + FRAME_OFFSET_L7], %l7 |
---|
354 | ld [%sp + FRAME_OFFSET_I0], %i0 |
---|
355 | ld [%sp + FRAME_OFFSET_I1], %i1 |
---|
356 | ld [%sp + FRAME_OFFSET_I2], %i2 |
---|
357 | ld [%sp + FRAME_OFFSET_I3], %i3 |
---|
358 | ld [%sp + FRAME_OFFSET_I4], %i4 |
---|
359 | ld [%sp + FRAME_OFFSET_I5], %i5 |
---|
360 | ld [%sp + FRAME_OFFSET_I6], %i6 |
---|
361 | ld [%sp + FRAME_OFFSET_I7], %i7 |
---|
362 | |
---|
363 | sub %sp, -FRAME_SIZE, %sp |
---|
364 | |
---|
365 | return_value: |
---|
366 | /* Load callback address and jump back */ |
---|
367 | jmp %o7 + 8 |
---|
368 | add %sp, FRAME_SIZE, %sp |
---|