112027Sjungma@eit.uni-kl.de/* mips.s -- assembly support. */
212027Sjungma@eit.uni-kl.de
312027Sjungma@eit.uni-kl.de/*
412027Sjungma@eit.uni-kl.de * QuickThreads -- Threads-building toolkit.
512027Sjungma@eit.uni-kl.de * Copyright (c) 1993 by David Keppel
612027Sjungma@eit.uni-kl.de *
712027Sjungma@eit.uni-kl.de * Permission to use, copy, modify and distribute this software and
812027Sjungma@eit.uni-kl.de * its documentation for any purpose and without fee is hereby
912027Sjungma@eit.uni-kl.de * granted, provided that the above copyright notice and this notice
1012027Sjungma@eit.uni-kl.de * appear in all copies.  This software is provided as a
1112027Sjungma@eit.uni-kl.de * proof-of-concept and for demonstration purposes; there is no
1212027Sjungma@eit.uni-kl.de * representation about the suitability of this software for any
1312027Sjungma@eit.uni-kl.de * purpose.
1412027Sjungma@eit.uni-kl.de */
1512027Sjungma@eit.uni-kl.de
1612027Sjungma@eit.uni-kl.de/* Callee-save $16-$23, $30-$31.
1712027Sjungma@eit.uni-kl.de *
1812027Sjungma@eit.uni-kl.de * $25 is used as a procedure value pointer, used to discover constants
1912027Sjungma@eit.uni-kl.de * in a callee.  Thus, each caller here sets $25 before the call.
2012027Sjungma@eit.uni-kl.de *
2112027Sjungma@eit.uni-kl.de * On startup, restore regs so retpc === call to a function to start.
2212027Sjungma@eit.uni-kl.de * We're going to call a function ($4) from within this routine.
2312027Sjungma@eit.uni-kl.de * We're passing 3 args, therefore need to allocate 12 extra bytes on
2412027Sjungma@eit.uni-kl.de * the stack for a save area.  The start routine needs a like 16-byte
2512027Sjungma@eit.uni-kl.de * save area.  Must be doubleword aligned (_mips r3000 risc
2612027Sjungma@eit.uni-kl.de * architecture_, gerry kane, pg d-23).
2712027Sjungma@eit.uni-kl.de */
2812027Sjungma@eit.uni-kl.de
2912027Sjungma@eit.uni-kl.de/*
3012027Sjungma@eit.uni-kl.de * Modified by Assar Westerlund <assar@sics.se> to support Irix 5.x
3112027Sjungma@eit.uni-kl.de * calling conventions for dynamically-linked code.
3212027Sjungma@eit.uni-kl.de */
3312027Sjungma@eit.uni-kl.de
3412027Sjungma@eit.uni-kl.de	/* Make this position-independent code. */
3512027Sjungma@eit.uni-kl.de	.option pic2
3612027Sjungma@eit.uni-kl.de
3712027Sjungma@eit.uni-kl.de	.globl qt_block
3812027Sjungma@eit.uni-kl.de	.globl qt_blocki
3912027Sjungma@eit.uni-kl.de	.globl qt_abort
4012027Sjungma@eit.uni-kl.de	.globl qt_start
4112027Sjungma@eit.uni-kl.de	.globl qt_vstart
4212027Sjungma@eit.uni-kl.de
4312027Sjungma@eit.uni-kl.de	/*
4412027Sjungma@eit.uni-kl.de	** $4: ptr to function to call once curr is suspended
4512027Sjungma@eit.uni-kl.de	**	and control is on $7's stack.
4612027Sjungma@eit.uni-kl.de	** $5: 1'th arg to $4.
4712027Sjungma@eit.uni-kl.de	** $6: 2'th arg to $4
4812027Sjungma@eit.uni-kl.de	** $7: sp of thread to suspend.
4912027Sjungma@eit.uni-kl.de	**
5012027Sjungma@eit.uni-kl.de	** Totally gross hack: The MIPS calling convention reserves
5112027Sjungma@eit.uni-kl.de	** 4 words on the stack for a0..a3.  This routine "ought" to
5212027Sjungma@eit.uni-kl.de	** allocate space for callee-save registers plus 4 words for
5312027Sjungma@eit.uni-kl.de	** the helper function, but instead we use the 4 words
5412027Sjungma@eit.uni-kl.de	** provided by the function that called us (we don't need to
5512027Sjungma@eit.uni-kl.de	** save our argument registers).  So what *appears* to be
5612027Sjungma@eit.uni-kl.de	** allocating only 40 bytes is actually allocating 56, by
5712027Sjungma@eit.uni-kl.de	** using the caller's 16 bytes.
5812027Sjungma@eit.uni-kl.de	**
5912027Sjungma@eit.uni-kl.de	** The helper routine returns a value that is passed on as the
6012027Sjungma@eit.uni-kl.de	** return value from the blocking routine.  Since we don't
6112027Sjungma@eit.uni-kl.de	** touch $2 between the helper's return and the end of
6212027Sjungma@eit.uni-kl.de	** function, we get this behavior for free.
6312027Sjungma@eit.uni-kl.de	*/
6412027Sjungma@eit.uni-kl.deqt_blocki:
6512027Sjungma@eit.uni-kl.de	sub $sp,$sp,40		/* Allocate reg save space. */
6612027Sjungma@eit.uni-kl.de	sw $16, 0+16($sp)
6712027Sjungma@eit.uni-kl.de	sw $17, 4+16($sp)
6812027Sjungma@eit.uni-kl.de	sw $18, 8+16($sp)
6912027Sjungma@eit.uni-kl.de	sw $19,12+16($sp)
7012027Sjungma@eit.uni-kl.de	sw $20,16+16($sp)
7112027Sjungma@eit.uni-kl.de	sw $21,20+16($sp)
7212027Sjungma@eit.uni-kl.de	sw $22,24+16($sp)
7312027Sjungma@eit.uni-kl.de	sw $23,28+16($sp)
7412027Sjungma@eit.uni-kl.de	sw $30,32+16($sp)
7512027Sjungma@eit.uni-kl.de	sw $31,36+16($sp)
7612027Sjungma@eit.uni-kl.de	add $2, $sp,$0		/* $2 <= old sp to pass to func@$4. */
7712027Sjungma@eit.uni-kl.deqt_abort:
7812027Sjungma@eit.uni-kl.de	add $sp, $7,$0		/* $sp <= new sp. */
7912027Sjungma@eit.uni-kl.de	.set noreorder
8012027Sjungma@eit.uni-kl.de	add $25, $4,$0		/* Set helper function procedure value. */
8112027Sjungma@eit.uni-kl.de	jal $31,$25		/* Call helper func@$4 . */
8212027Sjungma@eit.uni-kl.de	add $4, $2,$0		/* $a0 <= pass old sp as a parameter. */
8312027Sjungma@eit.uni-kl.de	.set reorder
8412027Sjungma@eit.uni-kl.de	lw $31,36+16($sp)	/* Restore callee-save regs... */
8512027Sjungma@eit.uni-kl.de	lw $30,32+16($sp)
8612027Sjungma@eit.uni-kl.de	lw $23,28+16($sp)
8712027Sjungma@eit.uni-kl.de	lw $22,24+16($sp)
8812027Sjungma@eit.uni-kl.de	lw $21,20+16($sp)
8912027Sjungma@eit.uni-kl.de	lw $20,16+16($sp)
9012027Sjungma@eit.uni-kl.de	lw $19,12+16($sp)
9112027Sjungma@eit.uni-kl.de	lw $18, 8+16($sp)
9212027Sjungma@eit.uni-kl.de	lw $17, 4+16($sp)
9312027Sjungma@eit.uni-kl.de	lw $16, 0+16($sp)	/* Restore callee-save */
9412027Sjungma@eit.uni-kl.de
9512027Sjungma@eit.uni-kl.de	add $sp,$sp,40		/* Deallocate reg save space. */
9612027Sjungma@eit.uni-kl.de	j $31			/* Return to caller. */
9712027Sjungma@eit.uni-kl.de
9812027Sjungma@eit.uni-kl.de	/*
9912027Sjungma@eit.uni-kl.de	** Non-varargs thread startup.
10012027Sjungma@eit.uni-kl.de	** Note: originally, 56 bytes were allocated on the stack.
10112027Sjungma@eit.uni-kl.de	** The thread restore routine (_blocki/_abort) removed 40
10212027Sjungma@eit.uni-kl.de	** of them, which means there is still 16 bytes for the
10312027Sjungma@eit.uni-kl.de	** argument area required by the MIPS calling convention.
10412027Sjungma@eit.uni-kl.de	*/
10512027Sjungma@eit.uni-kl.deqt_start:
10612027Sjungma@eit.uni-kl.de	add $4, $16,$0		/* Load up user function pu. */
10712027Sjungma@eit.uni-kl.de	add $5, $17,$0		/* ... user function pt. */
10812027Sjungma@eit.uni-kl.de	add $6, $18,$0		/* ... user function userf. */
10912027Sjungma@eit.uni-kl.de	add $25, $19,$0		/* Set `only' procedure value. */
11012027Sjungma@eit.uni-kl.de	jal $31,$25		/* Call `only'. */
11112027Sjungma@eit.uni-kl.de	la $25,qt_error		/* Set `qt_error' procedure value. */
11212027Sjungma@eit.uni-kl.de	j $25
11312027Sjungma@eit.uni-kl.de
11412027Sjungma@eit.uni-kl.de
11512027Sjungma@eit.uni-kl.de	/*
11612027Sjungma@eit.uni-kl.de	** Save calle-save floating-point regs $f20-$f30
11712027Sjungma@eit.uni-kl.de	** See comment in `qt_block' about calling conventinos and
11812027Sjungma@eit.uni-kl.de	** reserved space.  Use the same trick here, but here we
11912027Sjungma@eit.uni-kl.de	** actually have to allocate all the bytes since we have to
12012027Sjungma@eit.uni-kl.de	** leave 4 words leftover for `qt_blocki'.
12112027Sjungma@eit.uni-kl.de	**
12212027Sjungma@eit.uni-kl.de	** Return value from `qt_block' is the same as the return from
12312027Sjungma@eit.uni-kl.de	** `qt_blocki'.  We get that for free since we don't touch $2
12412027Sjungma@eit.uni-kl.de	** between the return from `qt_blocki' and the return from
12512027Sjungma@eit.uni-kl.de	** `qt_block'.
12612027Sjungma@eit.uni-kl.de	*/
12712027Sjungma@eit.uni-kl.deqt_block:
12812027Sjungma@eit.uni-kl.de	sub $sp, $sp,56		/* 6 8-byte regs, saved ret pc, aligned. */
12912027Sjungma@eit.uni-kl.de	swc1 $f20,  0+16($sp)
13012027Sjungma@eit.uni-kl.de	swc1 $f22,  8+16($sp)
13112027Sjungma@eit.uni-kl.de	swc1 $f24, 16+16($sp)
13212027Sjungma@eit.uni-kl.de	swc1 $f26, 24+16($sp)
13312027Sjungma@eit.uni-kl.de	swc1 $f28, 32+16($sp)
13412027Sjungma@eit.uni-kl.de	swc1 $f30, 40+16($sp)
13512027Sjungma@eit.uni-kl.de	sw $31, 48+16($sp)
13612027Sjungma@eit.uni-kl.de	jal qt_blocki
13712027Sjungma@eit.uni-kl.de	lwc1 $f20,  0+16($sp)
13812027Sjungma@eit.uni-kl.de	lwc1 $f22,  8+16($sp)
13912027Sjungma@eit.uni-kl.de	lwc1 $f24, 16+16($sp)
14012027Sjungma@eit.uni-kl.de	lwc1 $f26, 24+16($sp)
14112027Sjungma@eit.uni-kl.de	lwc1 $f28, 32+16($sp)
14212027Sjungma@eit.uni-kl.de	lwc1 $f30, 40+16($sp)
14312027Sjungma@eit.uni-kl.de	lw $31, 48+16($sp)
14412027Sjungma@eit.uni-kl.de	add $sp, $sp,56
14512027Sjungma@eit.uni-kl.de	j $31
14612027Sjungma@eit.uni-kl.de
14712027Sjungma@eit.uni-kl.de
14812027Sjungma@eit.uni-kl.de	/*
14912027Sjungma@eit.uni-kl.de	** First, call `startup' with the `pt' argument.
15012027Sjungma@eit.uni-kl.de	**
15112027Sjungma@eit.uni-kl.de	** Next, call the user's function with all arguments.
15212027Sjungma@eit.uni-kl.de	** Note that we don't know whether args were passed in
15312027Sjungma@eit.uni-kl.de	** integer regs, fp regs, or on the stack (See Gerry Kane
15412027Sjungma@eit.uni-kl.de	** "MIPS R2000 RISC Architecture" pg D-22), so we reload
15512027Sjungma@eit.uni-kl.de	** all the registers, possibly with garbage arguments.
15612027Sjungma@eit.uni-kl.de	**
15712027Sjungma@eit.uni-kl.de	** Finally, call `cleanup' with the `pt' argument and with
15812027Sjungma@eit.uni-kl.de	** the return value from the user's function.  It is an error
15912027Sjungma@eit.uni-kl.de	** for `cleanup' to return.
16012027Sjungma@eit.uni-kl.de	*/
16112027Sjungma@eit.uni-kl.deqt_vstart:
16212027Sjungma@eit.uni-kl.de	add $4, $17,$0		/* `pt' is arg0 to `startup'. */
16312027Sjungma@eit.uni-kl.de	add $25, $18,$0		/* Set `startup' procedure value. */
16412027Sjungma@eit.uni-kl.de	jal $31, $25		/* Call `startup'. */
16512027Sjungma@eit.uni-kl.de
16612027Sjungma@eit.uni-kl.de	add $sp, $sp,16		/* Free extra save space. */
16712027Sjungma@eit.uni-kl.de	lw $4,  0($sp)		/* Load up args. */
16812027Sjungma@eit.uni-kl.de	lw $5,  4($sp)
16912027Sjungma@eit.uni-kl.de	lw $6,  8($sp)
17012027Sjungma@eit.uni-kl.de	lw $7, 12($sp)
17112027Sjungma@eit.uni-kl.de	lwc1 $f12, 0($sp)	/* Load up fp args. */
17212027Sjungma@eit.uni-kl.de	lwc1 $f14, 8($sp)
17312027Sjungma@eit.uni-kl.de	add $25, $19,$0		/* Set `userf' procedure value. */
17412027Sjungma@eit.uni-kl.de	jal $31,$25		/* Call `userf'. */
17512027Sjungma@eit.uni-kl.de
17612027Sjungma@eit.uni-kl.de	add $4, $17,$0		/* `pt' is arg0 to `cleanup'. */
17712027Sjungma@eit.uni-kl.de	add $5, $2,$0		/* Ret. val is arg1 to `cleanup'. */
17812027Sjungma@eit.uni-kl.de	add $25, $16,$0		/* Set `cleanup' procedure value. */
17912027Sjungma@eit.uni-kl.de	jal $31, $25		/* Call `cleanup'. */
18012027Sjungma@eit.uni-kl.de
18112027Sjungma@eit.uni-kl.de	la $25,qt_error		/* Set `qt_error' procedure value. */
18212027Sjungma@eit.uni-kl.de	j $25
183