]>
Commit | Line | Data |
---|---|---|
a86a7a39 | 1 | /* Create new context. |
f7a9f785 | 2 | Copyright (C) 2008-2016 Free Software Foundation, Inc. |
a86a7a39 JJ |
3 | This file is part of the GNU C Library. |
4 | Contributed by David S. Miller <davem@davemloft.net>, 2008. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Lesser General Public | |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
17 | License along with the GNU C Library; if not, see |
18 | <http://www.gnu.org/licenses/>. */ | |
a86a7a39 JJ |
19 | |
20 | #include <sysdep.h> | |
21 | #include <stdarg.h> | |
22 | #include <stdint.h> | |
23 | #include <ucontext.h> | |
24 | ||
25 | /* Sets up the outgoing arguments and the program counter for a user | |
26 | context for the requested function call. | |
27 | ||
28 | Returning to the correct parent context is pretty simple on | |
29 | Sparc. We only need to link up the register windows correctly. | |
30 | Since global registers are clobbered by calls, we need not be | |
382466e0 | 31 | concerned about those, and thus is all could be worked out without |
a86a7a39 JJ |
32 | using a trampoline. |
33 | ||
34 | Except that we must deal with the signal mask, thus a trampoline | |
35 | is unavoidable. 32-bit stackframe layout: | |
36 | +-----------------------------------------+ | |
37 | | 7th and further parameters | | |
38 | +-----------------------------------------+ | |
39 | | backup storage for initial 6 parameters | | |
40 | +-----------------------------------------+ | |
41 | | struct return pointer | | |
42 | +-----------------------------------------+ | |
43 | | 8 incoming registers | | |
44 | +-----------------------------------------+ | |
45 | | 8 local registers | | |
46 | %sp --> +-----------------------------------------+ | |
47 | ||
48 | */ | |
49 | ||
50 | void | |
51 | __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) | |
52 | { | |
53 | extern void __start_context (void); | |
54 | unsigned long int *sp; | |
55 | va_list ap; | |
56 | int i; | |
57 | ||
58 | sp = (unsigned long int *) (ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); | |
59 | sp -= 16 + 7 + argc; | |
60 | sp = (unsigned long int *) (((uintptr_t) sp) & ~(8 - 1)); | |
61 | ||
62 | for (i = 0; i < 8; i++) | |
63 | sp[i + 8] = ucp->uc_mcontext.gregs[REG_O0 + i]; | |
64 | ||
65 | /* The struct return pointer is essentially unused, so we can | |
66 | place the link there. */ | |
67 | sp[16] = (unsigned long int) ucp->uc_link; | |
68 | ||
69 | va_start (ap, argc); | |
70 | ||
71 | /* Fill in outgoing arguments, including those which will | |
72 | end up being passed on the stack. */ | |
73 | for (i = 0; i < argc; i++) | |
74 | { | |
75 | unsigned long int arg = va_arg (ap, unsigned long int); | |
76 | if (i < 6) | |
77 | ucp->uc_mcontext.gregs[REG_O0 + i] = arg; | |
78 | else | |
34a407de | 79 | sp[i + 23 - 6] = arg; |
a86a7a39 JJ |
80 | } |
81 | ||
82 | va_end (ap); | |
83 | ||
84 | ucp->uc_mcontext.gregs[REG_O6] = (unsigned long int) sp; | |
85 | ||
86 | ucp->uc_mcontext.gregs[REG_O7] = ((unsigned long int) __start_context) - 8; | |
87 | ||
88 | ucp->uc_mcontext.gregs[REG_PC] = (unsigned long int) func; | |
89 | ucp->uc_mcontext.gregs[REG_nPC] = ucp->uc_mcontext.gregs[REG_PC] + 4; | |
90 | } | |
91 | ||
92 | weak_alias (__makecontext, makecontext) |