Disable optimisation for NewStackSwap(): pc-i386 boots again.
[AROS.git] / arch / i386-all / exec / newstackswap.c
blob8a07d0e520a376958d54f36e460b960c3c763532
1 /*
2 Copyright © 1995-2012, 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 splower = t->tc_SPLower;
27 volatile APTR spupper = t->tc_SPUpper;
28 IPTR ret;
29 BYTE i;
31 /* Put arguments on stack in appropriate order */
32 for (i = 7; i >= 0; i--)
34 D(bug("[NewStackSwap] Argument %d value 0x%08lX\n", i, args->Args[i]));
35 _PUSH(sp, args->Args[i]);
38 if (t->tc_Flags & TF_STACKCHK)
40 volatile UBYTE* startfill = sss->stk_Lower;
42 while (startfill < (UBYTE *)sp)
43 *startfill++ = 0xE1;
47 * We need to Disable() before changing limits and SP, otherwise
48 * stack check will fail if we get interrupted in the middle of this
50 D(bug("[NewStackSwap] SP 0x%p, entry point 0x%p\n", sp, entry));
51 Disable();
53 /* Change limits. The rest is done in asm below */
54 t->tc_SPLower = sss->stk_Lower;
55 t->tc_SPUpper = sss->stk_Upper;
57 asm volatile
59 /* Save original ESP by setting up a new stack frame */
60 " push %%ebp\n"
61 " movl %%esp, %%ebp\n"
62 /* Actually change the stack */
63 " movl %2, %%esp\n\t"
65 /* Enable(). Pass SysBase in %eax, We don't need %eax afterwards */
66 " call *-84(%0)\n"
68 /* Call our function */
69 " call *%1\n"
72 * Disable().
73 * Remember %eax (e.g. %0) and put local SysBase of this function in it.
74 * %3 was clobbered by the called function.
75 */
76 " push %0\n"
77 " movl SysBase, %0\n"
78 " call *-80(%0)\n"
79 " pop %0\n"
81 /* Restore original ESP. Function's return value is in EAX. */
82 " movl %%ebp, %%esp\n"
83 " pop %%ebp\n"
84 : "=a"(ret)
85 : "r"(entry), "r"(sp), "a"(SysBase)
86 : "ecx", "edx", "cc");
88 /* Change limits back and return */
89 t->tc_SPLower = splower;
90 t->tc_SPUpper = spupper;
91 Enable();
93 D(bug("[NewStackSwap] Returning 0x%08lX\n", ret));
94 return ret;
96 AROS_LIBFUNC_EXIT
97 } /* NewStackSwap() */