prism2.device: Compiler delint
[AROS.git] / arch / i386-all / exec / stackswap.S
blob34bd10fa83d32928d7692688028fde208e406c86
1 /*
2     Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3     $Id$
4 */
6 /*****************************************************************************
7  
8     NAME
9  
10         AROS_LH1(void, StackSwap,
12     SYNOPSIS
13         AROS_LHA(struct StackSwapStruct *, newStack, A0),
15     LOCATION
16         struct ExecBase *, SysBase, 122, Exec)
18     FUNCTION
19         This function switches to the new stack given by the parameters in the
20         stackswapstruct structure. The old stack parameters are returned in
21         the same structure so that the stack can be restored later
23     INPUTS
24         newStack - parameters for the new stack
26     RESULT
28     NOTES
30     EXAMPLE
32     BUGS
34     SEE ALSO
36     INTERNALS
38     HISTORY
40 ******************************************************************************/
41 #include "aros/i386/asm.h"
42 #include <aros/config.h>
44         .text
45         .globl  AROS_SLIB_ENTRY(StackSwap,Exec,122)
46         _FUNCTION(AROS_SLIB_ENTRY(StackSwap,Exec,122))
47 AROS_SLIB_ENTRY(StackSwap,Exec,122):
48         /* Save %ebx content */
49         pushl   %ebx
51         /* Take the function's parameters; SysBase is in %eax */
52         movl    8(%esp),  %ebx  //newStack
54         /* Disable interrupts, to be sure they always find a good stackframe */
55         call    *Disable(%eax)
57         /* FindTask(NULL) in %edx */
58         movl    ThisTask(%eax), %edx
60         /* Swap Lower boundaries, %ecx is used as temp register */
61         movl    tc_SPLower(%edx), %ecx
62         xchgl   %ecx,             stk_Lower(%ebx)
63         movl    %ecx,             tc_SPLower(%edx)
65         /* Swap Upper boundaries, %ecx is used as temp register */
66         movl    tc_SPUpper(%edx), %ecx
67         xchgl   %ecx,             stk_Upper(%ebx)
68         movl    %ecx,             tc_SPUpper(%edx)
70         movb    tc_Flags(%edx), %cx
71         test    $TF_STACKCHK, %cx
72         je      noStackSnoop
74         /* Fill [stk_Lower .. stk_Pointer - 16] with 0xE1 */
76         pushl   %edi
77         pushl   %eax // SysBase
79         /* Destination register = %edi = NEW SPLower.
80            Which was already swapped above, so to be found
81            in task->tc_SPLower */
82         movl    tc_SPLower(%edx), %edi
84         /* %ecx = count register = NEW SP register - NEW SP_Lower - 16 */
85         movl    stk_Pointer(%ebx), %ecx
86         subl    $16, %ecx
87         subl    %edi, %ecx
89         /* byte value to store */
90         movb    $0xE1, %al
92         /* direction to store: forward */
93         cld
95         /* do the store operation: put %ecx times %al into memory starting at %edi. */
96         rep
97         stosb
99         popl    %eax // SysBase
100         popl    %edi
102 noStackSnoop:
103         /* Now restore %ebx */
104         popl    %ebx
106         /* Pop function's return address and arguments before we swap stacks.
107            This is needed for proper stack balancing (saved value of sp must be
108            caller's stack pointer, right before StackSwap() was called. This way
109            second StackSwap() call will restore the stack to exactly the same state. */
110         popl    %ecx    // return address
111         popl    %edx    // newStack
113         /* Swap stack pointers */
114         xchgl   %esp, stk_Pointer(%edx) 
116         /* Reenable interrupts. */
117         call    *Enable(%eax)
119         /*
120          * Now we should make the top of new stack to look exactly like the
121          * old one. This means it should contain arguments passed to StackSwap(),
122          * because the caller now will want to clear the stack and remove arguments.
123          * Arguments were: newStack. So we need to push it to the new stack.
124          */
125         pushl %edx
127         /* Return. %ecx contains the return address, and the stack is already
128            adjusted, we don't need, or even can, use ret here.  */
129         jmp     *%ecx