mips.s revision 12027:1eb7dc7aa10b
112855Sgabeblack@google.com/* mips.s -- assembly support. */
212855Sgabeblack@google.com
312855Sgabeblack@google.com/*
412855Sgabeblack@google.com * QuickThreads -- Threads-building toolkit.
512855Sgabeblack@google.com * Copyright (c) 1993 by David Keppel
612855Sgabeblack@google.com *
712855Sgabeblack@google.com * Permission to use, copy, modify and distribute this software and
812855Sgabeblack@google.com * its documentation for any purpose and without fee is hereby
912855Sgabeblack@google.com * granted, provided that the above copyright notice and this notice
1012855Sgabeblack@google.com * appear in all copies.  This software is provided as a
1112855Sgabeblack@google.com * proof-of-concept and for demonstration purposes; there is no
1212855Sgabeblack@google.com * representation about the suitability of this software for any
1312855Sgabeblack@google.com * purpose.
1412855Sgabeblack@google.com */
1512855Sgabeblack@google.com
1612855Sgabeblack@google.com/* Callee-save $16-$23, $30-$31.
1712855Sgabeblack@google.com *
1812855Sgabeblack@google.com * On startup, restore regs so retpc === call to a function to start.
1912855Sgabeblack@google.com * We're going to call a function ($4) from within this routine.
2012855Sgabeblack@google.com * We're passing 3 args, therefore need to allocate 12 extra bytes on
2112855Sgabeblack@google.com * the stack for a save area.  The start routine needs a like 16-byte
2212855Sgabeblack@google.com * save area.  Must be doubleword aligned (_mips r3000 risc
2312855Sgabeblack@google.com * architecture_, gerry kane, pg d-23).
2412855Sgabeblack@google.com */
2512855Sgabeblack@google.com
2612855Sgabeblack@google.com	.globl qt_block
2712855Sgabeblack@google.com	.globl qt_blocki
2812855Sgabeblack@google.com	.globl qt_abort
2912855Sgabeblack@google.com	.globl qt_start
3012855Sgabeblack@google.com	.globl qt_vstart
3112855Sgabeblack@google.com
3212855Sgabeblack@google.com	/*
3312855Sgabeblack@google.com	** $4: ptr to function to call once curr is suspended
3412855Sgabeblack@google.com	**	and control is on $7's stack.
3512855Sgabeblack@google.com	** $5: 1'th arg to $4.
3612855Sgabeblack@google.com	** $6: 2'th arg to $4
3712855Sgabeblack@google.com	** $7: sp of thread to suspend.
3812855Sgabeblack@google.com	**
3912855Sgabeblack@google.com	** Totally gross hack: The MIPS calling convention reserves
4012855Sgabeblack@google.com	** 4 words on the stack for a0..a3.  This routine "ought" to
4112855Sgabeblack@google.com	** allocate space for callee-save registers plus 4 words for
4212855Sgabeblack@google.com	** the helper function, but instead we use the 4 words
4312855Sgabeblack@google.com	** provided by the function that called us (we don't need to
4412855Sgabeblack@google.com	** save our argument registers).  So what *appears* to be
4512855Sgabeblack@google.com	** allocating only 40 bytes is actually allocating 56, by
4612855Sgabeblack@google.com	** using the caller's 16 bytes.
4712855Sgabeblack@google.com	**
4812855Sgabeblack@google.com	** The helper routine returns a value that is passed on as the
4912855Sgabeblack@google.com	** return value from the blocking routine.  Since we don't
5012855Sgabeblack@google.com	** touch $2 between the helper's return and the end of
5112855Sgabeblack@google.com	** function, we get this behavior for free.
5212855Sgabeblack@google.com	*/
5312855Sgabeblack@google.comqt_blocki:
5412855Sgabeblack@google.com	sub $sp,$sp,40		/* Allocate reg save space. */
5512855Sgabeblack@google.com	sw $16, 0+16($sp)
5612855Sgabeblack@google.com	sw $17, 4+16($sp)
5712855Sgabeblack@google.com	sw $18, 8+16($sp)
5812855Sgabeblack@google.com	sw $19,12+16($sp)
5912855Sgabeblack@google.com	sw $20,16+16($sp)
6012855Sgabeblack@google.com	sw $21,20+16($sp)
6112855Sgabeblack@google.com	sw $22,24+16($sp)
6212855Sgabeblack@google.com	sw $23,28+16($sp)
6312855Sgabeblack@google.com	sw $30,32+16($sp)
6412855Sgabeblack@google.com	sw $31,36+16($sp)
6512855Sgabeblack@google.com	add $2, $sp,$0		/* $2 <= old sp to pass to func@$4. */
6612855Sgabeblack@google.comqt_abort:
6712855Sgabeblack@google.com	add $sp, $7,$0		/* $sp <= new sp. */
6812855Sgabeblack@google.com	.set noreorder
6912855Sgabeblack@google.com	jal $31,$4		/* Call helper func@$4 . */
7012855Sgabeblack@google.com	add $4, $2,$0		/* $a0 <= pass old sp as a parameter. */
7112855Sgabeblack@google.com	.set reorder
7212855Sgabeblack@google.com	lw $31,36+16($sp)	/* Restore callee-save regs... */
7312855Sgabeblack@google.com	lw $30,32+16($sp)
7412855Sgabeblack@google.com	lw $23,28+16($sp)
7512855Sgabeblack@google.com	lw $22,24+16($sp)
7612855Sgabeblack@google.com	lw $21,20+16($sp)
7712855Sgabeblack@google.com	lw $20,16+16($sp)
7812855Sgabeblack@google.com	lw $19,12+16($sp)
7912855Sgabeblack@google.com	lw $18, 8+16($sp)
8012855Sgabeblack@google.com	lw $17, 4+16($sp)
8112855Sgabeblack@google.com	lw $16, 0+16($sp)	/* Restore callee-save */
8212855Sgabeblack@google.com
8312855Sgabeblack@google.com	add $sp,$sp,40		/* Deallocate reg save space. */
8412855Sgabeblack@google.com	j $31			/* Return to caller. */
8512855Sgabeblack@google.com
8612855Sgabeblack@google.com	/*
8712855Sgabeblack@google.com	** Non-varargs thread startup.
8812855Sgabeblack@google.com	** Note: originally, 56 bytes were allocated on the stack.
8912855Sgabeblack@google.com	** The thread restore routine (_blocki/_abort) removed 40
9012855Sgabeblack@google.com	** of them, which means there is still 16 bytes for the
9112855Sgabeblack@google.com	** argument area required by the MIPS calling convention.
9212855Sgabeblack@google.com	*/
9312855Sgabeblack@google.comqt_start:
9412855Sgabeblack@google.com	add $4, $16,$0		/* Load up user function pu. */
9512855Sgabeblack@google.com	add $5, $17,$0		/* ... user function pt. */
9612855Sgabeblack@google.com	add $6, $18,$0		/* ... user function userf. */
9712855Sgabeblack@google.com	jal $31,$19		/* Call `only'. */
9812855Sgabeblack@google.com	j qt_error
9912855Sgabeblack@google.com
10012855Sgabeblack@google.com
10112855Sgabeblack@google.com	/*
10212855Sgabeblack@google.com	** Save calle-save floating-point regs $f20-$f30
10312855Sgabeblack@google.com	** See comment in `qt_block' about calling conventinos and
10412855Sgabeblack@google.com	** reserved space.  Use the same trick here, but here we
10512855Sgabeblack@google.com	** actually have to allocate all the bytes since we have to
10612855Sgabeblack@google.com	** leave 4 words leftover for `qt_blocki'.
10712855Sgabeblack@google.com	**
10812855Sgabeblack@google.com	** Return value from `qt_block' is the same as the return from
10912855Sgabeblack@google.com	** `qt_blocki'.  We get that for free since we don't touch $2
11012855Sgabeblack@google.com	** between the return from `qt_blocki' and the return from
11112855Sgabeblack@google.com	** `qt_block'.
11212855Sgabeblack@google.com	*/
11312855Sgabeblack@google.comqt_block:
11412855Sgabeblack@google.com	sub $sp, $sp,56		/* 6 8-byte regs, saved ret pc, aligned. */
11512855Sgabeblack@google.com	swc1 $f20,  0+16($sp)
116	swc1 $f22,  8+16($sp)
117	swc1 $f24, 16+16($sp)
118	swc1 $f26, 24+16($sp)
119	swc1 $f28, 32+16($sp)
120	swc1 $f30, 40+16($sp)
121	sw $31, 48+16($sp)
122	jal qt_blocki
123	lwc1 $f20,  0+16($sp)
124	lwc1 $f22,  8+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)
129	lw $31, 48+16($sp)
130	add $sp, $sp,56
131	j $31
132
133
134	/*
135	** First, call `startup' with the `pt' argument.
136	**
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.
142	**
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.
146	*/
147qt_vstart:
148	add $4, $17,$0		/* `pt' is arg0 to `startup'. */
149	jal $31, $18		/* Call `startup'. */
150
151	add $sp, $sp,16		/* Free extra save space. */
152	lw $4,  0($sp)		/* Load up args. */
153	lw $5,  4($sp)
154	lw $6,  8($sp)
155	lw $7, 12($sp)
156	lwc1 $f12, 0($sp)	/* Load up fp args. */
157	lwc1 $f14, 8($sp)
158	jal $31,$19		/* Call `userf'. */
159
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'. */
163
164	j qt_error
165