/[cmucl]/src/lisp/sparc-assem.S
ViewVC logotype

Contents of /src/lisp/sparc-assem.S

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.25 - (show annotations)
Mon Jul 19 23:08:37 2010 UTC (3 years, 8 months ago) by rtoy
Branch: MAIN
CVS Tags: release-20b-pre1, release-20b-pre2, GIT-CONVERSION, cross-sol-x86-merged, RELEASE_20b, cross-sol-x86-base, snapshot-2010-12, snapshot-2010-11, snapshot-2011-09, snapshot-2011-06, snapshot-2011-07, snapshot-2011-04, snapshot-2011-02, snapshot-2011-03, snapshot-2011-01, snapshot-2010-08, cross-sol-x86-2010-12-20, cross-sparc-branch-base, HEAD
Branch point for: cross-sparc-branch, RELEASE-20B-BRANCH, cross-sol-x86-branch
Changes since 1.24: +7 -2 lines
Merge changes from sparc-tramp-assem-2010-07-19.  This moves
closure_tramp and undefined_tramp from the C side to the Lisp side via
Lisp assembly routines.  (Simplifies things quite a bit for sparc.)

Also includes some GC fixes for sparc and ppc to handle moving the pc,
npc, lr, and ctr registers.  They need to be handled like the lip
register.

