home *** CD-ROM | disk | FTP | other *** search
- **
- ** StackCall.a
- **
- ** Stack swap routines
- **
- ** Copyright © 1990-1994 by Olaf `Olsen' Barthel
- ** All Rights Reserved
- **
-
- include "exec/types.i"
- include "exec/tasks.i"
- include "exec/memory.i"
- include "exec/execbase.i"
-
- include "dos/dos.i"
- include "dos/dosextens.i"
-
- *----------------------------------------------------------------------
-
- CALL macro
- xref LVO\1
- jsr LVO\1(a6)
- endm
-
- *----------------------------------------------------------------------
-
- ARG_SUCCESS equ 4+5*4
- ARG_STACKSIZE equ ARG_SUCCESS+4
- ARG_ARGCOUNT equ ARG_STACKSIZE+4
- ARG_ROUTINE equ ARG_ARGCOUNT+4
- ARG_ARGS equ ARG_ROUTINE+4
-
- TRUE equ 1
- FALSE equ 0
-
- *----------------------------------------------------------------------
-
- csect text,0,0,1,2
-
- *----------------------------------------------------------------------
-
- xdef StackCall
-
- ; LONG __stdargs StackCall( LONG *Success,
- ; LONG StackSize,
- ; LONG ArgCount,
- ; LONG (* __stdargs Function)(...),
- ; ...);
- ;
- ; Calls a function with parameters on a newly-allocated
- ; stack. Caution: assumes all arguments are 32 bits wide.
-
- StackCall:
-
- movem.l d2/d3/a2/a3/a6,-(sp) ; Save registers
-
- move.l ARG_STACKSIZE(sp),d0 ; Get desired stack size
- add.l #15+StackSwapStruct_SIZEOF,d0 ; Round to next...
- and.l #-16,d0 ; ...quad long word
- move.l d0,d2 ; Save it for later
- move.l #MEMF_PUBLIC,d1 ; Well?
- move.l SysBase(a4),a6 ; Get SysBase
-
- CALL AllocMem ; Allocate the memory
- tst.l d0 ; Successful?
- beq.b 1$ ; Exit if not
-
- move.l d0,a2 ; Remember base address
-
- add.l #StackSwapStruct_SIZEOF,d0 ; Skip the header
- move.l d0,stk_Lower(a2) ; Store the stack lower bound
-
- move.l a2,a3 ; Get the base address
- add.l d2,a3 ; Add the allocation size
- move.l a3,stk_Upper(a2) ; Store the stack upper bound
-
- move.l ARG_ARGCOUNT(sp),d0 ; Get the number of arguments
- beq.b 3$ ; Skip if none
-
- move.l d0,d1
- add.l d1,d1 ; One long word per argument
- add.l d1,d1
- addq.l #4,d1 ; One for predecrement
- sub.l d1,a3 ; Pull it down
-
- subq.l #1,d0 ; Subtract one for DBRA
- lea.l ARG_ARGS(sp),a0 ; Get the source argument list
- move.l a3,a1 ; Get the destination argument list
-
- 2$ move.l (a0)+,(a1)+ ; Copy the parameters
- dbra d0,2$ ; Loop until all is copied
-
- 3$ move.l a3,stk_Pointer(a2) ; Store the new stack pointer
-
- move.l ARG_ROUTINE(sp),a3 ; Get address of the routine to call
-
- move.l a2,a0 ; Swap the stack
- CALL StackSwap
-
- jsr (a3) ; Call the routine
- move.l d0,d3 ; Save the result
-
- move.l a2,a0 ; Swap the stack
- CALL StackSwap
-
- move.l a2,a1 ; Get the base address
- move.l d2,d0 ; Get the allocation length
- CALL FreeMem ; Free the memory
-
- move.l ARG_SUCCESS(sp),a0 ; Flag as success
- move.l #TRUE,(a0)
-
- move.l d3,d0 ; Return the result
-
- movem.l (sp)+,d2/d3/a2/a3/a6 ; Restore registers
- rts
-
- 1$ move.l ARG_SUCCESS(sp),a0 ; Flag as failure
- move.l #FALSE,(a0)
-
- movem.l (sp)+,d2/d3/a2/a3/a6 ; Restore registers
- rts
-
- *----------------------------------------------------------------------
-
- dc.l _BSSBAS
- dc.l _BSSLEN
-
- *----------------------------------------------------------------------
-
- csect __MERGED,data
-
- xref SysBase
-
- xref _BSSBAS
- xref _BSSLEN
-
- *----------------------------------------------------------------------
-
- end
-