]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
1 /* Copyright (C) 2000-2019 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
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 <http://www.gnu.org/licenses/>. */
18 #ifndef _LINUX_MIPS_MIPS32_SYSDEP_H
19 #define _LINUX_MIPS_MIPS32_SYSDEP_H 1
21 /* Always enable vsyscalls on mips32. */
22 #define ALWAYS_USE_VSYSCALL 1
24 /* There is some commonality. */
25 #include <sysdeps/unix/sysv/linux/sysdep.h>
26 #include <sysdeps/unix/mips/mips32/sysdep.h>
30 /* In order to get __set_errno() definition in INLINE_SYSCALL. */
35 /* For Linux we can use the system call table in the header file
36 /usr/include/asm/unistd.h
37 of the kernel. But these symbols do not follow the SYS_* syntax
38 so we have to redefine the `SYS_ify' macro here. */
40 #define SYS_ify(syscall_name) __NR_##syscall_name
44 /* We don't want the label for the error handler to be visible in the symbol
45 table when we define it here. */
47 # define SYSCALL_ERROR_LABEL 99b
50 #else /* ! __ASSEMBLER__ */
52 /* Define a macro which expands into the inline wrapper code for a system
55 #define INLINE_SYSCALL(name, nr, args...) \
56 ({ INTERNAL_SYSCALL_DECL (_sc_err); \
57 long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
58 if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \
60 __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \
65 #undef INTERNAL_SYSCALL_DECL
66 #define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused))
68 #undef INTERNAL_SYSCALL_ERROR_P
69 #define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err))
71 #undef INTERNAL_SYSCALL_ERRNO
72 #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val)
74 /* Note that the original Linux syscall restart convention required the
75 instruction immediately preceding SYSCALL to initialize $v0 with the
76 syscall number. Then if a restart triggered, $v0 would have been
77 clobbered by the syscall interrupted, and needed to be reinititalized.
78 The kernel would decrement the PC by 4 before switching back to the
79 user mode so that $v0 had been reloaded before SYSCALL was executed
80 again. This implied the place $v0 was loaded from must have been
81 preserved across a syscall, e.g. an immediate, static register, stack
84 The convention was relaxed in Linux with a change applied to the kernel
85 GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that
86 first appeared in the 2.6.36 release. Since then the kernel has had
87 code that reloads $v0 upon syscall restart and resumes right at the
88 SYSCALL instruction, so no special arrangement is needed anymore.
90 For backwards compatibility with existing kernel binaries we support
91 the old convention by choosing the instruction preceding SYSCALL
92 carefully. This also means we have to force a 32-bit encoding of the
93 microMIPS MOVE instruction if one is used. */
95 #ifdef __mips_micromips
96 # define MOVE32 "move32"
98 # define MOVE32 "move"
101 #undef INTERNAL_SYSCALL
102 #undef INTERNAL_SYSCALL_NCS
104 #define __nomips16 __attribute__ ((nomips16))
106 union __mips_syscall_return
118 /* There's no MIPS16 syscall instruction, so we go through out-of-line
119 standard MIPS wrappers. These do use inline snippets below though,
120 through INTERNAL_SYSCALL_MIPS16. Spilling the syscall number to
121 memory gives the best code in that case, avoiding the need to save
122 and restore a static register. */
124 # include <mips16-syscall.h>
126 # define INTERNAL_SYSCALL(name, err, nr, args...) \
127 INTERNAL_SYSCALL_NCS (SYS_ify (name), err, nr, args)
129 # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
131 union __mips_syscall_return _sc_ret; \
132 _sc_ret.val = __mips16_syscall##nr (args, number); \
133 err = _sc_ret.reg.v1; \
137 # define INTERNAL_SYSCALL_MIPS16(number, err, nr, args...) \
138 internal_syscall##nr ("lw\t%0, %2\n\t", \
142 #else /* !__mips16 */
143 # define INTERNAL_SYSCALL(name, err, nr, args...) \
144 internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \
145 "IK" (SYS_ify (name)), \
146 SYS_ify (name), err, args)
148 # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
149 internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \
153 #endif /* !__mips16 */
155 #define internal_syscall0(v0_init, input, number, err, dummy...) \
160 register long __s0 asm ("$16") __attribute__ ((unused)) \
162 register long __v0 asm ("$2"); \
163 register long __a3 asm ("$7"); \
165 ".set\tnoreorder\n\t" \
169 : "=r" (__v0), "=r" (__a3) \
171 : __SYSCALL_CLOBBERS); \
173 _sys_result = __v0; \
178 #define internal_syscall1(v0_init, input, number, err, arg1) \
183 register long __s0 asm ("$16") __attribute__ ((unused)) \
185 register long __v0 asm ("$2"); \
186 register long __a0 asm ("$4") = (long) (arg1); \
187 register long __a3 asm ("$7"); \
189 ".set\tnoreorder\n\t" \
193 : "=r" (__v0), "=r" (__a3) \
194 : input, "r" (__a0) \
195 : __SYSCALL_CLOBBERS); \
197 _sys_result = __v0; \
202 #define internal_syscall2(v0_init, input, number, err, arg1, arg2) \
207 register long __s0 asm ("$16") __attribute__ ((unused)) \
209 register long __v0 asm ("$2"); \
210 register long __a0 asm ("$4") = (long) (arg1); \
211 register long __a1 asm ("$5") = (long) (arg2); \
212 register long __a3 asm ("$7"); \
214 ".set\tnoreorder\n\t" \
218 : "=r" (__v0), "=r" (__a3) \
219 : input, "r" (__a0), "r" (__a1) \
220 : __SYSCALL_CLOBBERS); \
222 _sys_result = __v0; \
227 #define internal_syscall3(v0_init, input, number, err, \
233 register long __s0 asm ("$16") __attribute__ ((unused)) \
235 register long __v0 asm ("$2"); \
236 register long __a0 asm ("$4") = (long) (arg1); \
237 register long __a1 asm ("$5") = (long) (arg2); \
238 register long __a2 asm ("$6") = (long) (arg3); \
239 register long __a3 asm ("$7"); \
241 ".set\tnoreorder\n\t" \
245 : "=r" (__v0), "=r" (__a3) \
246 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
247 : __SYSCALL_CLOBBERS); \
249 _sys_result = __v0; \
254 #define internal_syscall4(v0_init, input, number, err, \
255 arg1, arg2, arg3, arg4) \
260 register long __s0 asm ("$16") __attribute__ ((unused)) \
262 register long __v0 asm ("$2"); \
263 register long __a0 asm ("$4") = (long) (arg1); \
264 register long __a1 asm ("$5") = (long) (arg2); \
265 register long __a2 asm ("$6") = (long) (arg3); \
266 register long __a3 asm ("$7") = (long) (arg4); \
268 ".set\tnoreorder\n\t" \
272 : "=r" (__v0), "+r" (__a3) \
273 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
274 : __SYSCALL_CLOBBERS); \
276 _sys_result = __v0; \
281 /* Standalone MIPS wrappers used for 5, 6, and 7 argument syscalls,
282 which require stack arguments. We rely on the compiler arranging
283 wrapper's arguments according to the MIPS o32 function calling
284 convention, which is reused by syscalls, except for the syscall
285 number passed and the error flag returned (taken care of in the
286 wrapper called). This relieves us from relying on non-guaranteed
287 compiler specifics required for the stack arguments to be pushed,
288 which would be the case if these syscalls were inlined. */
290 long long __nomips16
__mips_syscall5 (long arg1
, long arg2
, long arg3
,
291 long arg4
, long arg5
,
293 libc_hidden_proto (__mips_syscall5
, nomips16
)
295 #define internal_syscall5(v0_init, input, number, err, \
296 arg1, arg2, arg3, arg4, arg5) \
298 union __mips_syscall_return _sc_ret; \
299 _sc_ret.val = __mips_syscall5 ((long) (arg1), \
305 err = _sc_ret.reg.v1; \
309 long long __nomips16
__mips_syscall6 (long arg1
, long arg2
, long arg3
,
310 long arg4
, long arg5
, long arg6
,
312 libc_hidden_proto (__mips_syscall6
, nomips16
)
314 #define internal_syscall6(v0_init, input, number, err, \
315 arg1, arg2, arg3, arg4, arg5, arg6) \
317 union __mips_syscall_return _sc_ret; \
318 _sc_ret.val = __mips_syscall6 ((long) (arg1), \
325 err = _sc_ret.reg.v1; \
329 long long __nomips16
__mips_syscall7 (long arg1
, long arg2
, long arg3
,
330 long arg4
, long arg5
, long arg6
,
333 libc_hidden_proto (__mips_syscall7
, nomips16
)
335 #define internal_syscall7(v0_init, input, number, err, \
336 arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
338 union __mips_syscall_return _sc_ret; \
339 _sc_ret.val = __mips_syscall7 ((long) (arg1), \
347 err = _sc_ret.reg.v1; \
351 #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
352 "$14", "$15", "$24", "$25", "hi", "lo", "memory"
354 /* Standard MIPS syscalls have an error flag, and return a positive errno
355 when the error flag is set. Emulate this behaviour for vsyscalls so that
356 the INTERNAL_SYSCALL_{ERROR_P,ERRNO} macros work correctly. */
357 #define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
359 long _ret = funcptr (args); \
360 err = ((unsigned long) (_ret) >= (unsigned long) -4095L); \
366 /* List of system calls which are supported as vsyscalls. */
367 #define HAVE_CLOCK_GETTIME_VSYSCALL 1
368 #define HAVE_GETTIMEOFDAY_VSYSCALL 1
370 #endif /* __ASSEMBLER__ */
372 /* Pointer mangling is not yet supported for MIPS. */
373 #define PTR_MANGLE(var) (void) (var)
374 #define PTR_DEMANGLE(var) (void) (var)
376 #endif /* linux/mips/mips32/sysdep.h */