revert between 56095 -> 55830 in arch
[AROS.git] / arch / i386-all / exec / stackswap.S
blobcdce95e48d3941a057d6871d3da46034f260d6e9
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         pushl   %eax            /* Arg1: Sysbase */
59         pushl   $0                      /* Arg0: NULL */
60         call    *FindTask(%eax)
61         movl    %eax, %edx      /* ThisTask to %edx */
62         movl    4(%esp), %eax   /* Restore SysBase from stack */
63         addl    $8, %esp        /* Move stack pointer back */
64         /* movl ThisTask(%eax), %edx */
66         /* Swap Lower boundaries, %ecx is used as temp register */
67         movl    tc_SPLower(%edx), %ecx
68         xchgl   %ecx,             stk_Lower(%ebx)
69         movl    %ecx,             tc_SPLower(%edx)
71         /* Swap Upper boundaries, %ecx is used as temp register */
72         movl    tc_SPUpper(%edx), %ecx
73         xchgl   %ecx,             stk_Upper(%ebx)
74         movl    %ecx,             tc_SPUpper(%edx)
76         movb    tc_Flags(%edx), %cx
77         test    $TF_STACKCHK, %cx
78         je      noStackSnoop
80         /* Fill [stk_Lower .. stk_Pointer - 16] with 0xE1 */
82         pushl   %edi
83         pushl   %eax // SysBase
85         /* Destination register = %edi = NEW SPLower.
86            Which was already swapped above, so to be found
87            in task->tc_SPLower */
88         movl    tc_SPLower(%edx), %edi
90         /* %ecx = count register = NEW SP register - NEW SP_Lower - 16 */
91         movl    stk_Pointer(%ebx), %ecx
92         subl    $16, %ecx
93         subl    %edi, %ecx
95         /* byte value to store */
96         movb    $0xE1, %al
98         /* direction to store: forward */
99         cld
101         /* do the store operation: put %ecx times %al into memory starting at %edi. */
102         rep
103         stosb
105         popl    %eax // SysBase
106         popl    %edi
108 noStackSnoop:
109         /* Now restore %ebx */
110         popl    %ebx
112         /* Pop function's return address and arguments before we swap stacks.
113            This is needed for proper stack balancing (saved value of sp must be
114            caller's stack pointer, right before StackSwap() was called. This way
115            second StackSwap() call will restore the stack to exactly the same state. */
116         popl    %ecx    // return address
117         popl    %edx    // newStack
119         /* Swap stack pointers */
120         xchgl   %esp, stk_Pointer(%edx) 
122         /* Reenable interrupts. */
123         call    *Enable(%eax)
125         /*
126          * Now we should make the top of new stack to look exactly like the
127          * old one. This means it should contain arguments passed to StackSwap(),
128          * because the caller now will want to clear the stack and remove arguments.
129          * Arguments were: newStack. So we need to push it to the new stack.
130          */
131         pushl %edx
133         /* Return. %ecx contains the return address, and the stack is already
134            adjusted, we don't need, or even can, use ret here.  */
135         jmp     *%ecx