2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
5 Desc: NewStackSwap() - Call a function with swapped stack, ARM version
9 #include <aros/debug.h>
10 #include <exec/tasks.h>
11 #include <proto/exec.h>
13 #define _PUSH(sp, val) *--sp = (IPTR)val
15 AROS_LH3(IPTR
, NewStackSwap
,
16 AROS_LHA(struct StackSwapStruct
*, sss
, A0
),
17 AROS_LHA(LONG_FUNC
, entry
, A1
),
18 AROS_LHA(struct StackSwapArgs
*, args
, A2
),
19 struct ExecBase
*, SysBase
, 134, Exec
)
23 volatile struct Task
*t
= FindTask(NULL
);
24 volatile IPTR
*sp
= sss
->stk_Pointer
;
25 volatile APTR spreg
= t
->tc_SPReg
;
26 volatile APTR splower
= t
->tc_SPLower
;
27 volatile APTR spupper
= t
->tc_SPUpper
;
32 /* Only last four arguments are put to stack in ARM */
33 _PUSH(sp
, args
->Args
[7]);
34 _PUSH(sp
, args
->Args
[6]);
35 _PUSH(sp
, args
->Args
[5]);
36 _PUSH(sp
, args
->Args
[4]);
40 /* Dummy args to be put in registers below */
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_SPReg
= (APTR
)sp
;
61 t
->tc_SPLower
= sss
->stk_Lower
;
62 t
->tc_SPUpper
= sss
->stk_Upper
;
66 /* Save original SP by adding one more stack frame */
69 /* Actually change the stack */
72 /* Enable(). It preserves all registers by convention. */
74 " ldr r12, [r0, #-84]\n"
77 /* Call our function with its arguments */
81 " ldr r3, [%3, #12]\n"
84 /* Disable(). r0 is first argument, so save it. */
88 " ldr r12, [r0, #-80]\n"
92 /* Restore original SP. Function's return value is in %0 now. */
96 : "r"(entry
), "r"(sp
), "r"(args
), "r"(SysBase
)
97 : "r0", "r1", "r2", "r3", "r12", "lr", "cc");
99 /* Change limits back and return */
101 t
->tc_SPLower
= splower
;
102 t
->tc_SPUpper
= spupper
;
105 D(bug("[NewStackSwap] Returning 0x%p\n", ret
));
109 } /* NewStackSwap() */
111 /* Reference to a global SysBase */
112 asm ("_sysbase: .word SysBase");