2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
5 Desc: NewStackSwap() - Call a function with swapped stack.
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
)
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
;
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
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
)
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
));
59 /* Change limits. The rest is done in asm below */
60 t
->tc_SPLower
= sss
->stk_Lower
;
61 t
->tc_SPUpper
= sss
->stk_Upper
;
64 /* Save original ESP to the location reserved before */
65 "movl %%esp, 32(%2)\n\t"
66 /* Actually change the stack */
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"
74 "call *-84(%%ebx)\n\t"
77 /* Call our function */
80 /* Disable(). Also preserves registers. */
81 "movl SysBase, %%ebx\n\t"
83 "call *-80(%%ebx)\n\t"
86 /* Restore original ESP. Function's return value is in EAX. */
87 "movl 32(%%esp), %%esp\n\t"
90 : "ebx", "ecx", "edx", "cc");
92 /* Change limits back and return */
93 t
->tc_SPLower
= splower
;
94 t
->tc_SPUpper
= spupper
;
97 D(bug("[NewStackSwap] Returning 0x%08lX\n", ret
));
101 } /* NewStackSwap() */