revert between 56095 -> 55830 in arch
[AROS.git] / arch / arm-all / exec / newstackswap.c
blob486fc39f65d50cda9f15c968bb0a31b5196ff534
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: NewStackSwap() - Call a function with swapped stack, ARM version
6 Lang: english
7 */
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)
21 AROS_LIBFUNC_INIT
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;
28 IPTR ret;
30 if (args != NULL)
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]);
38 else
40 /* Dummy args to be put in registers below */
41 args = splower;
44 if (t->tc_Flags & TF_STACKCHK)
46 UBYTE* startfill = sss->stk_Lower;
48 while (startfill < (UBYTE *)sp)
49 *startfill++ = 0xE1;
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));
57 Disable();
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;
64 asm volatile
66 /* Save original SP by adding one more stack frame */
67 " push {fp}\n"
68 " add fp, sp, #4\n"
69 /* Actually change the stack */
70 " mov sp, %2\n"
72 /* Enable(). It preserves all registers by convention. */
73 " mov r0, %4\n"
74 " ldr r12, [r0, #-84]\n"
75 " blx r12\n"
77 /* Call our function with its arguments */
78 " ldr r0, [%3, #0]\n"
79 " ldr r1, [%3, #4]\n"
80 " ldr r2, [%3, #8]\n"
81 " ldr r3, [%3, #12]\n"
82 " blx %1\n"
84 /* Disable(). r0 is first argument, so save it. */
85 " push {r0}\n"
86 " ldr r0, _sysbase\n"
87 " ldr r0, [r0]\n"
88 " ldr r12, [r0, #-80]\n"
89 " blx r12\n"
90 " pop {%0}\n"
92 /* Restore original SP. Function's return value is in %0 now. */
93 " sub sp, fp, #4\n"
94 " pop {fp}\n"
95 : "=r"(ret)
96 : "r"(entry), "r"(sp), "r"(args), "r"(SysBase)
97 : "r0", "r1", "r2", "r3", "r12", "lr", "cc");
99 /* Change limits back and return */
100 t->tc_SPReg = spreg;
101 t->tc_SPLower = splower;
102 t->tc_SPUpper = spupper;
103 Enable();
105 D(bug("[NewStackSwap] Returning 0x%p\n", ret));
106 return ret;
108 AROS_LIBFUNC_EXIT
109 } /* NewStackSwap() */
111 /* Reference to a global SysBase */
112 asm ("_sysbase: .word SysBase");