]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
1 /* Copyright (C) 2000-2018 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 /* There is some commonality. */
22 #include <sysdeps/unix/sysv/linux/sysdep.h>
23 #include <sysdeps/unix/mips/mips32/sysdep.h>
27 /* In order to get __set_errno() definition in INLINE_SYSCALL. */
32 /* For Linux we can use the system call table in the header file
33 /usr/include/asm/unistd.h
34 of the kernel. But these symbols do not follow the SYS_* syntax
35 so we have to redefine the `SYS_ify' macro here. */
37 #define SYS_ify(syscall_name) __NR_##syscall_name
41 /* We don't want the label for the error handler to be visible in the symbol
42 table when we define it here. */
44 # define SYSCALL_ERROR_LABEL 99b
47 #else /* ! __ASSEMBLER__ */
49 /* Define a macro which expands into the inline wrapper code for a system
52 #define INLINE_SYSCALL(name, nr, args...) \
53 ({ INTERNAL_SYSCALL_DECL (_sc_err); \
54 long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
55 if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \
57 __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \
62 #undef INTERNAL_SYSCALL_DECL
63 #define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused))
65 #undef INTERNAL_SYSCALL_ERROR_P
66 #define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err))
68 #undef INTERNAL_SYSCALL_ERRNO
69 #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val)
71 /* Note that the original Linux syscall restart convention required the
72 instruction immediately preceding SYSCALL to initialize $v0 with the
73 syscall number. Then if a restart triggered, $v0 would have been
74 clobbered by the syscall interrupted, and needed to be reinititalized.
75 The kernel would decrement the PC by 4 before switching back to the
76 user mode so that $v0 had been reloaded before SYSCALL was executed
77 again. This implied the place $v0 was loaded from must have been
78 preserved across a syscall, e.g. an immediate, static register, stack
81 The convention was relaxed in Linux with a change applied to the kernel
82 GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that
83 first appeared in the 2.6.36 release. Since then the kernel has had
84 code that reloads $v0 upon syscall restart and resumes right at the
85 SYSCALL instruction, so no special arrangement is needed anymore.
87 For backwards compatibility with existing kernel binaries we support
88 the old convention by choosing the instruction preceding SYSCALL
89 carefully. This also means we have to force a 32-bit encoding of the
90 microMIPS MOVE instruction if one is used. */
92 #ifdef __mips_micromips
93 # define MOVE32 "move32"
95 # define MOVE32 "move"
98 #undef INTERNAL_SYSCALL
99 #undef INTERNAL_SYSCALL_NCS
101 #define __nomips16 __attribute__ ((nomips16))
103 union __mips_syscall_return
115 /* There's no MIPS16 syscall instruction, so we go through out-of-line
116 standard MIPS wrappers. These do use inline snippets below though,
117 through INTERNAL_SYSCALL_MIPS16. Spilling the syscall number to
118 memory gives the best code in that case, avoiding the need to save
119 and restore a static register. */
121 # include <mips16-syscall.h>
123 # define INTERNAL_SYSCALL(name, err, nr, args...) \
124 INTERNAL_SYSCALL_NCS (SYS_ify (name), err, nr, args)
126 # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
128 union __mips_syscall_return _sc_ret; \
129 _sc_ret.val = __mips16_syscall##nr (args, number); \
130 err = _sc_ret.reg.v1; \
134 # define INTERNAL_SYSCALL_MIPS16(number, err, nr, args...) \
135 internal_syscall##nr ("lw\t%0, %2\n\t", \
139 #else /* !__mips16 */
140 # define INTERNAL_SYSCALL(name, err, nr, args...) \
141 internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \
142 "IK" (SYS_ify (name)), \
143 SYS_ify (name), err, args)
145 # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
146 internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \
150 #endif /* !__mips16 */
152 #define internal_syscall0(v0_init, input, number, err, dummy...) \
157 register long __s0 asm ("$16") __attribute__ ((unused)) \
159 register long __v0 asm ("$2"); \
160 register long __a3 asm ("$7"); \
162 ".set\tnoreorder\n\t" \
166 : "=r" (__v0), "=r" (__a3) \
168 : __SYSCALL_CLOBBERS); \
170 _sys_result = __v0; \
175 #define internal_syscall1(v0_init, input, number, err, arg1) \
180 register long __s0 asm ("$16") __attribute__ ((unused)) \
182 register long __v0 asm ("$2"); \
183 register long __a0 asm ("$4") = (long) (arg1); \
184 register long __a3 asm ("$7"); \
186 ".set\tnoreorder\n\t" \
190 : "=r" (__v0), "=r" (__a3) \
191 : input, "r" (__a0) \
192 : __SYSCALL_CLOBBERS); \
194 _sys_result = __v0; \
199 #define internal_syscall2(v0_init, input, number, err, arg1, arg2) \
204 register long __s0 asm ("$16") __attribute__ ((unused)) \
206 register long __v0 asm ("$2"); \
207 register long __a0 asm ("$4") = (long) (arg1); \
208 register long __a1 asm ("$5") = (long) (arg2); \
209 register long __a3 asm ("$7"); \
211 ".set\tnoreorder\n\t" \
215 : "=r" (__v0), "=r" (__a3) \
216 : input, "r" (__a0), "r" (__a1) \
217 : __SYSCALL_CLOBBERS); \
219 _sys_result = __v0; \
224 #define internal_syscall3(v0_init, input, number, err, \
230 register long __s0 asm ("$16") __attribute__ ((unused)) \
232 register long __v0 asm ("$2"); \
233 register long __a0 asm ("$4") = (long) (arg1); \
234 register long __a1 asm ("$5") = (long) (arg2); \
235 register long __a2 asm ("$6") = (long) (arg3); \
236 register long __a3 asm ("$7"); \
238 ".set\tnoreorder\n\t" \
242 : "=r" (__v0), "=r" (__a3) \
243 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
244 : __SYSCALL_CLOBBERS); \
246 _sys_result = __v0; \
251 #define internal_syscall4(v0_init, input, number, err, \
252 arg1, arg2, arg3, arg4) \
257 register long __s0 asm ("$16") __attribute__ ((unused)) \
259 register long __v0 asm ("$2"); \
260 register long __a0 asm ("$4") = (long) (arg1); \
261 register long __a1 asm ("$5") = (long) (arg2); \
262 register long __a2 asm ("$6") = (long) (arg3); \
263 register long __a3 asm ("$7") = (long) (arg4); \
265 ".set\tnoreorder\n\t" \
269 : "=r" (__v0), "+r" (__a3) \
270 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
271 : __SYSCALL_CLOBBERS); \
273 _sys_result = __v0; \
278 /* Standalone MIPS wrappers used for 5, 6, and 7 argument syscalls,
279 which require stack arguments. We rely on the compiler arranging
280 wrapper's arguments according to the MIPS o32 function calling
281 convention, which is reused by syscalls, except for the syscall
282 number passed and the error flag returned (taken care of in the
283 wrapper called). This relieves us from relying on non-guaranteed
284 compiler specifics required for the stack arguments to be pushed,
285 which would be the case if these syscalls were inlined. */
287 long long __nomips16
__mips_syscall5 (long arg1
, long arg2
, long arg3
,
288 long arg4
, long arg5
,
290 libc_hidden_proto (__mips_syscall5
, nomips16
)
292 #define internal_syscall5(v0_init, input, number, err, \
293 arg1, arg2, arg3, arg4, arg5) \
295 union __mips_syscall_return _sc_ret; \
296 _sc_ret.val = __mips_syscall5 ((long) (arg1), \
302 err = _sc_ret.reg.v1; \
306 long long __nomips16
__mips_syscall6 (long arg1
, long arg2
, long arg3
,
307 long arg4
, long arg5
, long arg6
,
309 libc_hidden_proto (__mips_syscall6
, nomips16
)
311 #define internal_syscall6(v0_init, input, number, err, \
312 arg1, arg2, arg3, arg4, arg5, arg6) \
314 union __mips_syscall_return _sc_ret; \
315 _sc_ret.val = __mips_syscall6 ((long) (arg1), \
322 err = _sc_ret.reg.v1; \
326 long long __nomips16
__mips_syscall7 (long arg1
, long arg2
, long arg3
,
327 long arg4
, long arg5
, long arg6
,
330 libc_hidden_proto (__mips_syscall7
, nomips16
)
332 #define internal_syscall7(v0_init, input, number, err, \
333 arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
335 union __mips_syscall_return _sc_ret; \
336 _sc_ret.val = __mips_syscall7 ((long) (arg1), \
344 err = _sc_ret.reg.v1; \
348 #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
349 "$14", "$15", "$24", "$25", "hi", "lo", "memory"
351 /* Standard MIPS syscalls have an error flag, and return a positive errno
352 when the error flag is set. Emulate this behaviour for vsyscalls so that
353 the INTERNAL_SYSCALL_{ERROR_P,ERRNO} macros work correctly. */
354 #define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
356 long _ret = funcptr (args); \
357 err = ((unsigned long) (_ret) >= (unsigned long) -4095L); \
363 /* List of system calls which are supported as vsyscalls. */
364 #define HAVE_CLOCK_GETTIME_VSYSCALL 1
365 #define HAVE_GETTIMEOFDAY_VSYSCALL 1
367 #endif /* __ASSEMBLER__ */
369 /* Pointer mangling is not yet supported for MIPS. */
370 #define PTR_MANGLE(var) (void) (var)
371 #define PTR_DEMANGLE(var) (void) (var)
373 #endif /* linux/mips/mips32/sysdep.h */