1 /* mips.s -- assembly support. */
4 * QuickThreads -- Threads-building toolkit.
5 * Copyright (c) 1993 by David Keppel
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
16 /* Callee-save $16-$23, $30-$31.
18 * On startup, restore regs so retpc === call to a function to start.
19 * We're going to call a function ($4) from within this routine.
20 * We're passing 3 args, therefore need to allocate 12 extra bytes on
21 * the stack for a save area. The start routine needs a like 16-byte
22 * save area. Must be doubleword aligned (_mips r3000 risc
23 * architecture_, gerry kane, pg d-23).
33 ** $4: ptr to function to call once curr is suspended
34 ** and control is on $7's stack.
35 ** $5: 1'th arg to $4.
37 ** $7: sp of thread to suspend.
39 ** Totally gross hack: The MIPS calling convention reserves
40 ** 4 words on the stack for a0..a3. This routine "ought" to
41 ** allocate space for callee-save registers plus 4 words for
42 ** the helper function, but instead we use the 4 words
43 ** provided by the function that called us (we don't need to
44 ** save our argument registers). So what *appears* to be
45 ** allocating only 40 bytes is actually allocating 56, by
46 ** using the caller's 16 bytes.
48 ** The helper routine returns a value that is passed on as the
49 ** return value from the blocking routine. Since we don't
50 ** touch $2 between the helper's return and the end of
51 ** function, we get this behavior for free.
54 sub $sp,$sp,40 /* Allocate reg save space. */
65 add $2, $sp,$0 /* $2 <= old sp to pass to func@$4. */
67 add $sp, $7,$0 /* $sp <= new sp. */
69 jal $31,$4 /* Call helper func@$4 . */
70 add $4, $2,$0 /* $a0 <= pass old sp as a parameter. */
72 lw $31,36+16($sp) /* Restore callee-save regs... */
81 lw $16, 0+16($sp) /* Restore callee-save */
83 add $sp,$sp,40 /* Deallocate reg save space. */
84 j $31 /* Return to caller. */
87 ** Non-varargs thread startup.
88 ** Note: originally, 56 bytes were allocated on the stack.
89 ** The thread restore routine (_blocki/_abort) removed 40
90 ** of them, which means there is still 16 bytes for the
91 ** argument area required by the MIPS calling convention.
94 add $4, $16,$0 /* Load up user function pu. */
95 add $5, $17,$0 /* ... user function pt. */
96 add $6, $18,$0 /* ... user function userf. */
97 jal $31,$19 /* Call `only'. */
102 ** Save calle-save floating-point regs $f20-$f30
103 ** See comment in `qt_block' about calling conventinos and
104 ** reserved space. Use the same trick here, but here we
105 ** actually have to allocate all the bytes since we have to
106 ** leave 4 words leftover for `qt_blocki'.
108 ** Return value from `qt_block' is the same as the return from
109 ** `qt_blocki'. We get that for free since we don't touch $2
110 ** between the return from `qt_blocki' and the return from
114 sub $sp, $sp,56 /* 6 8-byte regs, saved ret pc, aligned. */
117 swc1 $f24, 16+16($sp)
118 swc1 $f26, 24+16($sp)
119 swc1 $f28, 32+16($sp)
120 swc1 $f30, 40+16($sp)
125 lwc1 $f24, 16+16($sp)
126 lwc1 $f26, 24+16($sp)
127 lwc1 $f28, 32+16($sp)
128 lwc1 $f30, 40+16($sp)
135 ** First, call `startup' with the `pt' argument.
137 ** Next, call the user's function with all arguments.
138 ** Note that we don't know whether args were passed in
139 ** integer regs, fp regs, or on the stack (See Gerry Kane
140 ** "MIPS R2000 RISC Architecture" pg D-22), so we reload
141 ** all the registers, possibly with garbage arguments.
143 ** Finally, call `cleanup' with the `pt' argument and with
144 ** the return value from the user's function. It is an error
145 ** for `cleanup' to return.
148 add $4, $17,$0 /* `pt' is arg0 to `startup'. */
149 jal $31, $18 /* Call `startup'. */
151 add $sp, $sp,16 /* Free extra save space. */
152 lw $4, 0($sp) /* Load up args. */
156 lwc1 $f12, 0($sp) /* Load up fp args. */
158 jal $31,$19 /* Call `userf'. */
160 add $4, $17,$0 /* `pt' is arg0 to `cleanup'. */
161 add $5, $2,$0 /* Ret. val is arg1 to `cleanup'. */
162 jal $31, $16 /* Call `cleanup'. */