2 Copyright © 1995-2014, 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
, 134, Exec
)
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
;
32 /* Put arguments on stack in appropriate order */
33 for (i
= 7; i
>= 0; i
--)
35 D(bug("[NewStackSwap] Argument %d value 0x%08lX\n", i
, args
->Args
[i
]));
36 _PUSH(sp
, args
->Args
[i
]);
39 if (t
->tc_Flags
& TF_STACKCHK
)
41 volatile UBYTE
* startfill
= sss
->stk_Lower
;
43 while (startfill
< (UBYTE
*)sp
)
48 * We need to Disable() before changing limits and SP, otherwise
49 * stack check will fail if we get interrupted in the middle of this
51 D(bug("[NewStackSwap] SP 0x%p, entry point 0x%p\n", sp
, entry
));
54 /* Change limits. The rest is done in asm below */
55 t
->tc_SPReg
= (APTR
)sp
;
56 t
->tc_SPLower
= sss
->stk_Lower
;
57 t
->tc_SPUpper
= sss
->stk_Upper
;
61 /* Save original ESP by setting up a new stack frame */
63 " movl %%esp, %%ebp\n"
64 /* Actually change the stack */
67 /* Enable(). Pass SysBase in %eax, We don't need %eax afterwards */
70 /* Call our function */
75 * Remember %eax (e.g. %0) and put local SysBase of this function in it.
76 * %3 was clobbered by the called function.
83 /* Restore original ESP. Function's return value is in EAX. */
84 " movl %%ebp, %%esp\n"
87 : "r"(entry
), "r"(sp
), "a"(SysBase
)
88 : "ecx", "edx", "cc");
90 /* Change limits back and return */
92 t
->tc_SPLower
= splower
;
93 t
->tc_SPUpper
= spupper
;
96 D(bug("[NewStackSwap] Returning 0x%08lX\n", ret
));
100 } /* NewStackSwap() */