Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / unix / sysv / linux / mips / mips64 / n64 / sysdep.h
bloba9f9649e7432c4fb64cd05c6699594e933ec6f68
1 /* Copyright (C) 2000-2014 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_SYSDEP_H
19 #define _LINUX_MIPS_SYSDEP_H 1
21 /* There is some commonality. */
22 #include <sysdeps/unix/mips/mips64/n64/sysdep.h>
24 #include <tls.h>
26 /* In order to get __set_errno() definition in INLINE_SYSCALL. */
27 #ifndef __ASSEMBLER__
28 #include <errno.h>
29 #endif
31 /* For Linux we can use the system call table in the header file
32 /usr/include/asm/unistd.h
33 of the kernel. But these symbols do not follow the SYS_* syntax
34 so we have to redefine the `SYS_ify' macro here. */
35 #undef SYS_ify
36 #define SYS_ify(syscall_name) __NR_##syscall_name
38 #ifdef __ASSEMBLER__
40 /* We don't want the label for the error handler to be visible in the symbol
41 table when we define it here. */
42 # define SYSCALL_ERROR_LABEL 99b
44 #else /* ! __ASSEMBLER__ */
46 /* Define a macro which expands into the inline wrapper code for a system
47 call. */
48 #undef INLINE_SYSCALL
49 #define INLINE_SYSCALL(name, nr, args...) \
50 ({ INTERNAL_SYSCALL_DECL(err); \
51 long result_var = INTERNAL_SYSCALL (name, err, nr, args); \
52 if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \
53 { \
54 __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \
55 result_var = -1L; \
56 } \
57 result_var; })
59 #undef INTERNAL_SYSCALL_DECL
60 #define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused))
62 #undef INTERNAL_SYSCALL_ERROR_P
63 #define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err))
65 #undef INTERNAL_SYSCALL_ERRNO
66 #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val)
68 /* Note that the original Linux syscall restart convention required the
69 instruction immediately preceding SYSCALL to initialize $v0 with the
70 syscall number. Then if a restart triggered, $v0 would have been
71 clobbered by the syscall interrupted, and needed to be reinititalized.
72 The kernel would decrement the PC by 4 before switching back to the
73 user mode so that $v0 had been reloaded before SYSCALL was executed
74 again. This implied the place $v0 was loaded from must have been
75 preserved across a syscall, e.g. an immediate, static register, stack
76 slot, etc.
78 The convention was relaxed in Linux with a change applied to the kernel
79 GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that
80 first appeared in the 2.6.36 release. Since then the kernel has had
81 code that reloads $v0 upon syscall restart and resumes right at the
82 SYSCALL instruction, so no special arrangement is needed anymore.
84 For backwards compatibility with existing kernel binaries we support
85 the old convention by choosing the instruction preceding SYSCALL
86 carefully. This also means we have to force a 32-bit encoding of the
87 microMIPS MOVE instruction if one is used. */
89 #ifdef __mips_micromips
90 # define MOVE32 "move32"
91 #else
92 # define MOVE32 "move"
93 #endif
95 #undef INTERNAL_SYSCALL
96 #define INTERNAL_SYSCALL(name, err, nr, args...) \
97 internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \
98 "IK" (SYS_ify (name)), \
99 0, err, args)
101 #undef INTERNAL_SYSCALL_NCS
102 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
103 internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \
104 "r" (__s0), \
105 number, err, args)
107 #define internal_syscall0(v0_init, input, number, err, dummy...) \
108 ({ \
109 long _sys_result; \
112 register long __s0 asm ("$16") __attribute__ ((unused)) \
113 = (number); \
114 register long __v0 asm ("$2"); \
115 register long __a3 asm ("$7"); \
116 __asm__ volatile ( \
117 ".set\tnoreorder\n\t" \
118 v0_init \
119 "syscall\n\t" \
120 ".set reorder" \
121 : "=r" (__v0), "=r" (__a3) \
122 : input \
123 : __SYSCALL_CLOBBERS); \
124 err = __a3; \
125 _sys_result = __v0; \
127 _sys_result; \
130 #define internal_syscall1(v0_init, input, number, err, arg1) \
131 ({ \
132 long _sys_result; \
135 register long __s0 asm ("$16") __attribute__ ((unused)) \
136 = (number); \
137 register long __v0 asm ("$2"); \
138 register long __a0 asm ("$4") = (long) (arg1); \
139 register long __a3 asm ("$7"); \
140 __asm__ volatile ( \
141 ".set\tnoreorder\n\t" \
142 v0_init \
143 "syscall\n\t" \
144 ".set reorder" \
145 : "=r" (__v0), "=r" (__a3) \
146 : input, "r" (__a0) \
147 : __SYSCALL_CLOBBERS); \
148 err = __a3; \
149 _sys_result = __v0; \
151 _sys_result; \
154 #define internal_syscall2(v0_init, input, number, err, arg1, arg2) \
155 ({ \
156 long _sys_result; \
159 register long __s0 asm ("$16") __attribute__ ((unused)) \
160 = (number); \
161 register long __v0 asm ("$2"); \
162 register long __a0 asm ("$4") = (long) (arg1); \
163 register long __a1 asm ("$5") = (long) (arg2); \
164 register long __a3 asm ("$7"); \
165 __asm__ volatile ( \
166 ".set\tnoreorder\n\t" \
167 v0_init \
168 "syscall\n\t" \
169 ".set\treorder" \
170 : "=r" (__v0), "=r" (__a3) \
171 : input, "r" (__a0), "r" (__a1) \
172 : __SYSCALL_CLOBBERS); \
173 err = __a3; \
174 _sys_result = __v0; \
176 _sys_result; \
179 #define internal_syscall3(v0_init, input, number, err, \
180 arg1, arg2, arg3) \
181 ({ \
182 long _sys_result; \
185 register long __s0 asm ("$16") __attribute__ ((unused)) \
186 = (number); \
187 register long __v0 asm ("$2"); \
188 register long __a0 asm ("$4") = (long) (arg1); \
189 register long __a1 asm ("$5") = (long) (arg2); \
190 register long __a2 asm ("$6") = (long) (arg3); \
191 register long __a3 asm ("$7"); \
192 __asm__ volatile ( \
193 ".set\tnoreorder\n\t" \
194 v0_init \
195 "syscall\n\t" \
196 ".set\treorder" \
197 : "=r" (__v0), "=r" (__a3) \
198 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
199 : __SYSCALL_CLOBBERS); \
200 err = __a3; \
201 _sys_result = __v0; \
203 _sys_result; \
206 #define internal_syscall4(v0_init, input, number, err, \
207 arg1, arg2, arg3, arg4) \
208 ({ \
209 long _sys_result; \
212 register long __s0 asm ("$16") __attribute__ ((unused)) \
213 = (number); \
214 register long __v0 asm ("$2"); \
215 register long __a0 asm ("$4") = (long) (arg1); \
216 register long __a1 asm ("$5") = (long) (arg2); \
217 register long __a2 asm ("$6") = (long) (arg3); \
218 register long __a3 asm ("$7") = (long) (arg4); \
219 __asm__ volatile ( \
220 ".set\tnoreorder\n\t" \
221 v0_init \
222 "syscall\n\t" \
223 ".set\treorder" \
224 : "=r" (__v0), "+r" (__a3) \
225 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
226 : __SYSCALL_CLOBBERS); \
227 err = __a3; \
228 _sys_result = __v0; \
230 _sys_result; \
233 #define internal_syscall5(v0_init, input, number, err, \
234 arg1, arg2, arg3, arg4, arg5) \
235 ({ \
236 long _sys_result; \
239 register long __s0 asm ("$16") __attribute__ ((unused)) \
240 = (number); \
241 register long __v0 asm ("$2"); \
242 register long __a0 asm ("$4") = (long) (arg1); \
243 register long __a1 asm ("$5") = (long) (arg2); \
244 register long __a2 asm ("$6") = (long) (arg3); \
245 register long __a3 asm ("$7") = (long) (arg4); \
246 register long __a4 asm ("$8") = (long) (arg5); \
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), "r" (__a4) \
254 : __SYSCALL_CLOBBERS); \
255 err = __a3; \
256 _sys_result = __v0; \
258 _sys_result; \
261 #define internal_syscall6(v0_init, input, number, err, \
262 arg1, arg2, arg3, arg4, arg5, arg6) \
263 ({ \
264 long _sys_result; \
267 register long __s0 asm ("$16") __attribute__ ((unused)) \
268 = (number); \
269 register long __v0 asm ("$2"); \
270 register long __a0 asm ("$4") = (long) (arg1); \
271 register long __a1 asm ("$5") = (long) (arg2); \
272 register long __a2 asm ("$6") = (long) (arg3); \
273 register long __a3 asm ("$7") = (long) (arg4); \
274 register long __a4 asm ("$8") = (long) (arg5); \
275 register long __a5 asm ("$9") = (long) (arg6); \
276 __asm__ volatile ( \
277 ".set\tnoreorder\n\t" \
278 v0_init \
279 "syscall\n\t" \
280 ".set\treorder" \
281 : "=r" (__v0), "+r" (__a3) \
282 : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4), \
283 "r" (__a5) \
284 : __SYSCALL_CLOBBERS); \
285 err = __a3; \
286 _sys_result = __v0; \
288 _sys_result; \
291 #define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
292 "$14", "$15", "$24", "$25", "hi", "lo", "memory"
293 #endif /* __ASSEMBLER__ */
295 /* Pointer mangling is not yet supported for MIPS. */
296 #define PTR_MANGLE(var) (void) (var)
297 #define PTR_DEMANGLE(var) (void) (var)
299 #endif /* linux/mips/sysdep.h */