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