2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: PrepareContext() - Prepare a task context for dispatch, x86-64 version
9 #include <exec/execbase.h>
10 #include <exec/memory.h>
11 #include <utility/tagitem.h>
12 #include <proto/kernel.h>
13 #include <aros/x86_64/cpucontext.h>
15 #include "exec_intern.h"
16 #include "exec_util.h"
18 extern void TaskExitStub(void);
20 #define _PUSH(sp, val) *--sp = (IPTR)val
22 BOOL
PrepareContext(struct Task
*task
, APTR entryPoint
, APTR fallBack
,
23 const struct TagItem
*tagList
, struct ExecBase
*SysBase
)
26 IPTR
*sp
= task
->tc_SPReg
;
27 struct TagItem
*t
, *tstate
= (struct TagItem
*)tagList
;
28 struct ExceptionContext
*ctx
;
30 if (!(task
->tc_Flags
& TF_ETASK
))
33 ctx
= KrnCreateContext();
34 task
->tc_UnionETask
.tc_ETask
->et_RegFrame
= ctx
;
38 while ((t
= LibNextTagItem(&tstate
)))
43 #define REGARG(x, reg) \
44 case TASKTAG_ARG ## x: \
45 ctx->reg = t->ti_Data; \
49 case TASKTAG_ARG ## x: \
50 args[x - 7] = t->ti_Data; \
65 * 64-bit ABI says that the stack must be 16-byte aligned *BEFORE*
66 * calling a function. When a return address is pushed by call instruction,
67 * the stack loses alignment, the callee knows about it and fixes it up.
68 * Commonly it's fixed automatically by pushing old frame pointer.
69 * A little of magic below ensures proper stack alignment for both entryPoint
70 * and fallBack routines.
72 _PUSH(sp
, 0); /* De-align the stack (this will be RSP value when fallBack is called) */
73 _PUSH(sp
, fallBack
); /* Push real exit code address for TaskExitStub */
76 * Now stacked arguments for entry point. On x86-64 C function gets on stack only
77 * last two arguments, and we always push them both even if they are empty.
78 * This is needed for two reasons:
79 * 1. Keep stack 16-byte-aligned (we can't push only one, for example).
80 * 2. Simplify TaskExitStub, so that it always knows there are two arguments pushed.
86 * Now push the return address. Stack becomes de-aligned here, this will be RSP
87 * value upon entering entryPoint.
88 * TaskExitStub will remove two arguments pushed above and execute 'ret' instruction.
89 * This way fallBack will be called with proper RSP value.
91 _PUSH(sp
, TaskExitStub
);
93 /* Then set up the frame to be used by Dispatch() */
95 ctx
->rip
= (UQUAD
)entryPoint
;
98 /* We return the new stack pointer back to the caller. */
102 } /* PrepareContext() */