revert between 56095 -> 55830 in arch
[AROS.git] / arch / i386-all / exec / newstackswap.c
blobd19d63ac5a1deb31babceb9903fee0a52fc8bbb7
1 /*
2 Copyright © 1995-2014, 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, 134, Exec)
22 AROS_LIBFUNC_INIT
24 volatile struct Task *t = FindTask(NULL);
25 volatile IPTR *sp = sss->stk_Pointer;
26 volatile APTR spreg = t->tc_SPReg;
27 volatile APTR splower = t->tc_SPLower;
28 volatile APTR spupper = t->tc_SPUpper;
29 IPTR ret;
30 BYTE i;
32 /* Put arguments on stack in appropriate order */
33 if (args != NULL)
35 for (i = 7; i >= 0; i--)
37 D(bug("[NewStackSwap] Argument %d value 0x%08lX\n",
38 i, args->Args[i]));
39 _PUSH(sp, args->Args[i]);
43 if (t->tc_Flags & TF_STACKCHK)
45 volatile UBYTE* startfill = sss->stk_Lower;
47 while (startfill < (UBYTE *)sp)
48 *startfill++ = 0xE1;
52 * We need to Disable() before changing limits and SP, otherwise
53 * stack check will fail if we get interrupted in the middle of this
55 D(bug("[NewStackSwap] SP 0x%p, entry point 0x%p\n", sp, entry));
56 Disable();
58 /* Change limits. The rest is done in asm below */
59 t->tc_SPReg = (APTR)sp;
60 t->tc_SPLower = sss->stk_Lower;
61 t->tc_SPUpper = sss->stk_Upper;
63 asm volatile
65 /* Save original ESP by setting up a new stack frame */
66 " push %%ebp\n"
67 " movl %%esp, %%ebp\n"
68 /* Actually change the stack */
69 " movl %2, %%esp\n\t"
71 /* Enable(). Pass SysBase in %eax, We don't need %eax afterwards */
72 " call *-84(%0)\n"
74 /* Call our function */
75 " call *%1\n"
78 * Disable().
79 * Remember %eax (e.g. %0) and put local SysBase of this function in it.
80 * %3 was clobbered by the called function.
81 */
82 " push %0\n"
83 " movl SysBase, %0\n"
84 " call *-80(%0)\n"
85 " pop %0\n"
87 /* Restore original ESP. Function's return value is in EAX. */
88 " movl %%ebp, %%esp\n"
89 " pop %%ebp\n"
90 : "=a"(ret)
91 : "r"(entry), "r"(sp), "a"(SysBase)
92 : "ecx", "edx", "cc");
94 /* Change limits back and return */
95 t->tc_SPReg = spreg;
96 t->tc_SPLower = splower;
97 t->tc_SPUpper = spupper;
98 Enable();
100 D(bug("[NewStackSwap] Returning 0x%08lX\n", ret));
101 return ret;
103 AROS_LIBFUNC_EXIT
104 } /* NewStackSwap() */