2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: NewStackSwap() - Call a function with swapped stack, x86-64 version
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 splower
= t
->tc_SPLower
;
27 volatile APTR spupper
= t
->tc_SPUpper
;
30 /* Only last two arguments are put to stack in x86-64 */
31 _PUSH(sp
, args
->Args
[7]);
32 _PUSH(sp
, args
->Args
[6]);
34 if (t
->tc_Flags
& TF_STACKCHK
)
36 UBYTE
* startfill
= sss
->stk_Lower
;
38 while (startfill
< (UBYTE
*)sp
)
43 * We need to Disable() before changing limits and SP, otherwise
44 * stack check will fail if we get interrupted in the middle of this
46 D(bug("[NewStackSwap] SP 0x%p, entry point 0x%p\n", sp
, entry
));
49 /* Change limits. The rest is done in asm below */
50 t
->tc_SPLower
= sss
->stk_Lower
;
51 t
->tc_SPUpper
= sss
->stk_Upper
;
54 /* Save original RSP */
56 "movq %%rsp, %%rbp\n\t"
57 /* Actually change the stack */
60 /* Enable(). It preserves all registers by convention. */
61 "call *-168(%%rdi)\n\t"
63 /* Call our function with its arguments */
64 "movq 0(%3), %%rdi\n\t"
65 "movq 8(%3), %%rsi\n\t"
66 "movq 16(%3), %%rdx\n\t"
67 "movq 24(%3), %%rcx\n\t"
68 "movq 32(%3), %%r8\n\t"
69 "movq 40(%3), %%r9\n\t"
72 /* Disable(). Also preserves registers. */
73 "movabsq $SysBase, %%rdi\n\t"
74 "movq (%%rdi), %%rdi\n\t"
75 "call *-160(%%rdi)\n\t"
77 /* Restore original RSP. Function's return value is in RAX. */
78 "movq %%rbp, %%rsp\n\t"
81 : "r"(entry
), "r"(sp
), "r"(args
), "D"(SysBase
)
82 : "rsi", "rdx", "rcx", "r8", "r9", "cc");
84 /* Change limits back and return */
85 t
->tc_SPLower
= splower
;
86 t
->tc_SPUpper
= spupper
;
89 D(bug("[NewStackSwap] Returning 0x%p\n", ret
));
93 } /* NewStackSwap() */