112027Sjungma@eit.uni-kl.de/* i386.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/* NOTE: double-labeled `_name' and `name' for System V compatability.  */
1612027Sjungma@eit.uni-kl.de/* NOTE: Mixed C/C++-style comments used. Sorry! */
1712027Sjungma@eit.uni-kl.de
1812027Sjungma@eit.uni-kl.de/* Callee-save: %esi, %edi, %ebx, %ebp
1912027Sjungma@eit.uni-kl.de// Caller-save: %eax, %ecx
2012027Sjungma@eit.uni-kl.de// Can't tell: %edx (seems to work w/o saving it.)
2112027Sjungma@eit.uni-kl.de//
2212027Sjungma@eit.uni-kl.de// Assignment:
2312027Sjungma@eit.uni-kl.de//
2412027Sjungma@eit.uni-kl.de// See ``i386.h'' for the somewhat unconventional stack layout.  */
2512027Sjungma@eit.uni-kl.de
2612027Sjungma@eit.uni-kl.de
2712027Sjungma@eit.uni-kl.de	.text
2812027Sjungma@eit.uni-kl.de	.align 2
2912027Sjungma@eit.uni-kl.de
3012027Sjungma@eit.uni-kl.de	.globl _qt_abort
3112027Sjungma@eit.uni-kl.de	.globl qt_abort
3212027Sjungma@eit.uni-kl.de	.globl _qt_block
3312027Sjungma@eit.uni-kl.de	.globl qt_block
3412027Sjungma@eit.uni-kl.de	.globl _qt_blocki
3512027Sjungma@eit.uni-kl.de	.globl qt_blocki
3612027Sjungma@eit.uni-kl.de	.globl _qt_align
3712027Sjungma@eit.uni-kl.de	.globl qt_align
3812027Sjungma@eit.uni-kl.de
3912027Sjungma@eit.uni-kl.de/* These all have the type signature
4012027Sjungma@eit.uni-kl.de//
4112027Sjungma@eit.uni-kl.de//	void *blocking (helper, arg0, arg1, new)
4212027Sjungma@eit.uni-kl.de//
4312027Sjungma@eit.uni-kl.de// On procedure entry, the helper is at 4(sp), args at 8(sp) and
4412027Sjungma@eit.uni-kl.de// 12(sp) and the new thread's sp at 16(sp).  It *appears* that the
4512027Sjungma@eit.uni-kl.de// calling convention for the 8X86 requires the caller to save all
4612027Sjungma@eit.uni-kl.de// floating-point registers, this makes our life easy.  */
4712027Sjungma@eit.uni-kl.de
4812027Sjungma@eit.uni-kl.de/* Halt the currently-running thread.  Save it's callee-save regs on
4912027Sjungma@eit.uni-kl.de// to the stack, 32 bytes.  Switch to the new stack (next == 16+32(sp))
5012027Sjungma@eit.uni-kl.de// and call the user function (f == 4+32(sp) with arguments: old sp
5112027Sjungma@eit.uni-kl.de// arg1 (8+32(sp)) and arg2 (12+32(sp)).  When the user function is
5212027Sjungma@eit.uni-kl.de// done, restore the new thread's state and return.
5312027Sjungma@eit.uni-kl.de//
5412027Sjungma@eit.uni-kl.de// `qt_abort' is (currently) an alias for `qt_block' because most of
5512027Sjungma@eit.uni-kl.de// the work is shared.  We could save the insns up to `qt_common' by
5612027Sjungma@eit.uni-kl.de// replicating, but w/o replicating we need an inital subtract (to
5712027Sjungma@eit.uni-kl.de// offset the stack as if it had been a qt_block) and then a jump
5812027Sjungma@eit.uni-kl.de// to qt_common.  For the cost of a jump, we might as well just do
5912027Sjungma@eit.uni-kl.de// all the work.
6012027Sjungma@eit.uni-kl.de//
6112027Sjungma@eit.uni-kl.de// The helper function (4(sp)) can return a void* that is returned
6212027Sjungma@eit.uni-kl.de// by the call to `qt_blockk{,i}'.  Since we don't touch %eax in
6312027Sjungma@eit.uni-kl.de// between, we get that ``for free''.  */
6412027Sjungma@eit.uni-kl.de
6512027Sjungma@eit.uni-kl.de_qt_abort:
6612027Sjungma@eit.uni-kl.deqt_abort:
6712027Sjungma@eit.uni-kl.de_qt_block:
6812027Sjungma@eit.uni-kl.deqt_block:
6912027Sjungma@eit.uni-kl.de_qt_blocki:
7012027Sjungma@eit.uni-kl.deqt_blocki:
7112027Sjungma@eit.uni-kl.de	pushl %ebp		/* Save callee-save, sp-=4. */
7212027Sjungma@eit.uni-kl.de	pushl %esi		/* Save callee-save, sp-=4. */
7312027Sjungma@eit.uni-kl.de	pushl %edi		/* Save callee-save, sp-=4. */
7412027Sjungma@eit.uni-kl.de	pushl %ebx		/* Save callee-save, sp-=4. */
7512027Sjungma@eit.uni-kl.de	movl %esp, %eax		/* Remember old stack pointer. */
7612027Sjungma@eit.uni-kl.de
7712027Sjungma@eit.uni-kl.deqt_common:
7812027Sjungma@eit.uni-kl.de	movl 32(%esp), %esp	/* Move to new thread. */
7912027Sjungma@eit.uni-kl.de	pushl 28(%eax)		/* Push arg 2. */
8012027Sjungma@eit.uni-kl.de	pushl 24(%eax)		/* Push arg 1. */
8112027Sjungma@eit.uni-kl.de	pushl %eax		/* Push arg 0. */
8212027Sjungma@eit.uni-kl.de	movl 20(%eax), %ebx	/* Get function to call. */
8312027Sjungma@eit.uni-kl.de	call *%ebx		/* Call f. */
8412027Sjungma@eit.uni-kl.de	addl $12, %esp		/* Pop args. */
8512027Sjungma@eit.uni-kl.de
8612027Sjungma@eit.uni-kl.de	popl %ebx		/* Restore callee-save, sp+=4. */
8712027Sjungma@eit.uni-kl.de	popl %edi		/* Restore callee-save, sp+=4. */
8812027Sjungma@eit.uni-kl.de	popl %esi		/* Restore callee-save, sp+=4. */
8912027Sjungma@eit.uni-kl.de	popl %ebp		/* Restore callee-save, sp+=4. */
9012027Sjungma@eit.uni-kl.de_qt_align:
9112027Sjungma@eit.uni-kl.deqt_align:
9212027Sjungma@eit.uni-kl.de	ret			/* Resume the stopped function. */
9312027Sjungma@eit.uni-kl.de
9412027Sjungma@eit.uni-kl.de	.globl _qt_tramp
9512027Sjungma@eit.uni-kl.de	.globl qt_tramp
9612027Sjungma@eit.uni-kl.de_qt_tramp:
9712027Sjungma@eit.uni-kl.deqt_tramp:
9812027Sjungma@eit.uni-kl.de	movl 12(%esp), %eax	/* Load 'qt_error' address */
9912027Sjungma@eit.uni-kl.de	sub $4, %esp		/* Align stack pointer to 16-byte boundary */
10012027Sjungma@eit.uni-kl.de	jmp *%eax		/* call 'qt_error' */
10112027Sjungma@eit.uni-kl.de	hlt			/* 'qt_error' never returns */
10212027Sjungma@eit.uni-kl.de
10312027Sjungma@eit.uni-kl.de/* Start a varargs thread. */
10412027Sjungma@eit.uni-kl.de
10512027Sjungma@eit.uni-kl.de	.globl _qt_vstart
10612027Sjungma@eit.uni-kl.de	.globl qt_vstart
10712027Sjungma@eit.uni-kl.de_qt_vstart:
10812027Sjungma@eit.uni-kl.deqt_vstart:
10912027Sjungma@eit.uni-kl.de	pushl %edi		/* Push `pt' arg to `startup'. */
11012027Sjungma@eit.uni-kl.de	call *%ebp		/* Call `startup'. */
11112027Sjungma@eit.uni-kl.de	popl %eax		/* Clean up the stack. */
11212027Sjungma@eit.uni-kl.de
11312027Sjungma@eit.uni-kl.de	call *%ebx		/* Call the user's function. */
11412027Sjungma@eit.uni-kl.de
11512027Sjungma@eit.uni-kl.de	pushl %eax		/* Push return from user's. */
11612027Sjungma@eit.uni-kl.de	pushl %edi		/* Push `pt' arg to `cleanup'. */
11712027Sjungma@eit.uni-kl.de	call *%esi		/* Call `cleanup'. */
11812027Sjungma@eit.uni-kl.de
11912027Sjungma@eit.uni-kl.de	hlt			/* `cleanup' never returns. */
120