1 | /* Create new context. |
2 | Copyright (C) 2005-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <sysdep.h> |
20 | #include <abort-instr.h> |
21 | |
22 | #include "ucontext_i.h" |
23 | |
24 | /* void __makecontext (ucontext_t *ucp, void (*func)(), int argc, ...); |
25 | __makecontext sets up a stack and registers for context to run a given |
26 | function. The registers are set up like this: |
27 | r4-r7: parameters 1 to 4 |
28 | r8 : uc_link from ucontext structure |
29 | pc : (*func) pointer |
30 | pr : address of exitcode |
31 | r15 : stack pointer for func. */ |
32 | |
33 | .text |
34 | .align 5 |
35 | ENTRY(__makecontext) |
36 | mov #4, r3 |
37 | mov.l @(oSS_SP,r4), r1 /* r1 <- ucb->stack_base */ |
38 | mov.l @(oSS_SIZE,r4), r2 /* r2 <- ucb->stack_size */ |
39 | add r1, r2 /* r2 <- stack_top */ |
40 | cmp/gt r3, r6 /* argc > 4? */ |
41 | bf/s 1f |
42 | shlr2 r2 /* r2 <- stack_top / 4 */ |
43 | sub r6, r2 |
44 | add r3, r2 |
45 | 1: |
46 | shll2 r2 /* r2 <- stack_top - ((argc > 4) ? 4 * (argc - 4) : 0 */ |
47 | mov #oR15, r0 |
48 | mov.l @(oLINK,r4), r1 |
49 | mov.l r2, @(r0,r4) /* ucp->r15 <- r2 */ |
50 | mov.l r1, @(oR8,r4) /* ucp->r8 <- ucp->uc_link */ |
51 | mov #oPC, r0 |
52 | mov.l r5, @(r0,r4) /* ucp->PC <- func */ |
53 | |
54 | cmp/pl r6 /* argc > 0? */ |
55 | bf/s .L1 |
56 | dt r6 |
57 | mov.l r7, @(oR4,r4) /* ucp->r4 <- argv[0] */ |
58 | cmp/pl r6 /* argc > 1? */ |
59 | bf/s .L1 |
60 | dt r6 |
61 | mov.l @(0,r15), r1 |
62 | mov.l r1, @(oR5,r4) /* ucp->r5 <- argv[1] */ |
63 | cmp/pl r6 /* argc > 2? */ |
64 | bf/s .L1 |
65 | dt r6 |
66 | mov.l @(4,r15), r1 |
67 | mov.l r1, @(oR6,r4) /* ucp->r6 <- argv[2] */ |
68 | cmp/pl r6 /* argc > 3? */ |
69 | bf/s .L1 |
70 | dt r6 |
71 | mov.l @(8,r15), r1 |
72 | mov.l r1, @(oR7,r4) /* ucp->r7 <- argv[3] */ |
73 | mov #12,r0 |
74 | .L0: /* Save remaining argv[] on the stack. */ |
75 | cmp/pl r6 |
76 | bf/s .L1 |
77 | dt r6 |
78 | mov.l @(r0,r15), r1 |
79 | mov.l r1, @r2 |
80 | add #4, r0 |
81 | bra .L0 |
82 | add #4, r2 |
83 | .L1: |
84 | #ifdef PIC |
85 | mova .Lexitcode, r0 |
86 | #else |
87 | mov.l .L2, r0 |
88 | #endif |
89 | add #oPR, r4 |
90 | rts |
91 | mov.l r0, @r4 /* ucp->pr <- exitcode */ |
92 | #ifndef PIC |
93 | .align 2 |
94 | .L2: |
95 | .long .Lexitcode |
96 | #endif |
97 | cfi_endproc |
98 | |
99 | .align 5 |
100 | cfi_startproc |
101 | .Lexitcode: |
102 | #ifdef PIC |
103 | mov.l r12, @-r15 |
104 | cfi_adjust_cfa_offset (4) |
105 | cfi_rel_offset (r12, 0) |
106 | mova .Lgot, r0 |
107 | mov.l .Lgot, r12 |
108 | add r0, r12 |
109 | #endif |
110 | tst r8, r8 /* ucb->uc_link == NULL? */ |
111 | bt/s 2f |
112 | mov r8, r4 /* r4 <- ucb->uc_link */ |
113 | mov.l .Lsetcontext, r1 |
114 | sts.l pr, @-r15 |
115 | cfi_adjust_cfa_offset (4) |
116 | cfi_rel_offset (pr, 0) |
117 | #ifdef PIC |
118 | bsrf r1 |
119 | .LPCS0: |
120 | nop |
121 | #else |
122 | jsr @r1 |
123 | nop |
124 | #endif |
125 | /* Restore to keep CFI/CFA balanced. */ |
126 | lds.l @r15+, pr |
127 | cfi_adjust_cfa_offset (-4) |
128 | cfi_restore (pr) |
129 | /* If this returns (which can happen if the syscall fails) we'll exit |
130 | the program with the return error value (-1). */ |
131 | mov r0, r4 |
132 | |
133 | 2: |
134 | mov.l .Lexit, r1 |
135 | #ifdef PIC |
136 | add r12, r1 |
137 | #endif |
138 | jsr @r1 |
139 | nop |
140 | /* The 'exit' call should never return. In case it does cause the |
141 | process to terminate. */ |
142 | ABORT_INSTRUCTION_ASM |
143 | |
144 | .align 2 |
145 | #ifdef PIC |
146 | .Lgot: |
147 | .long _GLOBAL_OFFSET_TABLE_ |
148 | .Lsetcontext: |
149 | .long __setcontext@PLT-(.LPCS0+2-(.)) |
150 | .Lexit: |
151 | .long HIDDEN_JUMPTARGET(exit)@GOTOFF |
152 | #else |
153 | .Lsetcontext: |
154 | .long __setcontext |
155 | .Lexit: |
156 | .long HIDDEN_JUMPTARGET(exit) |
157 | #endif |
158 | PSEUDO_END(__makecontext) |
159 | |
160 | weak_alias (__makecontext, makecontext) |
161 | |