Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /* Copyright (C) 2000-2024 Free Software Foundation, Inc. |
---|---|
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library. If not, see |
16 | <https://www.gnu.org/licenses/>. */ |
17 | |
18 | #ifndef _LINUX_MIPS_MIPS32_SYSDEP_H |
19 | #define _LINUX_MIPS_MIPS32_SYSDEP_H 1 |
20 | |
21 | /* There is some commonality. */ |
22 | #include <sysdeps/unix/sysv/linux/mips/sysdep.h> |
23 | #include <sysdeps/unix/sysv/linux/sysdep.h> |
24 | #include <sysdeps/unix/mips/mips32/sysdep.h> |
25 | |
26 | #include <tls.h> |
27 | |
28 | /* For Linux we can use the system call table in the header file |
29 | /usr/include/asm/unistd.h |
30 | of the kernel. But these symbols do not follow the SYS_* syntax |
31 | so we have to redefine the `SYS_ify' macro here. */ |
32 | #undef SYS_ify |
33 | #define SYS_ify(syscall_name) __NR_##syscall_name |
34 | |
35 | #ifdef __ASSEMBLER__ |
36 | |
37 | /* We don't want the label for the error handler to be visible in the symbol |
38 | table when we define it here. */ |
39 | #ifdef __PIC__ |
40 | # undef SYSCALL_ERROR_LABEL |
41 | # define SYSCALL_ERROR_LABEL 99b |
42 | #endif |
43 | |
44 | #else /* ! __ASSEMBLER__ */ |
45 | |
46 | #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL |
47 | #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 |
48 | |
49 | /* Note that the original Linux syscall restart convention required the |
50 | instruction immediately preceding SYSCALL to initialize $v0 with the |
51 | syscall number. Then if a restart triggered, $v0 would have been |
52 | clobbered by the syscall interrupted, and needed to be reinititalized. |
53 | The kernel would decrement the PC by 4 before switching back to the |
54 | user mode so that $v0 had been reloaded before SYSCALL was executed |
55 | again. This implied the place $v0 was loaded from must have been |
56 | preserved across a syscall, e.g. an immediate, static register, stack |
57 | slot, etc. |
58 | |
59 | The convention was relaxed in Linux with a change applied to the kernel |
60 | GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that |
61 | first appeared in the 2.6.36 release. Since then the kernel has had |
62 | code that reloads $v0 upon syscall restart and resumes right at the |
63 | SYSCALL instruction, so no special arrangement is needed anymore. |
64 | |
65 | For backwards compatibility with existing kernel binaries we support |
66 | the old convention by choosing the instruction preceding SYSCALL |
67 | carefully. This also means we have to force a 32-bit encoding of the |
68 | microMIPS MOVE instruction if one is used. */ |
69 | |
70 | #ifdef __mips_micromips |
71 | # define MOVE32 "move32" |
72 | #else |
73 | # define MOVE32 "move" |
74 | #endif |
75 | |
76 | #undef INTERNAL_SYSCALL |
77 | #undef INTERNAL_SYSCALL_NCS |
78 | |
79 | #define __nomips16 __attribute__ ((nomips16)) |
80 | |
81 | union __mips_syscall_return |
82 | { |
83 | long long int val; |
84 | struct |
85 | { |
86 | long int v0; |
87 | long int v1; |
88 | } |
89 | reg; |
90 | }; |
91 | |
92 | #ifdef __mips16 |
93 | /* There's no MIPS16 syscall instruction, so we go through out-of-line |
94 | standard MIPS wrappers. These do use inline snippets below though, |
95 | through INTERNAL_SYSCALL_MIPS16. Spilling the syscall number to |
96 | memory gives the best code in that case, avoiding the need to save |
97 | and restore a static register. */ |
98 | |
99 | # include <mips16-syscall.h> |
100 | |
101 | # define INTERNAL_SYSCALL(name, nr, args...) \ |
102 | INTERNAL_SYSCALL_NCS (SYS_ify (name), nr, args) |
103 | |
104 | # define INTERNAL_SYSCALL_NCS(number, nr, args...) \ |
105 | ({ \ |
106 | union __mips_syscall_return _sc_ret; \ |
107 | _sc_ret.val = __mips16_syscall##nr (args, number); \ |
108 | _sc_ret.reg.v0; \ |
109 | }) |
110 | |
111 | # define INTERNAL_SYSCALL_MIPS16(number, err, nr, args...) \ |
112 | internal_syscall##nr ("lw\t%0, %2\n\t", \ |
113 | "R" (number), \ |
114 | number, err, args) |
115 | |
116 | #else /* !__mips16 */ |
117 | # define INTERNAL_SYSCALL(name, nr, args...) \ |
118 | internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \ |
119 | "IK" (SYS_ify (name)), \ |
120 | SYS_ify (name), err, args) |
121 | |
122 | # define INTERNAL_SYSCALL_NCS(number, nr, args...) \ |
123 | internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \ |
124 | "r" (__s0), \ |
125 | number, err, args) |
126 | |
127 | #endif /* !__mips16 */ |
128 | |
129 | #define internal_syscall0(v0_init, input, number, err, dummy...) \ |
130 | ({ \ |
131 | long int _sys_result; \ |
132 | \ |
133 | { \ |
134 | register long int __s0 asm ("$16") __attribute__ ((unused)) \ |
135 | = (number); \ |
136 | register long int __v0 asm ("$2"); \ |
137 | register long int __a3 asm ("$7"); \ |
138 | __asm__ volatile ( \ |
139 | ".set\tnoreorder\n\t" \ |
140 | v0_init \ |
141 | "syscall\n\t" \ |
142 | ".set reorder" \ |
143 | : "=r" (__v0), "=r" (__a3) \ |
144 | : input \ |
145 | : __SYSCALL_CLOBBERS); \ |
146 | _sys_result = __a3 != 0 ? -__v0 : __v0; \ |
147 | } \ |
148 | _sys_result; \ |
149 | }) |
150 | |
151 | #define internal_syscall1(v0_init, input, number, err, arg1) \ |
152 | ({ \ |
153 | long int _sys_result; \ |
154 | \ |
155 | { \ |
156 | long int _arg1 = (long int) (arg1); \ |
157 | register long int __s0 asm ("$16") __attribute__ ((unused)) \ |
158 | = (number); \ |
159 | register long int __v0 asm ("$2"); \ |
160 | register long int __a0 asm ("$4") = _arg1; \ |
161 | register long int __a3 asm ("$7"); \ |
162 | __asm__ volatile ( \ |
163 | ".set\tnoreorder\n\t" \ |
164 | v0_init \ |
165 | "syscall\n\t" \ |
166 | ".set reorder" \ |
167 | : "=r" (__v0), "=r" (__a3) \ |
168 | : input, "r" (__a0) \ |
169 | : __SYSCALL_CLOBBERS); \ |
170 | _sys_result = __a3 != 0 ? -__v0 : __v0; \ |
171 | } \ |
172 | _sys_result; \ |
173 | }) |
174 | |
175 | #define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ |
176 | ({ \ |
177 | long int _sys_result; \ |
178 | \ |
179 | { \ |
180 | long int _arg1 = (long int) (arg1); \ |
181 | long int _arg2 = (long int) (arg2); \ |
182 | register long int __s0 asm ("$16") __attribute__ ((unused)) \ |
183 | = (number); \ |
184 | register long int __v0 asm ("$2"); \ |
185 | register long int __a0 asm ("$4") = _arg1; \ |
186 | register long int __a1 asm ("$5") = _arg2; \ |
187 | register long int __a3 asm ("$7"); \ |
188 | __asm__ volatile ( \ |
189 | ".set\tnoreorder\n\t" \ |
190 | v0_init \ |
191 | "syscall\n\t" \ |
192 | ".set\treorder" \ |
193 | : "=r" (__v0), "=r" (__a3) \ |
194 | : input, "r" (__a0), "r" (__a1) \ |
195 | : __SYSCALL_CLOBBERS); \ |
196 | _sys_result = __a3 != 0 ? -__v0 : __v0; \ |
197 | } \ |
198 | _sys_result; \ |
199 | }) |
200 | |
201 | #define internal_syscall3(v0_init, input, number, err, \ |
202 | arg1, arg2, arg3) \ |
203 | ({ \ |
204 | long int _sys_result; \ |
205 | \ |
206 | { \ |
207 | long int _arg1 = (long int) (arg1); \ |
208 | long int _arg2 = (long int) (arg2); \ |
209 | long int _arg3 = (long int) (arg3); \ |
210 | register long int __s0 asm ("$16") __attribute__ ((unused)) \ |
211 | = (number); \ |
212 | register long int __v0 asm ("$2"); \ |
213 | register long int __a0 asm ("$4") = _arg1; \ |
214 | register long int __a1 asm ("$5") = _arg2; \ |
215 | register long int __a2 asm ("$6") = _arg3; \ |
216 | register long int __a3 asm ("$7"); \ |
217 | __asm__ volatile ( \ |
218 | ".set\tnoreorder\n\t" \ |
219 | v0_init \ |
220 | "syscall\n\t" \ |
221 | ".set\treorder" \ |
222 | : "=r" (__v0), "=r" (__a3) \ |
223 | : input, "r" (__a0), "r" (__a1), "r" (__a2) \ |
224 | : __SYSCALL_CLOBBERS); \ |
225 | _sys_result = __a3 != 0 ? -__v0 : __v0; \ |
226 | } \ |
227 | _sys_result; \ |
228 | }) |
229 | |
230 | #define internal_syscall4(v0_init, input, number, err, \ |
231 | arg1, arg2, arg3, arg4) \ |
232 | ({ \ |
233 | long int _sys_result; \ |
234 | \ |
235 | { \ |
236 | long int _arg1 = (long int) (arg1); \ |
237 | long int _arg2 = (long int) (arg2); \ |
238 | long int _arg3 = (long int) (arg3); \ |
239 | long int _arg4 = (long int) (arg4); \ |
240 | register long int __s0 asm ("$16") __attribute__ ((unused)) \ |
241 | = (number); \ |
242 | register long int __v0 asm ("$2"); \ |
243 | register long int __a0 asm ("$4") = _arg1; \ |
244 | register long int __a1 asm ("$5") = _arg2; \ |
245 | register long int __a2 asm ("$6") = _arg3; \ |
246 | register long int __a3 asm ("$7") = _arg4; \ |
247 | __asm__ volatile ( \ |
248 | ".set\tnoreorder\n\t" \ |
249 | v0_init \ |
250 | "syscall\n\t" \ |
251 | ".set\treorder" \ |
252 | : "=r" (__v0), "+r" (__a3) \ |
253 | : input, "r" (__a0), "r" (__a1), "r" (__a2) \ |
254 | : __SYSCALL_CLOBBERS); \ |
255 | _sys_result = __a3 != 0 ? -__v0 : __v0; \ |
256 | } \ |
257 | _sys_result; \ |
258 | }) |
259 | |
260 | /* Standalone MIPS wrappers used for 5, 6, and 7 argument syscalls, |
261 | which require stack arguments. We rely on the compiler arranging |
262 | wrapper's arguments according to the MIPS o32 function calling |
263 | convention, which is reused by syscalls, except for the syscall |
264 | number passed and the error flag returned (taken care of in the |
265 | wrapper called). This relieves us from relying on non-guaranteed |
266 | compiler specifics required for the stack arguments to be pushed, |
267 | which would be the case if these syscalls were inlined. */ |
268 | |
269 | long long int __nomips16 __mips_syscall5 (long int arg1, long int arg2, |
270 | long int arg3, long int arg4, |
271 | long int arg5, |
272 | long int number); |
273 | libc_hidden_proto (__mips_syscall5, nomips16) |
274 | |
275 | #define internal_syscall5(v0_init, input, number, err, \ |
276 | arg1, arg2, arg3, arg4, arg5) \ |
277 | ({ \ |
278 | union __mips_syscall_return _sc_ret; \ |
279 | _sc_ret.val = __mips_syscall5 ((long int) (arg1), \ |
280 | (long int) (arg2), \ |
281 | (long int) (arg3), \ |
282 | (long int) (arg4), \ |
283 | (long int) (arg5), \ |
284 | (long int) (number)); \ |
285 | _sc_ret.reg.v1 != 0 ? -_sc_ret.reg.v0 : _sc_ret.reg.v0; \ |
286 | }) |
287 | |
288 | long long int __nomips16 __mips_syscall6 (long int arg1, long int arg2, |
289 | long int arg3, long int arg4, |
290 | long int arg5, long int arg6, |
291 | long int number); |
292 | libc_hidden_proto (__mips_syscall6, nomips16) |
293 | |
294 | #define internal_syscall6(v0_init, input, number, err, \ |
295 | arg1, arg2, arg3, arg4, arg5, arg6) \ |
296 | ({ \ |
297 | union __mips_syscall_return _sc_ret; \ |
298 | _sc_ret.val = __mips_syscall6 ((long int) (arg1), \ |
299 | (long int) (arg2), \ |
300 | (long int) (arg3), \ |
301 | (long int) (arg4), \ |
302 | (long int) (arg5), \ |
303 | (long int) (arg6), \ |
304 | (long int) (number)); \ |
305 | _sc_ret.reg.v1 != 0 ? -_sc_ret.reg.v0 : _sc_ret.reg.v0; \ |
306 | }) |
307 | |
308 | long long int __nomips16 __mips_syscall7 (long int arg1, long int arg2, |
309 | long int arg3, long int arg4, |
310 | long int arg5, long int arg6, |
311 | long int arg7, |
312 | long int number); |
313 | libc_hidden_proto (__mips_syscall7, nomips16) |
314 | |
315 | #define internal_syscall7(v0_init, input, number, err, \ |
316 | arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ |
317 | ({ \ |
318 | union __mips_syscall_return _sc_ret; \ |
319 | _sc_ret.val = __mips_syscall7 ((long int) (arg1), \ |
320 | (long int) (arg2), \ |
321 | (long int) (arg3), \ |
322 | (long int) (arg4), \ |
323 | (long int) (arg5), \ |
324 | (long int) (arg6), \ |
325 | (long int) (arg7), \ |
326 | (long int) (number)); \ |
327 | _sc_ret.reg.v1 != 0 ? -_sc_ret.reg.v0 : _sc_ret.reg.v0; \ |
328 | }) |
329 | |
330 | #if __mips_isa_rev >= 6 |
331 | # define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \ |
332 | "$14", "$15", "$24", "$25", "memory" |
333 | #else |
334 | # define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \ |
335 | "$14", "$15", "$24", "$25", "hi", "lo", "memory" |
336 | #endif |
337 | |
338 | #endif /* __ASSEMBLER__ */ |
339 | |
340 | #endif /* linux/mips/mips32/sysdep.h */ |
341 |
Warning: That file was not part of the compilation database. It may have many parsing errors.