See bootfiles/20a/boot-2010-07-1-cross.lisp for instructions on how to
bootstrap this change.  A basic cross-compile with a specific cross
bootstrap file is needed.
1
2 #ifdef SOLARIS
3 #define _ASM
4 #include <sys/asm_linkage.h>
5 #include <sys/psw.h>
6 #include <sys/trap.h>
7 #define _current_binding_stack_pointer current_binding_stack_pointer
8 #define _current_control_stack_pointer current_control_stack_pointer
9 #define _current_dynamic_space_free_pointer current_dynamic_space_free_pointer
10 #define _foreign_function_call_active foreign_function_call_active
11 #define _current_control_frame_pointer current_control_frame_pointer
12 #define _call_into_lisp call_into_lisp
13 #define _function_end_breakpoint_end function_end_breakpoint_end
14 #define _closure_tramp closure_tramp
15 #define _undefined_tramp undefined_tramp
16 #define _function_end_breakpoint_trap function_end_breakpoint_trap
17 #define _function_end_breakpoint_guts function_end_breakpoint_guts
18 #define _call_into_c call_into_c
19 #define _flush_icache flush_icache
20 #define _do_pending_interrupt do_pending_interrupt
21 #define _do_dynamic_space_overflow_error do_dynamic_space_overflow_error
22 #define _do_dynamic_space_overflow_warning do_dynamic_space_overflow_warning
23 #ifdef GENCGC
24 /*#define _collect_garbage collect_garbage*/
25 #define _fpu_save fpu_save
26 #define _fpu_restore fpu_restore
27 #endif
28 #ifdef LINKAGE_TABLE
29 #define _resolve_linkage_tramp resolve_linkage_tramp
30 #define _lazy_resolve_linkage lazy_resolve_linkage
31 #define _undefined_foreign_symbol_trap undefined_foreign_symbol_trap
32 #endif
33 #ifdef __STDC__
34 #define FUNCDEF(x) .type x, \#function
35 #else
36 #define FUNCDEF(x) .type x, #function
37 #endif
38 #else
39 #include <machine/asm_linkage.h>
40 #include <machine/psl.h>
41 #include <machine/trap.h>
42 #define FUNCDEF(x) /* nothing */
43 #define SET_SIZE(x) /* nothing */
44 #endif
45
46 #define LANGUAGE_ASSEMBLY
47 #include "lispregs.h"
48 #include "internals.h"
49 #include "globals.h"
50
51 #define load(sym, reg) \
52 sethi %hi(sym), reg; ld [reg+%lo(sym)], reg
53 #define store(reg, sym) \
54 sethi %hi(sym), reg_L0; st reg, [reg_L0+%lo(sym)]
55
56 /*
57 * Our frame size needs to be large enough to hold our window,
58 * the structure return pointer, and some temp space. The temp space
59 * is to hold the 64-bit %o registers that might be converted to %i
60 * registers. A task switch will will not preserve all 64 bits of the
61 * %i registers, so we need to save our %o registers before entering C.
62 * Since %o0 and %o1 contain the return results, we do not have to save
63 * these.
64 */
65 #ifdef v8plus
66 #define FRAMESIZE (SA(WINDOWSIZE+4 + 6*8))
67 #else
68 #define FRAMESIZE (SA(MINFRAME))
69 #endif
70 .seg "text"
71 .global _call_into_lisp
72 FUNCDEF(_call_into_lisp)
73 _call_into_lisp:
74 save %sp, -FRAMESIZE, %sp
75 /* Flush all of C's register windows to the stack. */
76 ta ST_FLUSH_WINDOWS
77
78 /* Save the return address. */
79 st %i7, [%fp-4]
80
81 /* Clear the descriptor regs. (See sparc/vm.lisp) */
82 mov reg_ZERO, reg_A0
83 mov reg_ZERO, reg_A1
84 mov reg_ZERO, reg_A2
85 mov reg_ZERO, reg_A3
86 mov reg_ZERO, reg_A4
87 mov reg_ZERO, reg_A5
88 mov reg_ZERO, reg_OCFP
89 mov reg_ZERO, reg_LRA
90 mov reg_ZERO, reg_CODE
91
92 /* Establish NIL */
93 set NIL, reg_NIL
94
95 /* Set the pseudo-atomic flag. */
96 set pseudo_atomic_Value, reg_ALLOC
97
98 /* Turn off foreign function call. */
99 sethi %hi(_foreign_function_call_active), reg_NL0
100 st reg_ZERO, [reg_NL0+%lo(_foreign_function_call_active)]
101
102 /* Load the rest of lisp state. */
103 load(_current_dynamic_space_free_pointer, reg_NL0)
104 add reg_NL0, reg_ALLOC, reg_ALLOC
105 load(_current_binding_stack_pointer, reg_BSP)
106 load(_current_control_stack_pointer, reg_CSP)
107 load(_current_control_frame_pointer, reg_OCFP)
108
109 /* No longer atomic, and check for interrupt. */
110 andn reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
111 andcc reg_ALLOC, pseudo_atomic_InterruptedValue, reg_ZERO
112 tne trap_PseudoAtomic
113
114 /* Pass in the args. */
115 sll %i2, 2, reg_NARGS
116 mov %i1, reg_CFP
117 mov %i0, reg_LEXENV
118 ld [reg_CFP+0], reg_A0
119 ld [reg_CFP+4], reg_A1
120 ld [reg_CFP+8], reg_A2
121 ld [reg_CFP+12], reg_A3
122 ld [reg_CFP+16], reg_A4
123 ld [reg_CFP+20], reg_A5
124
125 /* Calculate LRA */
126 set lra + type_OtherPointer, reg_LRA
127
128 /* Indirect closure */
129 ld [reg_LEXENV+CLOSURE_FUNCTION_OFFSET], reg_CODE
130
131 jmp reg_CODE+FUNCTION_CODE_OFFSET
132 nop
133
134 .align 8
135 lra:
136 .word type_ReturnPcHeader
137
138 /* Blow off any extra values. */
139 mov reg_OCFP, reg_CSP
140 nop
141
142 /* Return the one value. */
143 mov reg_A0, %i0
144
145 /* Turn on pseudo_atomic */
146 or reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
147
148 /* Store LISP state */
149 andn reg_ALLOC, lowtag_Mask, reg_NL1
150 store(reg_NL1,_current_dynamic_space_free_pointer)
151 store(reg_BSP,_current_binding_stack_pointer)
152 store(reg_CSP,_current_control_stack_pointer)
153 store(reg_CFP,_current_control_frame_pointer)
154
155 /* No longer in Lisp. */
156 store(reg_NL1,_foreign_function_call_active)
157
158 /* Were we interrupted? */
159 andn reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
160 andcc reg_ALLOC, pseudo_atomic_InterruptedValue, reg_ZERO
161 tne trap_PseudoAtomic
162
163 /* Back to C we go. */
164 ld [%sp+FRAMESIZE-4], %i7
165 ret
166 restore %sp, FRAMESIZE, %sp
167 SET_SIZE(_call_into_lisp)
168
169
170
171 .global _call_into_c
172 FUNCDEF(_call_into_c)
173 _call_into_c:
174 #ifdef v8plus
175 stx %o2, [%fp - 8 - 1*8]
176 stx %o3, [%fp - 8 - 2*8]
177 stx %o4, [%fp - 8 - 3*8]
178 stx %o5, [%fp - 8 - 4*8]
179 stx %o6, [%fp - 8 - 5*8]
180 stx %o7, [%fp - 8 - 6*8]
181 #endif
182 /* Build a lisp stack frame */
183 mov reg_CFP, reg_OCFP
184 mov reg_CSP, reg_CFP
185 add reg_CSP, 32, reg_CSP
186 st reg_OCFP, [reg_CFP]
187 st reg_CODE, [reg_CFP+8]
188
189 /* Turn on pseudo-atomic. */
190 or reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
191
192 /* Convert the return address to an offset and save it on the stack. */
193 sub reg_LIP, reg_CODE, reg_L0
194 add reg_L0, type_OtherPointer, reg_L0
195 st reg_L0, [reg_CFP+4]
196
197 /* Store LISP state */
198 store(reg_BSP,_current_binding_stack_pointer)
199 store(reg_CSP,_current_control_stack_pointer)
200 store(reg_CFP,_current_control_frame_pointer)
201
202 /* Use reg_CFP as a work register, and restore it */
203 andn reg_ALLOC, lowtag_Mask, reg_CFP
204 store(reg_CFP,_current_dynamic_space_free_pointer)
205 load(_current_control_frame_pointer, reg_CFP)
206
207 /* No longer in Lisp. */
208 store(reg_CSP,_foreign_function_call_active)
209
210 /* Were we interrupted? */
211 andn reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
212 andcc reg_ALLOC, pseudo_atomic_InterruptedValue, reg_ZERO
213 tne trap_PseudoAtomic
214
215 /* Into C we go. */
216 call reg_CFUNC
217 nop
218
219 /*
220 * Note: C calling conventions (32-bit) say that %o0 and %o1
221 * are used to return function results. In particular 64-bit
222 * results are in %o0 (hi) and %o1 (low).
223 */
224
225 /* Re-establish NIL */
226 set NIL, reg_NIL
227
228 /* Atomic. */
229 set pseudo_atomic_Value, reg_ALLOC
230
231 /* No longer in foreign function call. */
232 sethi %hi(_foreign_function_call_active), reg_NL2
233 st reg_ZERO, [reg_NL2+%lo(_foreign_function_call_active)]
234
235 /* Load the rest of lisp state. */
236 load(_current_dynamic_space_free_pointer, reg_NL2)
237 add reg_NL2, reg_ALLOC, reg_ALLOC
238 load(_current_binding_stack_pointer, reg_BSP)
239 load(_current_control_stack_pointer, reg_CSP)
240 load(_current_control_frame_pointer, reg_CFP)
241
242 /* Get the return address back. */
243 ld [reg_CFP+4], reg_LIP
244 ld [reg_CFP+8], reg_CODE
245 add reg_LIP, reg_CODE, reg_LIP
246 sub reg_LIP, type_OtherPointer, reg_LIP
247
248 /* No longer atomic. */
249 andn reg_ALLOC, pseudo_atomic_Value, reg_ALLOC
250 andcc reg_ALLOC, pseudo_atomic_InterruptedValue, reg_ZERO
251 tne trap_PseudoAtomic
252
253 /* Reset the lisp stack. */
254 /* Note: OCFP is in one of the locals, it gets preserved across C. */
255 mov reg_CFP, reg_CSP
256 mov reg_OCFP, reg_CFP
257
258 #ifdef v8plus
259 ldx [%fp - 8 - 1*8], %o2
260 ldx [%fp - 8 - 2*8], %o3
261 ldx [%fp - 8 - 3*8], %o4
262 ldx [%fp - 8 - 4*8], %o5
263 ldx [%fp - 8 - 5*8], %o6
264 ldx [%fp - 8 - 6*8], %o7
265 #endif
266 /* And back into lisp. */
267 ret
268 nop
269
270 SET_SIZE(_call_into_c)
271
272 #if 0
273 /* undefined_tramp and closure_tramp are now Lisp assembly routines.
274 * so we don't need these anymore. Leave them here for a bit so
275 * we can look at the "real" versions for a while. But eventually,
276 * remove these.
277 */
278 .global _undefined_tramp
279 FUNCDEF(_undefined_tramp)
280 .align 8
281 .byte 0
282 _undefined_tramp:
283 .byte 0, 0, type_FunctionHeader
284 .word _undefined_tramp
285 .word NIL
286 .word NIL
287 .word NIL
288 .word NIL
289
290 b 1f
291 unimp trap_Cerror
292 /* Number of argument bytes */
293 .byte 4
294 .byte UNDEFINED_SYMBOL_ERROR
295 /* Escape to create 16bit number from following two bytes,
296 in little-endian order */
297 .byte 254
298 /* SC_OFFSET(sc_DescriptorReg,reg_FDEFN) */
299 .byte SC_OFFSET_LO(sc_DescriptorReg,reg_FDEFN_NUM)
300 .byte SC_OFFSET_HI(sc_DescriptorReg,reg_FDEFN_NUM)
301
302 .align 4
303 1:
304 ld [reg_FDEFN+FDEFN_RAW_ADDR_OFFSET], reg_CODE
305 jmp reg_CODE+FUNCTION_CODE_OFFSET
306 nop
307 SET_SIZE(_undefined_tramp)
308
309 .global _closure_tramp
310 FUNCDEF(_closure_tramp)
311 .align 8
312 .byte 0
313 _closure_tramp:
314 .byte 0, 0, type_FunctionHeader
315 .word _closure_tramp
316 .word NIL
317 .word NIL
318 .word NIL
319 .word NIL
320
321 ld [reg_FDEFN+FDEFN_FUNCTION_OFFSET], reg_LEXENV
322 ld [reg_LEXENV+CLOSURE_FUNCTION_OFFSET], reg_CODE
323 jmp reg_CODE+FUNCTION_CODE_OFFSET
324 nop
325 SET_SIZE(_closure_tramp)
326 #endif
327
328
329 /*
330 * Function-end breakpoint magic.
331 */
332
333 .text
334 .align 8
335 .global _function_end_breakpoint_guts
336 _function_end_breakpoint_guts:
337 .word type_ReturnPcHeader
338 b 1f
339 nop
340 mov reg_CSP, reg_OCFP
341 add 4, reg_CSP, reg_CSP
342 mov 4, reg_NARGS
343 mov reg_NIL, reg_A1
344 mov reg_NIL, reg_A2
345 mov reg_NIL, reg_A3
346 mov reg_NIL, reg_A4
347 mov reg_NIL, reg_A5
348 1:
349
350 .global _function_end_breakpoint_trap
351 _function_end_breakpoint_trap:
352 unimp trap_FunctionEndBreakpoint
353 b 1b
354 nop
355
356 .global _function_end_breakpoint_end
357 _function_end_breakpoint_end:
358
359 .global _flush_icache
360 FUNCDEF(_flush_icache)
361 _flush_icache:
362 add %o0,%o1,%o2
363 1: iflush %o0 ! flush instruction cache
364 add %o0,8,%o0
365 cmp %o0,%o2
366 blt 1b
367 nop
368 retl ! return from leaf routine
369 nop
370 SET_SIZE(_flush_icache)
371
372 .global _do_pending_interrupt
373 FUNCDEF(_do_pending_interrupt)
374 _do_pending_interrupt:
375 unimp trap_PendingInterrupt
376 retl
377 nop
378 SET_SIZE(_do_pending_interrupt)
379
380 #ifdef trap_DynamicSpaceOverflowError
381 .global _do_dynamic_space_overflow_error
382 FUNCDEF(_do_dynamic_space_overflow_error)
383 _do_dynamic_space_overflow_error:
384 unimp trap_DynamicSpaceOverflowError
385 retl
386 nop
387 SET_SIZE(_do_dynamic_space_overflow_error)
388 #endif
389
390 #ifdef trap_DynamicSpaceOverflowWarning
391 .global _do_dynamic_space_overflow_warning
392 FUNCDEF(_do_dynamic_space_overflow_warning)
393 _do_dynamic_space_overflow_warning:
394 unimp trap_DynamicSpaceOverflowWarning
395 retl
396 nop
397 SET_SIZE(_do_dynamic_space_overflow_warning)
398 #endif
399
400 #ifdef LINKAGE_TABLE
401 /*
402 * Call into C code to resolve a linkage entry.
403 *
404 * We get here by Lisp calling call_into_c with an address of the
405 * desired function which is contained in the register reg_CFUNC (aka
406 * %i4, aka %r28). This is the address of the entry in the linkage
407 * table, which is what we need to figure out what function we really
408 * wanted.
409 *
410 * Note that because we get here from call_into_c, all necessary live
411 * registers have been saved, including FP registers. Hence, no need
412 * to save them.
413 */
414 .global _lazy_resolve_linkage
415 .global _resolve_linkage_tramp
416 FUNCDEF(_resolve_linkage_tramp)
417 _resolve_linkage_tramp:
418 /*
419 * At this point, all of the global %g registers have been
420 * saved by call_into_c, so we can use them as temps. %g2,
421 * aka reg_NIL, aka null-tn is a good choice. reg_L0 contains
422 * the address of the jmpl instruction in the linkage jump
423 * table. (See sparc-arch.c.)
424 */
425
426 mov reg_L0, reg_NIL
427
428 /*
429 * New stack frame so the %o regs become %i. We can't touch
430 * the original %o because they contain the parameters to the
431 * function!
432 */
433 save %sp, -FRAMESIZE, %sp
434
435 /* %g2 tells where we came from in the linkage table */
436 call _lazy_resolve_linkage
437 mov reg_NIL, %o0 ! in the delay slot
438
439 mov %o0, reg_NIL
440 restore %sp, FRAMESIZE, %sp
441
442 /* And away we go! */
443 jmp reg_NIL
444 nop
445
446 SET_SIZE(_resolve_linkage_tramp)
447
448 .global _undefined_foreign_symbol_trap
449 FUNCDEF(_undefined_foreign_symbol_trap)
450 /*
451 * When we get called, %o0 contains the address of the data_vector object
452 * which is a string naming the bad symbol.
453 */
454 _undefined_foreign_symbol_trap:
455 /*
456 Need to restore all the global registers with the Lisp values that
457 were saved away in call_into_c. (This routine is only called from
458 os_link_one_symbol, which is called from resolve_linkage_tramp, which
459 is called from call_into_c.)
460
461 The global registers are volatile across function calls, so who
462 knows what values have been they contain now!
463
464 */
465
466 load(_current_dynamic_space_free_pointer, reg_ALLOC)
467 load(_current_binding_stack_pointer, reg_BSP)
468 load(_current_control_stack_pointer, reg_CSP)
469 load(_current_control_frame_pointer, reg_CFP)
470
471 set NIL, reg_NIL
472
473 mov %o0, reg_A0
474 unimp trap_Error
475 .byte 4 /* Number of argument bytes */
476 .byte UNDEFINED_FOREIGN_SYMBOL_ERROR
477 /* Escape to create 16bit number from following two bytes, in
478 little-endian order */
479 .byte 254
480 .byte SC_OFFSET_LO(sc_DescriptorReg, reg_A0_NUM)
481 .byte SC_OFFSET_HI(sc_DescriptorReg, reg_A0_NUM)
482 .align 4
483
484 #endif
485 /*
486 * Save the FPU state. %o0 contains a pointer to where we can
487 * store our state.
488 */
489
490 /*
491 * Note we only save the 16 double-float registers (which saves
492 * the 32 single-float values too, I think). If we're compiling for
493 * a sparc v9, the Lisp code can actually use all 32 double-float
494 * registers. For later.
495 */
496 .global _fpu_save
497 FUNCDEF(_fpu_save)
498 _fpu_save:
499 std %f0, [%o0 + 4*0]
500 std %f2, [%o0 + 4*2]
501 std %f4, [%o0 + 4*4]
502 std %f6, [%o0 + 4*6]
503 std %f8, [%o0 + 4*8]
504 std %f10, [%o0 + 4*10]
505 std %f12, [%o0 + 4*12]
506 std %f14, [%o0 + 4*14]
507 std %f16, [%o0 + 4*16]
508 std %f18, [%o0 + 4*18]
509 std %f20, [%o0 + 4*20]
510 std %f22, [%o0 + 4*22]
511 std %f24, [%o0 + 4*24]
512 std %f26, [%o0 + 4*26]
513 std %f28, [%o0 + 4*28]
514 std %f30, [%o0 + 4*30]
515 #ifdef FEATURE_SPARC_V9
516 std %f32, [%o0 + 4*32]
517 std %f34, [%o0 + 4*34]
518 std %f36, [%o0 + 4*36]
519 std %f38, [%o0 + 4*38]
520 std %f40, [%o0 + 4*40]
521 std %f42, [%o0 + 4*42]
522 std %f44, [%o0 + 4*44]
523 std %f46, [%o0 + 4*46]
524 std %f48, [%o0 + 4*48]
525 std %f50, [%o0 + 4*50]
526 std %f52, [%o0 + 4*52]
527 std %f54, [%o0 + 4*54]
528 std %f56, [%o0 + 4*56]
529 std %f58, [%o0 + 4*58]
530 std %f60, [%o0 + 4*60]
531 std %f62, [%o0 + 4*62]
532 st %fsr, [%o0 + 4*64]
533 #else
534 st %fsr, [%o0 + 4*32]
535 #endif
536 retl
537 nop
538 SET_SIZE(_fpu_save)
539
540 .global _fpu_restore
541 FUNCDEF(_fpu_restore)
542 _fpu_restore:
543 ldd [%o0 + 4*0], %f0
544 ldd [%o0 + 4*2], %f2
545 ldd [%o0 + 4*4], %f4
546 ldd [%o0 + 4*6], %f6
547 ldd [%o0 + 4*8], %f8
548 ldd [%o0 + 4*10], %f10
549 ldd [%o0 + 4*12], %f12
550 ldd [%o0 + 4*14], %f14
551 ldd [%o0 + 4*16], %f16
552 ldd [%o0 + 4*18], %f18
553 ldd [%o0 + 4*20], %f20
554 ldd [%o0 + 4*22], %f22
555 ldd [%o0 + 4*24], %f24
556 ldd [%o0 + 4*26], %f26
557 ldd [%o0 + 4*28], %f28
558 ldd [%o0 + 4*30], %f30
559 #ifdef FEATURE_SPARC_V9
560 ldd [%o0 + 4*32], %f32
561 ldd [%o0 + 4*34], %f34
562 ldd [%o0 + 4*36], %f36
563 ldd [%o0 + 4*38], %f38
564 ldd [%o0 + 4*40], %f40
565 ldd [%o0 + 4*42], %f42
566 ldd [%o0 + 4*44], %f44
567 ldd [%o0 + 4*46], %f46
568 ldd [%o0 + 4*48], %f48
569 ldd [%o0 + 4*50], %f50
570 ldd [%o0 + 4*52], %f52
571 ldd [%o0 + 4*54], %f54
572 ldd [%o0 + 4*56], %f56
573 ldd [%o0 + 4*58], %f58
574 ldd [%o0 + 4*60], %f60
575 ldd [%o0 + 4*62], %f62
576 ld [%o0 + 4*64], %fsr
577 #else
578 ld [%o0 + 4*32], %fsr
579 #endif
580 retl
581 nop
582 SET_SIZE(_fpu_restore)
583
584 #ifndef SOLARIS
585
586 /****************************************************************\
587 * State saving and restoring.
588 \****************************************************************/
589
590
591 .global _call_on_stack
592 _call_on_stack:
593 call %o0
594 sub %o1, SA(MINFRAME), %sp
595 unimp 0
596
597 .global _save_state
598 _save_state:
599 save %sp, -(SA(8*4)+SA(MINFRAME)), %sp
600 ta ST_FLUSH_WINDOWS
601 st %i7, [%sp+SA(MINFRAME)]
602 st %g1, [%sp+SA(MINFRAME)+4]
603 std %g2, [%sp+SA(MINFRAME)+8]
604 std %g4, [%sp+SA(MINFRAME)+16]
605 std %g6, [%sp+SA(MINFRAME)+24]
606 ! ### Should also save the FP state.
607 mov %i1, %o1
608 call %i0
609 mov %sp, %o0
610 mov %o0, %i0
611 restore_state:
612 ld [%sp+SA(MINFRAME)+4], %g1
613 ldd [%sp+SA(MINFRAME)+8], %g2
614 ldd [%sp+SA(MINFRAME)+16], %g4
615 ldd [%sp+SA(MINFRAME)+24], %g6
616 ret
617 restore
618
619 .global _restore_state
620 _restore_state:
621 ta ST_FLUSH_WINDOWS
622 mov %o0, %fp
623 mov %o1, %i0
624 restore
625 ld [%sp+SA(MINFRAME)], %i7
626 b restore_state
627 mov %o0, %i0
628
629
630
631 /****************************************************************\
632
633 We need our own version of sigtramp.
634
635 \****************************************************************/
636
637 .global __sigtramp, __sigfunc
638 __sigtramp:
639 !
640 ! On entry sp points to:
641 ! 0 - 63: window save area
642 ! 64: signal number
643 ! 68: signal code
644 ! 72: pointer to sigcontext
645 ! 76: addr parameter
646 !
647 ! A sigcontext looks like:
648 #define SC_ONSTACK 0
649 #define SC_MASK 4
650 #define SC_SP 8
651 #define SC_PC 12
652 #define SC_NPC 16
653 #define SC_PSR 20
654 #define SC_G1 24
655 #define SC_O0 28
656 !
657 ! We change sc_g1 to point to a reg save area:
658 #define IREGS_SAVE 0
659 #define FPREGS_SAVE (32*4)
660 #define Y_SAVE (64*4)
661 #define FSR_SAVE (65*4)
662 #define REGSAVESIZE (66*4)
663 !
664 ! After we allocate space for the reg save area, the stack looks like:
665 ! < window save area, etc >
666 #define REGSAVEOFF SA(MINFRAME)
667 #define IREGSOFF REGSAVEOFF+IREGS_SAVE
668 #define FPREGSOFF REGSAVEOFF+FPREGS_SAVE
669 #define YOFF REGSAVEOFF+Y_SAVE
670 #define FSROFF REGSAVEOFF+FSR_SAVE
671 #define ORIGSIGNUMOFF REGSAVEOFF+REGSAVESIZE
672 #define ORIGCODEOFF ORIGSIGNUMOFF+4
673 #define ORIGSCPOFF ORIGSIGNUMOFF+8
674 #define ORIGADDROFF ORIGSIGNUMOFF+12
675
676 ! Allocate space for the reg save area.
677 sub %sp, REGSAVESIZE+SA(MINFRAME)-64, %sp
678
679 ! Save integer registers.
680 ! Note: the globals and outs are good, but the locals and ins have
681 ! been trashed. But luckly, they have been saved on the stack.
682 ! So we need to extract the saved stack pointer from the sigcontext
683 ! to determine where they are.
684 std %g0, [%sp+IREGSOFF]
685 std %g2, [%sp+IREGSOFF+8]
686 std %g4, [%sp+IREGSOFF+16]
687 std %g6, [%sp+IREGSOFF+24]
688 std %o0, [%sp+IREGSOFF+32]
689 std %o2, [%sp+IREGSOFF+40]
690 ld [%sp+ORIGSCPOFF], %o2
691 ld [%o2+SC_SP], %o0
692 std %o4, [%sp+IREGSOFF+48]
693 st %o0, [%sp+IREGSOFF+56]
694 st %o7, [%sp+IREGSOFF+60]
695
696 ldd [%o0], %l0
697 ldd [%o0+8], %l2
698 ldd [%o0+16], %l4
699 ldd [%o0+24], %l6
700 ldd [%o0+32], %i0
701 ldd [%o0+40], %i2
702 ldd [%o0+48], %i4
703 ldd [%o0+56], %i6
704 std %l0, [%sp+IREGSOFF+64]
705 std %l2, [%sp+IREGSOFF+72]
706 std %l4, [%sp+IREGSOFF+80]
707 std %l6, [%sp+IREGSOFF+88]
708 std %i0, [%sp+IREGSOFF+96]
709 std %i2, [%sp+IREGSOFF+104]
710 std %i4, [%sp+IREGSOFF+112]
711 std %i6, [%sp+IREGSOFF+120]
712
713 ! Check to see if we need to save the fp regs.
714 ld [%o2+SC_PSR], %l5 ! get psr
715 set PSR_EF, %l0
716 mov %y, %l2 ! save y
717 btst %l0, %l5 ! is FPU enabled?
718 bz 1f ! if not skip FPU save
719 st %l2, [%sp + YOFF]
720
721 ! save all fpu registers.
722 std %f0, [%sp+FPREGSOFF+(0*4)]
723 std %f2, [%sp+FPREGSOFF+(2*4)]
724 std %f4, [%sp+FPREGSOFF+(4*4)]
725 std %f6, [%sp+FPREGSOFF+(6*4)]
726 std %f8, [%sp+FPREGSOFF+(8*4)]
727 std %f10, [%sp+FPREGSOFF+(10*4)]
728 std %f12, [%sp+FPREGSOFF+(12*4)]
729 std %f14, [%sp+FPREGSOFF+(14*4)]
730 std %f16, [%sp+FPREGSOFF+(16*4)]
731 std %f18, [%sp+FPREGSOFF+(18*4)]
732 std %f20, [%sp+FPREGSOFF+(20*4)]
733 std %f22, [%sp+FPREGSOFF+(22*4)]
734 std %f24, [%sp+FPREGSOFF+(24*4)]
735 std %f26, [%sp+FPREGSOFF+(26*4)]
736 std %f28, [%sp+FPREGSOFF+(28*4)]
737 std %f30, [%sp+FPREGSOFF+(30*4)]
738 st %fsr, [%sp+FSROFF] ! save old fsr
739 1:
740
741 ld [%sp+ORIGSIGNUMOFF], %o0! get signal number
742 set __sigfunc, %g1 ! get array of function ptrs
743 sll %o0, 2, %g2 ! scale signal number for index
744 ld [%g1+%g2], %g1 ! get func
745 ld [%sp+ORIGCODEOFF], %o1 ! get code
746 ! %o2 is already loaded with scp
747 add %sp, REGSAVEOFF, %o3 ! compute pointer to reg save area
748 st %o3, [%o2 + SC_G1] ! save in sc_g1.
749 call %g1 ! (*_sigfunc[sig])(sig,code,scp,addr)
750 ld [%sp+ORIGADDROFF], %o3 ! get addr
751
752 ! Recompute scp, and drop into _sigreturn
753 ld [%sp+ORIGSCPOFF], %o0 ! get scp
754
755 .global _sigreturn
756 _sigreturn:
757 ! Load g1 with addr of reg save area (from sc_g1)
758 ld [%o0+SC_G1], %g1
759
760 ! Move values we cannot restore directory into real sigcontext.
761 ld [%g1+IREGS_SAVE+(4*1)], %l0 ! g1
762 ld [%g1+IREGS_SAVE+(4*8)], %l1 ! o0
763 ld [%g1+IREGS_SAVE+(4*14)], %l2 ! sp
764 st %l0, [%o0+SC_G1]
765 st %l1, [%o0+SC_O0]
766 st %l2, [%o0+SC_SP]
767
768 ld [%o0+SC_PSR], %l2 ! get psr
769 set PSR_EF, %l0
770 ld [%g1+Y_SAVE], %l1 ! restore y
771 btst %l0, %l2 ! is FPU enabled?
772 bz 2f ! if not skip FPU restore
773 mov %l1, %y
774
775 ldd [%g1+FPREGS_SAVE+(0*4)], %f0 ! restore all fpu registers.
776 ldd [%g1+FPREGS_SAVE+(2*4)], %f2
777 ldd [%g1+FPREGS_SAVE+(4*4)], %f4
778 ldd [%g1+FPREGS_SAVE+(6*4)], %f6
779 ldd [%g1+FPREGS_SAVE+(8*4)], %f8
780 ldd [%g1+FPREGS_SAVE+(10*4)], %f10
781 ldd [%g1+FPREGS_SAVE+(12*4)], %f12
782 ldd [%g1+FPREGS_SAVE+(14*4)], %f14
783 ldd [%g1+FPREGS_SAVE+(16*4)], %f16
784 ldd [%g1+FPREGS_SAVE+(18*4)], %f18
785 ldd [%g1+FPREGS_SAVE+(20*4)], %f20
786 ldd [%g1+FPREGS_SAVE+(22*4)], %f22
787 ldd [%g1+FPREGS_SAVE+(24*4)], %f24
788 ldd [%g1+FPREGS_SAVE+(26*4)], %f26
789 ldd [%g1+FPREGS_SAVE+(28*4)], %f28
790 ldd [%g1+FPREGS_SAVE+(30*4)], %f30
791 ld [%g1+FSR_SAVE], %fsr ! restore old fsr
792 2:
793
794 ! The locals and in are restored from the stack, so we have to put
795 ! them there.
796 ld [%o0+SC_SP], %o1
797 ldd [%g1+IREGS_SAVE+(16*4)], %l0
798 ldd [%g1+IREGS_SAVE+(18*4)], %l2
799 ldd [%g1+IREGS_SAVE+(20*4)], %l4
800 ldd [%g1+IREGS_SAVE+(22*4)], %l6
801 ldd [%g1+IREGS_SAVE+(24*4)], %i0
802 ldd [%g1+IREGS_SAVE+(26*4)], %i2
803 ldd [%g1+IREGS_SAVE+(28*4)], %i4
804 ldd [%g1+IREGS_SAVE+(30*4)], %i6
805 std %l0, [%o1+(0*4)]
806 std %l2, [%o1+(2*4)]
807 std %l4, [%o1+(4*4)]
808 std %l6, [%o1+(6*4)]
809 std %i0, [%o1+(8*4)]
810 std %i2, [%o1+(10*4)]
811 std %i4, [%o1+(12*4)]
812 std %i6, [%o1+(14*4)]
813
814 ! Restore the globals and outs. Do not restore %g1, %o0, or %sp
815 ! because they get restored from the sigcontext.
816 ldd [%g1+IREGS_SAVE+(2*4)], %g2
817 ldd [%g1+IREGS_SAVE+(4*4)], %g4
818 ldd [%g1+IREGS_SAVE+(6*4)], %g6
819 ld [%g1+IREGS_SAVE+(9*4)], %o1
820 ldd [%g1+IREGS_SAVE+(10*4)], %o2
821 ldd [%g1+IREGS_SAVE+(12*4)], %o4
822 ld [%g1+IREGS_SAVE+(15*4)], %o7
823
824 set 139, %g1 ! sigcleanup system call
825 t 0
826 unimp 0 ! just in case it returns
827 /*NOTREACHED*/
828
829 #else /* SOLARIS */
830 .global save_context
831 FUNCDEF(save_context)
832 save_context:
833 ta ST_FLUSH_WINDOWS ! flush register windows
834 retl ! return from leaf routine
835 nop
836 SET_SIZE(save_context)
837
838 #endif
839 /*
840 * Local variables:
841 * tab-width: 8
842 * End:
843 */
844

  ViewVC Help
Powered by ViewVC 1.1.5