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