mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-01 04:10:18 +02:00
108 lines
3.4 KiB
ArmAsm
108 lines
3.4 KiB
ArmAsm
/* i386.s -- assembly support. */
|
|
|
|
/*
|
|
// QuickThreads -- Threads-building toolkit.
|
|
// Copyright (c) 1993 by David Keppel
|
|
//
|
|
// Permission to use, copy, modify and distribute this software and
|
|
// its documentation for any purpose and without fee is hereby
|
|
// granted, provided that the above copyright notice and this notice
|
|
// appear in all copies. This software is provided as a
|
|
// proof-of-concept and for demonstration purposes; there is no
|
|
// representation about the suitability of this software for any
|
|
// purpose. */
|
|
|
|
/* NOTE: double-labeled `_name' and `name' for System V compatability. */
|
|
/* NOTE: Comment lines start like this one, or with '//' ONLY. Sorry! */
|
|
|
|
/* Callee-save: %esi, %edi, %ebx, %ebp
|
|
// Caller-save: %eax, %ecx
|
|
// Can't tell: %edx (seems to work w/o saving it.)
|
|
//
|
|
// Assignment:
|
|
//
|
|
// See ``i386.h'' for the somewhat unconventional stack layout. */
|
|
|
|
|
|
.text
|
|
.align 2
|
|
|
|
.globl _qt_abort
|
|
.globl qt_abort
|
|
.globl _qt_block
|
|
.globl qt_block
|
|
.globl _qt_blocki
|
|
.globl qt_blocki
|
|
|
|
/* These all have the type signature
|
|
//
|
|
// void *blocking (helper, arg0, arg1, new)
|
|
//
|
|
// On procedure entry, the helper is at 4(sp), args at 8(sp) and
|
|
// 12(sp) and the new thread's sp at 16(sp). It *appears* that the
|
|
// calling convention for the 8X86 requires the caller to save all
|
|
// floating-point registers, this makes our life easy. */
|
|
|
|
/* Halt the currently-running thread. Save it's callee-save regs on
|
|
// to the stack, 32 bytes. Switch to the new stack (next == 16+32(sp))
|
|
// and call the user function (f == 4+32(sp) with arguments: old sp
|
|
// arg1 (8+32(sp)) and arg2 (12+32(sp)). When the user function is
|
|
// done, restore the new thread's state and return.
|
|
//
|
|
// `qt_abort' is (currently) an alias for `qt_block' because most of
|
|
// the work is shared. We could save the insns up to `qt_common' by
|
|
// replicating, but w/o replicating we need an inital subtract (to
|
|
// offset the stack as if it had been a qt_block) and then a jump
|
|
// to qt_common. For the cost of a jump, we might as well just do
|
|
// all the work.
|
|
//
|
|
// The helper function (4(sp)) can return a void* that is returned
|
|
// by the call to `qt_blockk{,i}'. Since we don't touch %eax in
|
|
// between, we get that ``for free''. */
|
|
|
|
_qt_abort:
|
|
qt_abort:
|
|
_qt_block:
|
|
qt_block:
|
|
_qt_blocki:
|
|
qt_blocki:
|
|
pushl %ebp /* Save callee-save, sp-=4. */
|
|
pushl %esi /* Save callee-save, sp-=4. */
|
|
pushl %edi /* Save callee-save, sp-=4. */
|
|
pushl %ebx /* Save callee-save, sp-=4. */
|
|
movl %esp, %eax /* Remember old stack pointer. */
|
|
|
|
qt_common:
|
|
movl 32(%esp), %esp /* Move to new thread. */
|
|
pushl 28(%eax) /* Push arg 2. */
|
|
pushl 24(%eax) /* Push arg 1. */
|
|
pushl %eax /* Push arg 0. */
|
|
movl 20(%eax), %ebx /* Get function to call. */
|
|
call *%ebx /* Call f. */
|
|
addl $12, %esp /* Pop args. */
|
|
|
|
popl %ebx /* Restore callee-save, sp+=4. */
|
|
popl %edi /* Restore callee-save, sp+=4. */
|
|
popl %esi /* Restore callee-save, sp+=4. */
|
|
popl %ebp /* Restore callee-save, sp+=4. */
|
|
ret /* Resume the stopped function. */
|
|
hlt
|
|
|
|
|
|
/* Start a varargs thread. */
|
|
|
|
.globl _qt_vstart
|
|
.globl qt_vstart
|
|
_qt_vstart:
|
|
qt_vstart:
|
|
pushl %edi /* Push `pt' arg to `startup'. */
|
|
call *%ebp /* Call `startup'. */
|
|
popl %eax /* Clean up the stack. */
|
|
|
|
call *%ebx /* Call the user's function. */
|
|
|
|
pushl %eax /* Push return from user's. */
|
|
pushl %edi /* Push `pt' arg to `cleanup'. */
|
|
call *%esi /* Call `cleanup'. */
|
|
|
|
hlt /* `cleanup' never returns. */
|