]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
Remove PREPARE_VERSION and PREPARE_VERSION_KNOW
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / mips / mips64 / n64 / sysdep.h
1 /* Copyright (C) 2000-2019 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_SYSDEP_H
19 #define _LINUX_MIPS_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/mips64/n64/sysdep.h>
25
26 #include <tls.h>
27
28 /* In order to get __set_errno() definition in INLINE_SYSCALL. */
29 #ifndef __ASSEMBLER__
30 #include <errno.h>
31 #endif
32
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
38 #define SYS_ify(syscall_name) __NR_##syscall_name
39
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 # define SYSCALL_ERROR_LABEL 99b
45
46 #else /* ! __ASSEMBLER__ */
47
48 /* Define a macro which expands into the inline wrapper code for a system
49 call. */
50 #undef INLINE_SYSCALL
51 #define INLINE_SYSCALL(name, nr, args...) \
52 ({ INTERNAL_SYSCALL_DECL (_sc_err); \
53 long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
54 if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \
55 { \
56 __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \
57 result_var = -1L; \
58 } \
59 result_var; })
60
61 #undef INTERNAL_SYSCALL_DECL
62 #define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused))
63
64 #undef INTERNAL_SYSCALL_ERROR_P
65 #define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err))
66
67 #undef INTERNAL_SYSCALL_ERRNO
68 #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val)
69
70 /* Note that the original Linux syscall restart convention required the
71 instruction immediately preceding SYSCALL to initialize $v0 with the
72 syscall number. Then if a restart triggered, $v0 would have been
73 clobbered by the syscall interrupted, and needed to be reinititalized.
74 The kernel would decrement the PC by 4 before switching back to the
75 user mode so that $v0 had been reloaded before SYSCALL was executed
76 again. This implied the place $v0 was loaded from must have been
77 preserved across a syscall, e.g. an immediate, static register, stack
78 slot, etc.
79
80 The convention was relaxed in Linux with a change applied to the kernel
81 GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that
82 first appeared in the 2.6.36 release. Since then the kernel has had
83 code that reloads $v0 upon syscall restart and resumes right at the
84 SYSCALL instruction, so no special arrangement is needed anymore.
85
86 For backwards compatibility with existing kernel binaries we support
87 the old convention by choosing the instruction preceding SYSCALL
88 carefully. This also means we have to force a 32-bit encoding of the
89 microMIPS MOVE instruction if one is used. */
90
91 #ifdef __mips_micromips
92 # define MOVE32 "move32"
93 #else
94 # define MOVE32 "move"
95 #endif
96
97 #undef INTERNAL_SYSCALL
98 #define INTERNAL_SYSCALL(name, err, nr, args...) \
99 internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \
100 "IK" (SYS_ify (name)), \
101 0, err, args)
102
103 #undef INTERNAL_SYSCALL_NCS
104 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
105 internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \
106 "r" (__s0), \
107 number, err, args)
108
109 #define internal_syscall0(v0_init, input, number, err, dummy...) \
110 ({ \
111 long _sys_result; \
112 \
113 { \
114 register long __s0 asm ("$16") __attribute__ ((unused)) \
115 = (number); \
116 register long __v0 asm ("$2"); \
117 register long __a3 asm ("$7"); \
118 __asm__ volatile ( \
119 ".set\tnoreorder\n\t" \
120 v0_init \
121 "syscall\n\t" \
122 ".set reorder" \
123 : "=r" (__v0), "=r" (__a3) \
124 : input \
125 : __SYSCALL_CLOBBERS); \
126 err = __a3; \
127 _sys_result = __v0; \
128 } \
129 _sys_result; \
130 })
131
132 #define internal_syscall1(v0_init, input, number, err, arg1) \
133 ({ \
134 long _sys_result; \
135 \
136 { \
137 register long __s0 asm ("$16") __attribute__ ((unused)) \
138 = (number); \
139 register long __v0 asm ("$2"); \
140 register long __a0 asm ("$4") = (long) (arg1); \
141 register long __a3 asm ("$7"); \
142 __asm__ volatile ( \
143 ".set\tnoreorder\n\t" \
144 v0_init \
145 "syscall\n\t" \
146 ".set reorder" \
147 : "=r" (__v0), "=r" (__a3) \
148 : input, "r" (__a0) \
149 : __SYSCALL_CLOBBERS); \
150 err = __a3; \
151 _sys_result = __v0; \
152 } \
153 _sys_result; \
154 })
155
156 #define internal_syscall2(v0_init, input, number, err, arg1, arg2) \
157 ({ \
158 long _sys_result; \
159 \
160 { \
161 register long __s0 asm ("$16") __attribute__ ((unused)) \
162 = (number); \
163 register long __v0 asm ("$2"); \
164 register long __a0 asm ("$4") = (long) (arg1); \
165 register long __a1 asm ("$5") = (long) (arg2); \
166 register long __a3 asm ("$7"); \
167 __asm__ volatile ( \
168 ".set\tnoreorder\n\t" \
169 v0_init \
170 "syscall\n\t" \
171 ".set\treorder" \
172 : "=r" (__v0), "=r" (__a3) \
173 : input, "r" (__a0), "r" (__a1) \
174 : __SYSCALL_CLOBBERS); \
175 err = __a3; \
176 _sys_result = __v0; \
177 } \
178 _sys_result; \
179 })
180
181 #define internal_syscall3(v0_init, input, number, err, \
182 arg1, arg2, arg3) \
183 ({ \
184 long _sys_result; \
185 \
186 { \
187 register long __s0 asm ("$16") __attribute__ ((unused)) \
188 = (number); \
189 register long __v0 asm ("$2"); \
190 register long __a0 asm ("$4") = (long) (arg1); \
191 register long __a1 asm ("$5") = (long) (arg2); \
192 register long __a2 asm ("$6") = (long) (arg3); \
193 register long __a3 asm ("$7"); \
194 __asm__ volatile ( \
195 ".set\tnoreorder\n\t" \
196 v0_init \
197 "syscall\n\t" \
198 ".set\treorder" \
199 : "=r" (__v0), "=r" (__a3) \
200 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
201 : __SYSCALL_CLOBBERS); \
202 err = __a3; \
203 _sys_result = __v0; \
204 } \
205 _sys_result; \
206 })
207
208 #define internal_syscall4(v0_init, input, number, err, \
209 arg1, arg2, arg3, arg4) \
210 ({ \
211 long _sys_result; \
212 \
213 { \
214 register long __s0 asm ("$16") __attribute__ ((unused)) \
215 = (number); \
216 register long __v0 asm ("$2"); \
217 register long __a0 asm ("$4") = (long) (arg1); \
218 register long __a1 asm ("$5") = (long) (arg2); \
219 register long __a2 asm ("$6") = (long) (arg3); \
220 register long __a3 asm ("$7") = (long) (arg4); \
221 __asm__ volatile ( \
222 ".set\tnoreorder\n\t" \
223 v0_init \
224 "syscall\n\t" \
225 ".set\treorder" \
226 : "=r" (__v0), "+r" (__a3) \
227 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
228 : __SYSCALL_CLOBBERS); \
229 err = __a3; \
230 _sys_result = __v0; \
231 } \
232 _sys_result; \
233 })
234
235 #define internal_syscall5(v0_init, input, number, err, \
236 arg1, arg2, arg3, arg4, arg5) \
237 ({ \
238 long _sys_result; \
239 \
240 { \
241 register long __s0 asm ("$16") __attribute__ ((unused)) \
242 = (number); \
243 register long __v0 asm ("$2"); \
244 register long __a0 asm ("$4") = (long) (arg1); \
245 register long __a1 asm ("$5") = (long) (arg2); \
246 register long __a2 asm ("$6") = (long) (arg3); \
247 register long __a3 asm ("$7") = (long) (arg4); \
248 register long __a4 asm ("$8") = (long) (arg5); \
249 __asm__ volatile ( \
250 ".set\tnoreorder\n\t" \
251 v0_init \
252 "syscall\n\t" \
253 ".set\treorder" \
254 : "=r" (__v0), "+r" (__a3) \
255 : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4) \
256 : __SYSCALL_CLOBBERS); \
257 err = __a3; \
258 _sys_result = __v0; \
259 } \
260 _sys_result; \
261 })
262
263 #define internal_syscall6(v0_init, input, number, err, \
264 arg1, arg2, arg3, arg4, arg5, arg6) \
265 ({ \
266 long _sys_result; \
267 \
268 { \
269 register long __s0 asm ("$16") __attribute__ ((unused)) \
270 = (number); \
271 register long __v0 asm ("$2"); \
272 register long __a0 asm ("$4") = (long) (arg1); \
273 register long __a1 asm ("$5") = (long) (arg2); \
274 register long __a2 asm ("$6") = (long) (arg3); \
275 register long __a3 asm ("$7") = (long) (arg4); \
276 register long __a4 asm ("$8") = (long) (arg5); \
277 register long __a5 asm ("$9") = (long) (arg6); \
278 __asm__ volatile ( \
279 ".set\tnoreorder\n\t" \
280 v0_init \
281 "syscall\n\t" \
282 ".set\treorder" \
283 : "=r" (__v0), "+r" (__a3) \
284 : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4), \
285 "r" (__a5) \
286 : __SYSCALL_CLOBBERS); \
287 err = __a3; \
288 _sys_result = __v0; \
289 } \
290 _sys_result; \
291 })
292
293 #define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
294 "$14", "$15", "$24", "$25", "hi", "lo", "memory"
295
296 /* Standard MIPS syscalls have an error flag, and return a positive errno
297 when the error flag is set. Emulate this behaviour for vsyscalls so that
298 the INTERNAL_SYSCALL_{ERROR_P,ERRNO} macros work correctly. */
299 #define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
300 ({ \
301 long _ret = funcptr (args); \
302 err = ((unsigned long) (_ret) >= (unsigned long) -4095L); \
303 if (err) \
304 _ret = -_ret; \
305 _ret; \
306 })
307
308 #endif /* __ASSEMBLER__ */
309
310 /* Pointer mangling is not yet supported for MIPS. */
311 #define PTR_MANGLE(var) (void) (var)
312 #define PTR_DEMANGLE(var) (void) (var)
313
314 #endif /* linux/mips/sysdep.h */