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
81union __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
269long 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);
273libc_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
288long 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);
292libc_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
308long 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);
313libc_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.

source code of glibc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h