Correct typo
[AROS.git] / arch / i386-all / exec / newstackswap.c
blobcb02561bf34173478d306bf93316c16ccb9acf82
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: NewStackSwap() - Call a function with swapped stack.
6 Lang: english
7 */
9 #include <aros/config.h>
10 #include <aros/debug.h>
11 #include <exec/tasks.h>
12 #include <proto/exec.h>
14 #define _PUSH(sp, val) *--sp = (IPTR)val
16 AROS_LH3(IPTR, NewStackSwap,
17 AROS_LHA(struct StackSwapStruct *, sss, A0),
18 AROS_LHA(LONG_FUNC, entry, A1),
19 AROS_LHA(struct StackSwapArgs *, args, A2),
20 struct ExecBase *, SysBase, 122, Exec)
22 AROS_LIBFUNC_INIT
24 volatile struct Task *t = FindTask(NULL);
25 volatile IPTR *sp = sss->stk_Pointer;
26 volatile APTR splower = t->tc_SPLower;
27 volatile APTR spupper = t->tc_SPUpper;
28 IPTR ret;
29 BYTE i;
32 * In order to be able to restore the stack after calling the function
33 * we'll need to store original SP on the new stack. So we reserve a
34 * location for it.
36 _PUSH(sp, 0);
37 /* Then put arguments on stack in appropriate order */
38 for (i = 7; i >= 0; i--)
40 D(bug("[NewStackSwap] Argument %d value 0x%08lX\n", i, args->Args[i]));
41 _PUSH(sp, args->Args[i]);
44 if (t->tc_Flags & TF_STACKCHK)
46 UBYTE* startfill = sss->stk_Lower;
48 while (startfill < (UBYTE *)sp)
49 *startfill++ = 0xE1;
53 * We need to Disable() before changing limits and SP, otherwise
54 * stack check will fail if we get interrupted in the middle of this
56 D(bug("[NewStackSwap] SP 0x%p, entry point 0x%p\n", sp, entry));
57 Disable();
59 /* Change limits. The rest is done in asm below */
60 t->tc_SPLower = sss->stk_Lower;
61 t->tc_SPUpper = sss->stk_Upper;
63 asm volatile(
64 /* Save original ESP to the location reserved before */
65 "movl %%esp, 32(%2)\n\t"
66 /* Actually change the stack */
67 "movl %2, %%esp\n\t"
69 /* Enable(). It preserves all registers by convention, so no EAX save/restore.
70 Note also that we use global SysBase here because we are running on the new
71 stack and SysBase is lost. */
72 "movl SysBase, %%ebx\n\t"
73 "push %%ebx\n\t"
74 "call *-84(%%ebx)\n\t"
75 "pop %%ebx\n\t"
77 /* Call our function */
78 "call *%1\n\t"
80 /* Disable(). Also preserves registers. */
81 "movl SysBase, %%ebx\n\t"
82 "push %%ebx\n\t"
83 "call *-80(%%ebx)\n\t"
84 "pop %%ebx\n\t"
86 /* Restore original ESP. Function's return value is in EAX. */
87 "movl 32(%%esp), %%esp\n\t"
88 : "=a"(ret)
89 : "r"(entry), "r"(sp)
90 : "ebx", "ecx", "edx", "cc");
92 /* Change limits back and return */
93 t->tc_SPLower = splower;
94 t->tc_SPUpper = spupper;
95 Enable();
97 D(bug("[NewStackSwap] Returning 0x%08lX\n", ret));
98 return ret;
100 AROS_LIBFUNC_EXIT
101 } /* NewStackSwap() */