Move shared umount.c from hppa to mips.
[jlayton/glibc.git] / ports / sysdeps / unix / sysv / linux / mips / mips64 / n64 / sysdep.h
1 /* Copyright (C) 2000-2014 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    <http://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/mips/mips64/n64/sysdep.h>
23
24 #include <tls.h>
25
26 /* In order to get __set_errno() definition in INLINE_SYSCALL.  */
27 #ifndef __ASSEMBLER__
28 #include <errno.h>
29 #endif
30
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
37
38 #ifdef __ASSEMBLER__
39
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
43
44 #else   /* ! __ASSEMBLER__ */
45
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; })
58
59 #undef INTERNAL_SYSCALL_DECL
60 #define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused))
61
62 #undef INTERNAL_SYSCALL_ERROR_P
63 #define INTERNAL_SYSCALL_ERROR_P(val, err)   ((void) (val), (long) (err))
64
65 #undef INTERNAL_SYSCALL_ERRNO
66 #define INTERNAL_SYSCALL_ERRNO(val, err)     ((void) (err), val)
67
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.
77
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.
83
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.  */
88
89 #ifdef __mips_micromips
90 # define MOVE32 "move32"
91 #else
92 # define MOVE32 "move"
93 #endif
94
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)
100
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)
106
107 #define internal_syscall0(v0_init, input, number, err, dummy...)        \
108 ({                                                                      \
109         long _sys_result;                                               \
110                                                                         \
111         {                                                               \
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;                                             \
126         }                                                               \
127         _sys_result;                                                    \
128 })
129
130 #define internal_syscall1(v0_init, input, number, err, arg1)            \
131 ({                                                                      \
132         long _sys_result;                                               \
133                                                                         \
134         {                                                               \
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;                                             \
150         }                                                               \
151         _sys_result;                                                    \
152 })
153
154 #define internal_syscall2(v0_init, input, number, err, arg1, arg2)      \
155 ({                                                                      \
156         long _sys_result;                                               \
157                                                                         \
158         {                                                               \
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;                                             \
175         }                                                               \
176         _sys_result;                                                    \
177 })
178
179 #define internal_syscall3(v0_init, input, number, err,                  \
180                           arg1, arg2, arg3)                             \
181 ({                                                                      \
182         long _sys_result;                                               \
183                                                                         \
184         {                                                               \
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;                                             \
202         }                                                               \
203         _sys_result;                                                    \
204 })
205
206 #define internal_syscall4(v0_init, input, number, err,                  \
207                           arg1, arg2, arg3, arg4)                       \
208 ({                                                                      \
209         long _sys_result;                                               \
210                                                                         \
211         {                                                               \
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;                                             \
229         }                                                               \
230         _sys_result;                                                    \
231 })
232
233 #define internal_syscall5(v0_init, input, number, err,                  \
234                           arg1, arg2, arg3, arg4, arg5)                 \
235 ({                                                                      \
236         long _sys_result;                                               \
237                                                                         \
238         {                                                               \
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;                                             \
257         }                                                               \
258         _sys_result;                                                    \
259 })
260
261 #define internal_syscall6(v0_init, input, number, err,                  \
262                           arg1, arg2, arg3, arg4, arg5, arg6)           \
263 ({                                                                      \
264         long _sys_result;                                               \
265                                                                         \
266         {                                                               \
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;                                             \
287         }                                                               \
288         _sys_result;                                                    \
289 })
290
291 #define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
292         "$14", "$15", "$24", "$25", "hi", "lo", "memory"
293 #endif /* __ASSEMBLER__ */
294
295 /* Pointer mangling is not yet supported for MIPS.  */
296 #define PTR_MANGLE(var) (void) (var)
297 #define PTR_DEMANGLE(var) (void) (var)
298
299 #endif /* linux/mips/sysdep.h */