1 | /* Modify saved context. |
2 | Copyright (C) 2009-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 <sys/asm.h> |
21 | #include <sys/fpregdef.h> |
22 | #include <sys/regdef.h> |
23 | |
24 | #include "ucontext_i.h" |
25 | |
26 | /* int makecontext (ucontext_t *ucp, (void *func) (), int argc, ...) */ |
27 | |
28 | .text |
29 | .set nomips16 |
30 | LOCALSZ = 0 |
31 | ARGSZ = 0 |
32 | MASK = 0x00000000 |
33 | #ifdef __PIC__ |
34 | LOCALSZ = 1 /* save gp */ |
35 | #endif |
36 | #if _MIPS_SIM != _ABIO32 |
37 | ARGSZ = 5 /* save a3-a7 */ |
38 | # ifdef __PIC__ |
39 | MASK = 0x10000000 |
40 | # endif |
41 | #endif |
42 | FRAMESZ = (((ARGSZ + LOCALSZ) * SZREG) + ALSZ) & ALMASK |
43 | GPOFF = FRAMESZ - ((ARGSZ + 1) * SZREG) |
44 | #if _MIPS_SIM != _ABIO32 |
45 | A3OFF = FRAMESZ - (5 * SZREG) /* callee-allocated */ |
46 | A4OFF = FRAMESZ - (4 * SZREG) |
47 | A5OFF = FRAMESZ - (3 * SZREG) |
48 | A6OFF = FRAMESZ - (2 * SZREG) |
49 | A7OFF = FRAMESZ - (1 * SZREG) |
50 | NARGREGS = 8 |
51 | #else |
52 | A3OFF = FRAMESZ + (3 * SZREG) /* caller-allocated */ |
53 | NARGREGS = 4 |
54 | #endif |
55 | MCONTEXT_GREGSZ = 8 |
56 | #if _MIPS_SIM == _ABIO32 && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
57 | MCONTEXT_GREGOFF = 4 |
58 | #else |
59 | MCONTEXT_GREGOFF = 0 |
60 | #endif |
61 | |
62 | NESTED (__makecontext, FRAMESZ, ra) |
63 | .mask MASK, -(ARGSZ * SZREG) |
64 | .fmask 0x00000000, 0 |
65 | |
66 | 98: |
67 | #ifdef __PIC__ |
68 | SETUP_GP |
69 | #endif |
70 | |
71 | PTR_ADDIU sp, -FRAMESZ |
72 | cfi_adjust_cfa_offset (FRAMESZ) |
73 | |
74 | #ifdef __PIC__ |
75 | SETUP_GP64_STACK (GPOFF, __makecontext) |
76 | SAVE_GP (GPOFF) |
77 | #endif |
78 | |
79 | #ifdef PROF |
80 | .set noat |
81 | move AT, ra |
82 | jal _mcount |
83 | .set at |
84 | #endif |
85 | |
86 | /* Store args to be passed. */ |
87 | REG_S a3, A3OFF(sp) |
88 | #if _MIPS_SIM != _ABIO32 |
89 | REG_S a4, A4OFF(sp) |
90 | REG_S a5, A5OFF(sp) |
91 | REG_S a6, A6OFF(sp) |
92 | REG_S a7, A7OFF(sp) |
93 | #endif |
94 | |
95 | /* Set up the stack. */ |
96 | PTR_L t0, STACK_SP(a0) |
97 | PTR_L t2, STACK_SIZE(a0) |
98 | PTR_ADDIU t1, sp, A3OFF |
99 | PTR_ADDU t0, t2 |
100 | and t0, ALMASK |
101 | blez a2, 2f /* no arguments */ |
102 | |
103 | /* Store register arguments. */ |
104 | PTR_ADDIU t2, a0, MCONTEXT_GREGS + 4 * MCONTEXT_GREGSZ + MCONTEXT_GREGOFF |
105 | move t3, zero |
106 | 0: |
107 | addiu t3, 1 |
108 | REG_L v1, (t1) |
109 | PTR_ADDIU t1, SZREG |
110 | REG_S v1, (t2) |
111 | PTR_ADDIU t2, MCONTEXT_GREGSZ |
112 | bgeu t3, a2, 2f /* all done */ |
113 | bltu t3, NARGREGS, 0b /* next */ |
114 | |
115 | /* Make room for stack arguments. */ |
116 | PTR_SUBU t2, a2, t3 |
117 | PTR_SLL t2, 3 |
118 | PTR_SUBU t0, t2 |
119 | and t0, ALMASK |
120 | |
121 | /* Store stack arguments. */ |
122 | move t2, t0 |
123 | 1: |
124 | addiu t3, 1 |
125 | REG_L v1, (t1) |
126 | PTR_ADDIU t1, SZREG |
127 | REG_S v1, (t2) |
128 | PTR_ADDIU t2, SZREG |
129 | bltu t3, a2, 1b /* next */ |
130 | |
131 | 2: |
132 | #if _MIPS_SIM == _ABIO32 |
133 | /* Make room for a0-a3 storage. */ |
134 | PTR_ADDIU t0, -(NARGSAVE * SZREG) |
135 | #endif |
136 | PTR_L v1, UCONTEXT_LINK(a0) |
137 | #ifdef __PIC__ |
138 | PTR_ADDIU t9, 99f - 98b |
139 | #else |
140 | PTR_LA t9, 99f |
141 | #endif |
142 | /* sp */ |
143 | REG_S t0, (MCONTEXT_GREGOFF + 29 * MCONTEXT_GREGSZ + MCONTEXT_GREGS)(a0) |
144 | /* s0 */ |
145 | REG_S v1, (MCONTEXT_GREGOFF + 16 * MCONTEXT_GREGSZ + MCONTEXT_GREGS)(a0) |
146 | #ifdef __PIC__ |
147 | /* s1 */ |
148 | REG_S gp, (MCONTEXT_GREGOFF + 17 * MCONTEXT_GREGSZ + MCONTEXT_GREGS)(a0) |
149 | #endif |
150 | /* ra */ |
151 | REG_S t9, (MCONTEXT_GREGOFF + 31 * MCONTEXT_GREGSZ + MCONTEXT_GREGS)(a0) |
152 | REG_S a1, (MCONTEXT_GREGOFF + MCONTEXT_PC)(a0) |
153 | |
154 | #ifdef __PIC__ |
155 | RESTORE_GP64_STACK |
156 | PTR_ADDIU sp, FRAMESZ |
157 | cfi_adjust_cfa_offset (-FRAMESZ) |
158 | #endif |
159 | jr ra |
160 | |
161 | /* We need to terminate the FDE to stop unwinding if backtrace was |
162 | called within a context created by makecontext. */ |
163 | cfi_endproc |
164 | nop |
165 | |
166 | 99: |
167 | #ifdef __PIC__ |
168 | move gp, s1 |
169 | #endif |
170 | move a0, zero |
171 | beqz s0, 0f |
172 | |
173 | /* setcontext (ucp) */ |
174 | move a0, s0 |
175 | #ifdef __PIC__ |
176 | PTR_LA t9, JUMPTARGET (__setcontext) |
177 | jalr t9 |
178 | # if _MIPS_SIM == _ABIO32 |
179 | move gp, s1 |
180 | # endif |
181 | #else |
182 | jal JUMPTARGET (__setcontext) |
183 | #endif |
184 | move a0, v0 |
185 | |
186 | 0: |
187 | /* exit (a0) */ |
188 | #ifdef __PIC__ |
189 | PTR_LA t9, HIDDEN_JUMPTARGET (exit) |
190 | jalr t9 |
191 | #else |
192 | jal HIDDEN_JUMPTARGET (exit) |
193 | #endif |
194 | |
195 | /* You don't exist, you won't feel anything. */ |
196 | 1: |
197 | lb zero, (zero) |
198 | b 1b |
199 | |
200 | cfi_startproc |
201 | PSEUDO_END (__makecontext) |
202 | |
203 | weak_alias (__makecontext, makecontext) |
204 | |