710479ae18f1099b261bb84d2af650f1d3823c1e
[jlayton/glibc.git] / sysdeps / unix / sysv / linux / mips / sysdep.h
1 /* Copyright (C) 2000 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, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #ifndef _LINUX_MIPS_SYSDEP_H
20 #define _LINUX_MIPS_SYSDEP_H 1
21
22 /* There is some commonality.  */
23 #include <sysdeps/unix/mips/sysdep.h>
24
25 /* For Linux we can use the system call table in the header file
26         /usr/include/asm/unistd.h
27    of the kernel.  But these symbols do not follow the SYS_* syntax
28    so we have to redefine the `SYS_ify' macro here.  */
29 #undef SYS_ify
30 #ifdef __STDC__
31 # define SYS_ify(syscall_name)  __NR_##syscall_name
32 #else
33 # define SYS_ify(syscall_name)  __NR_/**/syscall_name
34 #endif
35
36 #ifdef __ASSEMBLER__
37
38 /* We don't want the label for the error handler to be visible in the symbol
39    table when we define it here.  */
40 #ifdef __PIC__
41 # define SYSCALL_ERROR_LABEL 99b
42 #endif
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
61
62 #undef INTERNAL_SYSCALL_ERROR_P
63 #define INTERNAL_SYSCALL_ERROR_P(val, err)   ((long) (err))
64
65 #undef INTERNAL_SYSCALL_ERRNO
66 #define INTERNAL_SYSCALL_ERRNO(val, err)     (val)
67
68 #undef INTERNAL_SYSCALL
69 #define INTERNAL_SYSCALL(name, err, nr, args...) internal_syscall##nr(name, err, args)
70
71 #define internal_syscall0(name, err, dummy...)                          \
72 ({                                                                      \
73         long _sys_result;                                               \
74                                                                         \
75         {                                                               \
76         register long __v0 asm("$2");                                   \
77         register long __a3 asm("$7");                                   \
78         __asm__ volatile (                                              \
79         ".set\tnoreorder\n\t"                                           \
80         "li\t$2, %2\t\t\t# " #name "\n\t"                               \
81         "syscall\n\t"                                                   \
82         ".set reorder"                                                  \
83         : "=r" (__v0), "=r" (__a3)                                      \
84         : "i" (SYS_ify(name))                                           \
85         : __SYSCALL_CLOBBERS);                                          \
86         err = __a3;                                                     \
87         _sys_result = __v0;                                             \
88         }                                                               \
89         _sys_result;                                                    \
90 })
91
92 #define internal_syscall1(name, err, arg1)                              \
93 ({                                                                      \
94         long _sys_result;                                               \
95                                                                         \
96         {                                                               \
97         register long __v0 asm("$2");                                   \
98         register long __a0 asm("$4") = (long) arg1;                     \
99         register long __a3 asm("$7");                                   \
100         __asm__ volatile (                                              \
101         ".set\tnoreorder\n\t"                                           \
102         "li\t$2, %3\t\t\t# " #name "\n\t"                               \
103         "syscall\n\t"                                                   \
104         ".set reorder"                                                  \
105         : "=r" (__v0), "=r" (__a3)                                      \
106         : "r" (__a0), "i" (SYS_ify(name))                               \
107         : __SYSCALL_CLOBBERS);                                          \
108         err = __a3;                                                     \
109         _sys_result = __v0;                                             \
110         }                                                               \
111         _sys_result;                                                    \
112 })
113
114 #define internal_syscall2(name, err, arg1, arg2)                        \
115 ({                                                                      \
116         long _sys_result;                                               \
117                                                                         \
118         {                                                               \
119         register long __v0 asm("$2");                                   \
120         register long __a0 asm("$4") = (long) arg1;                     \
121         register long __a1 asm("$5") = (long) arg2;                     \
122         register long __a3 asm("$7");                                   \
123         __asm__ volatile (                                              \
124         ".set\tnoreorder\n\t"                                           \
125         "li\t$2, %4\t\t\t# " #name "\n\t"                               \
126         "syscall\n\t"                                                   \
127         ".set\treorder"                                                 \
128         : "=r" (__v0), "=r" (__a3)                                      \
129         : "r" (__a0), "r" (__a1), "i" (SYS_ify(name))                   \
130         : __SYSCALL_CLOBBERS);                                          \
131         err = __a3;                                                     \
132         _sys_result = __v0;                                             \
133         }                                                               \
134         _sys_result;                                                    \
135 })
136
137 #define internal_syscall3(name, err, arg1, arg2, arg3)                  \
138 ({                                                                      \
139         long _sys_result;                                               \
140                                                                         \
141         {                                                               \
142         register long __v0 asm("$2");                                   \
143         register long __a0 asm("$4") = (long) arg1;                     \
144         register long __a1 asm("$5") = (long) arg2;                     \
145         register long __a2 asm("$6") = (long) arg3;                     \
146         register long __a3 asm("$7");                                   \
147         __asm__ volatile (                                              \
148         ".set\tnoreorder\n\t"                                           \
149         "li\t$2, %5\t\t\t# " #name "\n\t"                               \
150         "syscall\n\t"                                                   \
151         ".set\treorder"                                                 \
152         : "=r" (__v0), "=r" (__a3)                                      \
153         : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name))       \
154         : __SYSCALL_CLOBBERS);                                          \
155         err = __a3;                                                     \
156         _sys_result = __v0;                                             \
157         }                                                               \
158         _sys_result;                                                    \
159 })
160
161 #define internal_syscall4(name, err, arg1, arg2, arg3, arg4)            \
162 ({                                                                      \
163         long _sys_result;                                               \
164                                                                         \
165         {                                                               \
166         register long __v0 asm("$2");                                   \
167         register long __a0 asm("$4") = (long) arg1;                     \
168         register long __a1 asm("$5") = (long) arg2;                     \
169         register long __a2 asm("$6") = (long) arg3;                     \
170         register long __a3 asm("$7") = (long) arg4;                     \
171         __asm__ volatile (                                              \
172         ".set\tnoreorder\n\t"                                           \
173         "li\t$2, %5\t\t\t# " #name "\n\t"                               \
174         "syscall\n\t"                                                   \
175         ".set\treorder"                                                 \
176         : "=r" (__v0), "+r" (__a3)                                      \
177         : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name))       \
178         : __SYSCALL_CLOBBERS);                                          \
179         err = __a3;                                                     \
180         _sys_result = __v0;                                             \
181         }                                                               \
182         _sys_result;                                                    \
183 })
184
185 #define internal_syscall5(name, err, arg1, arg2, arg3, arg4, arg5)      \
186 ({                                                                      \
187         long _sys_result;                                               \
188                                                                         \
189         {                                                               \
190         register long __v0 asm("$2");                                   \
191         register long __a0 asm("$4") = (long) arg1;                     \
192         register long __a1 asm("$5") = (long) arg2;                     \
193         register long __a2 asm("$6") = (long) arg3;                     \
194         register long __a3 asm("$7") = (long) arg4;                     \
195         __asm__ volatile (                                              \
196         ".set\tnoreorder\n\t"                                           \
197         "lw\t$2, %6\n\t"                                                \
198         "subu\t$29, 32\n\t"                                             \
199         "sw\t$2, 16($29)\n\t"                                           \
200         "li\t$2, %5\t\t\t# " #name "\n\t"                               \
201         "syscall\n\t"                                                   \
202         "addiu\t$29, 32\n\t"                                            \
203         ".set\treorder"                                                 \
204         : "=r" (__v0), "+r" (__a3)                                      \
205         : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)),      \
206           "m" ((long)arg5)                                              \
207         : __SYSCALL_CLOBBERS);                                          \
208         err = __a3;                                                     \
209         _sys_result = __v0;                                             \
210         }                                                               \
211         _sys_result;                                                    \
212 })
213
214 #define internal_syscall6(name, err, arg1, arg2, arg3, arg4, arg5, arg6)\
215 ({                                                                      \
216         long _sys_result;                                               \
217                                                                         \
218         {                                                               \
219         register long __v0 asm("$2");                                   \
220         register long __a0 asm("$4") = (long) arg1;                     \
221         register long __a1 asm("$5") = (long) arg2;                     \
222         register long __a2 asm("$6") = (long) arg3;                     \
223         register long __a3 asm("$7") = (long) arg4;                     \
224         __asm__ volatile (                                              \
225         ".set\tnoreorder\n\t"                                           \
226         "lw\t$2, %6\n\t"                                                \
227         "lw\t$8, %7\n\t"                                                \
228         "subu\t$29, 32\n\t"                                             \
229         "sw\t$2, 16($29)\n\t"                                           \
230         "sw\t$8, 20($29)\n\t"                                           \
231         "li\t$2, %5\t\t\t# " #name "\n\t"                               \
232         "syscall\n\t"                                                   \
233         "addiu\t$29, 32\n\t"                                            \
234         ".set\treorder"                                                 \
235         : "=r" (__v0), "+r" (__a3)                                      \
236         : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)),      \
237           "m" ((long)arg5), "m" ((long)arg6)                            \
238         : __SYSCALL_CLOBBERS);                                          \
239         err = __a3;                                                     \
240         _sys_result = __v0;                                             \
241         }                                                               \
242         _sys_result;                                                    \
243 })
244
245 #define internal_syscall7(name, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
246 ({                                                                      \
247         long _sys_result;                                               \
248                                                                         \
249         {                                                               \
250         register long __v0 asm("$2");                                   \
251         register long __a0 asm("$4") = (long) arg1;                     \
252         register long __a1 asm("$5") = (long) arg2;                     \
253         register long __a2 asm("$6") = (long) arg3;                     \
254         register long __a3 asm("$7") = (long) arg4;                     \
255         __asm__ volatile (                                              \
256         ".set\tnoreorder\n\t"                                           \
257         "lw\t$2, %6\n\t"                                                \
258         "lw\t$8, %7\n\t"                                                \
259         "lw\t$9, %8\n\t"                                                \
260         "subu\t$29, 32\n\t"                                             \
261         "sw\t$2, 16($29)\n\t"                                           \
262         "sw\t$8, 20($29)\n\t"                                           \
263         "sw\t$9, 24($29)\n\t"                                           \
264         "li\t$2, %5\t\t\t# " #name "\n\t"                               \
265         "syscall\n\t"                                                   \
266         "addiu\t$29, 32\n\t"                                            \
267         ".set\treorder"                                                 \
268         : "=r" (__v0), "+r" (__a3)                                      \
269         : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)),      \
270           "m" ((long)arg5), "m" ((long)arg6), "m" ((long)arg7)          \
271         : __SYSCALL_CLOBBERS);                                          \
272         err = __a3;                                                     \
273         _sys_result = __v0;                                             \
274         }                                                               \
275         _sys_result;                                                    \
276 })
277
278 #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25"
279
280 #endif /* __ASSEMBLER__ */
281
282 #endif /* linux/mips/sysdep.h */