(scm_t_guile_ticket, scm_leave_guile, scm_enter_guile): Removed from
[bpt/guile.git] / qt / md / _sparc.s
1 /* sparc.s -- assembly support for the `qt' thread building kit. */
2
3 /*
4 * QuickThreads -- Threads-building toolkit.
5 * Copyright (c) 1993 by David Keppel
6 *
7 * Permission to use, copy, modify and distribute this software and
8 * its documentation for any purpose and without fee is hereby
9 * granted, provided that the above copyright notice and this notice
10 * appear in all copies. This software is provided as a
11 * proof-of-concept and for demonstration purposes; there is no
12 * representation about the suitability of this software for any
13 * purpose.
14 */
15
16 /* #include <machine/trap.h> */
17
18 .text
19 .align 4
20 .global _qt_blocki
21 .global _qt_block
22 .global _qt_abort
23 .global _qt_start
24 .global _qt_vstart
25
26 /* Register assignment:
27 // %o0: incoming `helper' function to call after cswap
28 // also used as outgoing sp of old thread (qt_t *)
29 // %o1, %o2:
30 // parameters to `helper' function called after cswap
31 // %o3: sp of new thread
32 // %o5: tmp used to save old thread sp, while using %o0
33 // to call `helper' f() after cswap.
34 //
35 //
36 // Aborting a thread is easy if there are no cached register window
37 // frames: just switch to the new stack and away we go. If there are
38 // cached register window frames they must all be written back to the
39 // old stack before we move to the new stack. If we fail to do the
40 // writeback then the old stack memory can be written with register
41 // window contents e.g., after the stack memory has been freed and
42 // reused.
43 //
44 // If you don't believe this, try setting the frame pointer to zero
45 // once we're on the new stack. This will not affect correctnes
46 // otherwise because the frame pointer will eventually get reloaded w/
47 // the new thread's frame pointer. But it will be zero briefly before
48 // the reload. You will eventually (100,000 cswaps later on a small
49 // SPARC machine that I tried) get an illegal instruction trap from
50 // the kernel trying to flush a cached window to location 0x0.
51 //
52 // Solution: flush windows before switching stacks, which invalidates
53 // all the other register windows. We could do the trap
54 // conditionally: if we're in the lowest frame of a thread, the fp is
55 // zero already so we know there's nothing cached. But we expect most
56 // aborts will be done from a first function that does a `save', so we
57 // will rarely save anything and always pay the cost of testing to see
58 // if we should flush.
59 //
60 // All floating-point registers are caller-save, so this routine
61 // doesn't need to do anything to save and restore them.
62 //
63 // `qt_block' and `qt_blocki' return the same value as the value
64 // returned by the helper function. We get this ``for free''
65 // since we don't touch the return value register between the
66 // return from the helper function and return from qt_block{,i}.
67 */
68
69 _qt_block:
70 _qt_blocki:
71 sub %sp, 8, %sp /* Allocate save area for return pc. */
72 st %o7, [%sp+64] /* Save return pc. */
73 _qt_abort:
74 ta 0x03 /* Save locals and ins. */
75 mov %sp, %o5 /* Remember old sp w/o chng ins/locals. */
76 sub %o3, 64, %sp /* Allocate kwsa, switch stacks. */
77 call %o0, 0 /* Call `helper' routine. */
78 mov %o5, %o0 /* Pass old thread to qt_after_t() */
79 /* .. along w/ args in %o1 & %o2. */
80
81 /* Restore callee-save regs. The kwsa
82 // is on this stack, so offset all
83 // loads by sizeof(kwsa), 64 bytes.
84 */
85 ldd [%sp+ 0+64], %l0
86 ldd [%sp+ 8+64], %l2
87 ldd [%sp+16+64], %l4
88 ldd [%sp+24+64], %l6
89 ldd [%sp+32+64], %i0
90 ldd [%sp+40+64], %i2
91 ldd [%sp+48+64], %i4
92 ldd [%sp+56+64], %i6
93 ld [%sp+64+64], %o7 /* Restore return pc. */
94
95 retl /* Return to address in %o7. */
96 add %sp, 72, %sp /* Deallocate kwsa, ret pc area. */
97
98
99 /* The function calling conventions say there has to be a 1-word area
100 // in the caller's stack to hold a pointer to space for aggregate
101 // return values. It also says there should be a 6-word area to hold
102 // %o0..%o5 if the callee wants to save them (why? I don't know...)
103 // Round up to 8 words to maintain alignment.
104 //
105 // Parameter values were stored in callee-save regs and are moved to
106 // the parameter registers.
107 */
108 _qt_start:
109 mov %i1, %o0 /* `pu': Set up args to `only'. */
110 mov %i2, %o1 /* `pt'. */
111 mov %i4, %o2 /* `userf'. */
112 call %i5, 0 /* Call client function. */
113 sub %sp, 32, %sp /* Allocate 6-word callee space. */
114
115 call _qt_error, 0 /* `only' erroniously returned. */
116 nop
117
118
119 /* Same comments as `_qt_start' about allocating rounded-up 7-word
120 // save areas. */
121
122 _qt_vstart:
123 sub %sp, 32, %sp /* Allocate 7-word callee space. */
124 call %i5, 0 /* call `startup'. */
125 mov %i2, %o0 /* .. with argument `pt'. */
126
127 add %sp, 32, %sp /* Use 7-word space in varargs. */
128 ld [%sp+ 4+64], %o0 /* Load arg0 ... */
129 ld [%sp+ 8+64], %o1
130 ld [%sp+12+64], %o2
131 ld [%sp+16+64], %o3
132 ld [%sp+20+64], %o4
133 call %i4, 0 /* Call `userf'. */
134 ld [%sp+24+64], %o5
135
136 /* Use 6-word space in varargs. */
137 mov %o0, %o1 /* Pass return value from userf */
138 call %i3, 0 /* .. when call `cleanup. */
139 mov %i2, %o0 /* .. along with argument `pt'. */
140
141 call _qt_error, 0 /* `cleanup' erroniously returned. */
142 nop