OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / mips / sysdep.h
1 /* Copyright (C) 1992, 1995, 1997, 1999, 2000, 2002, 2003, 2004
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Brendan Kehoe (brendan@zen.org).
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #ifndef _LINUX_MIPS_SYSDEP_H
21 #define _LINUX_MIPS_SYSDEP_H 1
22
23 #include <sgidefs.h>
24 #include <common/sysdep.h>
25
26 /* For Linux we can use the system call table in the header file
27    /usr/include/asm/unistd.h
28    of the kernel.  But these symbols do not follow the SYS_* syntax
29    so we have to redefine the `SYS_ify' macro here.  */
30
31 #undef SYS_ify
32 #ifdef __STDC__
33 # define SYS_ify(syscall_name)  __NR_##syscall_name
34 #else
35 # define SYS_ify(syscall_name)  __NR_/**/syscall_name
36 #endif
37
38 #ifdef __ASSEMBLER__
39
40 #include <sys/regdef.h>
41
42 #define ENTRY(name)                                     \
43   .globl name;                                          \
44   .align 2;                                             \
45   .ent name,0;                                          \
46   name##:
47
48 #undef END
49 #define END(function)                                   \
50                 .end    function;                       \
51                 .size   function,.-function
52
53 #define ret     j ra ; nop
54
55 #undef PSEUDO_END
56 #define PSEUDO_END(sym) .end sym; .size sym,.-sym
57
58 #define PSEUDO_NOERRNO(name, syscall_name, args)        \
59   .align 2;                                             \
60   ENTRY(name)                                           \
61   .set noreorder;                                       \
62   li v0, SYS_ify(syscall_name);                         \
63   syscall
64
65 #undef PSEUDO_END_NOERRNO
66 #define PSEUDO_END_NOERRNO(sym) .end sym; .size sym,.-sym
67
68 #define ret_NOERRNO ret
69
70 #define PSEUDO_ERRVAL(name, syscall_name, args)         \
71   .align 2;                                             \
72   ENTRY(name)                                           \
73   .set noreorder;                                       \
74   li v0, SYS_ify(syscall_name);                         \
75   syscall
76
77 #undef PSEUDO_END_ERRVAL
78 #define PSEUDO_END_ERRVAL(sym) .end sym; .size sym,.-sym
79
80 #define ret_ERRVAL ret
81
82 #define r0      v0
83 #define r1      v1
84 /* The mips move insn is d,s.  */
85 #define MOVE(x,y)       move y , x
86
87 #if _MIPS_SIM == _ABIO32
88 # define L(label) $L ## label
89 #else
90 # define L(label) .L ## label
91 #endif
92
93 /* Note that while it's better structurally, going back to call __syscall_error
94    can make things confusing if you're debugging---it looks like it's jumping
95    backwards into the previous fn.  */
96
97 #ifdef __PIC__
98 #define PSEUDO(name, syscall_name, args)                \
99   .align 2;                                             \
100   99: move a0, v0;                                      \
101   la t9,__syscall_error;                                \
102   jr t9;                                                \
103   ENTRY(name)                                           \
104   .set noreorder;                                       \
105   .cpload t9;                                           \
106   li v0, SYS_ify(syscall_name);                         \
107   syscall;                                              \
108   .set reorder;                                         \
109   bne a3, zero, 99b;                                    \
110 L(syse1):
111 #else
112 #define PSEUDO(name, syscall_name, args)                \
113   .set noreorder;                                       \
114   .align 2;                                             \
115   99: move a0, v0;                                      \
116   j __syscall_error;                                    \
117   nop;                                                  \
118   ENTRY(name)                                           \
119   .set noreorder;                                       \
120   li v0, SYS_ify(syscall_name);                         \
121   syscall;                                              \
122   .set reorder;                                         \
123   bne a3, zero, 99b;                                    \
124 L(syse1):
125 #endif
126
127 /* We don't want the label for the error handler to be visible in the symbol
128    table when we define it here.  */
129 #ifdef __PIC__
130 # define SYSCALL_ERROR_LABEL 99b
131 #endif
132
133 #else   /* ! __ASSEMBLER__ */
134
135 /* Define a macro which expands into the inline wrapper code for a system
136    call.  */
137 #undef INLINE_SYSCALL
138 #define INLINE_SYSCALL(name, nr, args...)                               \
139   ({ INTERNAL_SYSCALL_DECL(err);                                        \
140      long result_var = INTERNAL_SYSCALL (name, err, nr, args);          \
141      if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) )                  \
142        {                                                                \
143          __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err));        \
144          result_var = -1L;                                              \
145        }                                                                \
146      result_var; })
147
148 #undef INTERNAL_SYSCALL_DECL
149 #define INTERNAL_SYSCALL_DECL(err) long err
150
151 #undef INTERNAL_SYSCALL_ERROR_P
152 #define INTERNAL_SYSCALL_ERROR_P(val, err)   ((long) (err))
153
154 #undef INTERNAL_SYSCALL_ERRNO
155 #define INTERNAL_SYSCALL_ERRNO(val, err)     (val)
156
157 #undef INTERNAL_SYSCALL
158 #define INTERNAL_SYSCALL(name, err, nr, args...) \
159         internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t",      \
160                               "i" (SYS_ify (name)), err, args)
161
162 #undef INTERNAL_SYSCALL_NCS
163 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
164         internal_syscall##nr (= number, , "r" (__v0), err, args)
165 #undef internal_syscall0
166 #define internal_syscall0(ncs_init, cs_init, input, err, dummy...)      \
167 ({                                                                      \
168         long _sys_result;                                               \
169                                                                         \
170         {                                                               \
171         register long __v0 __asm__("$2") ncs_init;                      \
172         register long __a3 __asm__("$7");                               \
173         __asm__ __volatile__ (                                          \
174         ".set\tnoreorder\n\t"                                           \
175         cs_init                                                         \
176         "syscall\n\t"                                                   \
177         ".set reorder"                                                  \
178         : "=r" (__v0), "=r" (__a3)                                      \
179         : input                                                         \
180         : __SYSCALL_CLOBBERS);                                          \
181         err = __a3;                                                     \
182         _sys_result = __v0;                                             \
183         }                                                               \
184         _sys_result;                                                    \
185 })
186
187 #undef internal_syscall1
188 #define internal_syscall1(ncs_init, cs_init, input, err, arg1)          \
189 ({                                                                      \
190         long _sys_result;                                               \
191                                                                         \
192         {                                                               \
193         register long __v0 __asm__("$2") ncs_init;                      \
194         register long __a0 __asm__("$4") = (long) arg1;                 \
195         register long __a3 __asm__("$7");                               \
196         __asm__ __volatile__ (                                          \
197         ".set\tnoreorder\n\t"                                           \
198         cs_init                                                         \
199         "syscall\n\t"                                                   \
200         ".set reorder"                                                  \
201         : "=r" (__v0), "=r" (__a3)                                      \
202         : input, "r" (__a0)                                             \
203         : __SYSCALL_CLOBBERS);                                          \
204         err = __a3;                                                     \
205         _sys_result = __v0;                                             \
206         }                                                               \
207         _sys_result;                                                    \
208 })
209
210 #undef internal_syscall2
211 #define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2)    \
212 ({                                                                      \
213         long _sys_result;                                               \
214                                                                         \
215         {                                                               \
216         register long __v0 __asm__("$2") ncs_init;                      \
217         register long __a0 __asm__("$4") = (long) arg1;                 \
218         register long __a1 __asm__("$5") = (long) arg2;                 \
219         register long __a3 __asm__("$7");                               \
220         __asm__ __volatile__ (                                          \
221         ".set\tnoreorder\n\t"                                           \
222         cs_init                                                         \
223         "syscall\n\t"                                                   \
224         ".set\treorder"                                                 \
225         : "=r" (__v0), "=r" (__a3)                                      \
226         : input, "r" (__a0), "r" (__a1)                                 \
227         : __SYSCALL_CLOBBERS);                                          \
228         err = __a3;                                                     \
229         _sys_result = __v0;                                             \
230         }                                                               \
231         _sys_result;                                                    \
232 })
233
234 #undef internal_syscall3
235 #define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\
236 ({                                                                      \
237         long _sys_result;                                               \
238                                                                         \
239         {                                                               \
240         register long __v0 __asm__("$2") ncs_init;                      \
241         register long __a0 __asm__("$4") = (long) arg1;                 \
242         register long __a1 __asm__("$5") = (long) arg2;                 \
243         register long __a2 __asm__("$6") = (long) arg3;                 \
244         register long __a3 __asm__("$7");                               \
245         __asm__ __volatile__ (                                          \
246         ".set\tnoreorder\n\t"                                           \
247         cs_init                                                         \
248         "syscall\n\t"                                                   \
249         ".set\treorder"                                                 \
250         : "=r" (__v0), "=r" (__a3)                                      \
251         : input, "r" (__a0), "r" (__a1), "r" (__a2)                     \
252         : __SYSCALL_CLOBBERS);                                          \
253         err = __a3;                                                     \
254         _sys_result = __v0;                                             \
255         }                                                               \
256         _sys_result;                                                    \
257 })
258
259 #undef internal_syscall4
260 #define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\
261 ({                                                                      \
262         long _sys_result;                                               \
263                                                                         \
264         {                                                               \
265         register long __v0 __asm__("$2") ncs_init;                      \
266         register long __a0 __asm__("$4") = (long) arg1;                 \
267         register long __a1 __asm__("$5") = (long) arg2;                 \
268         register long __a2 __asm__("$6") = (long) arg3;                 \
269         register long __a3 __asm__("$7") = (long) arg4;                 \
270         __asm__ __volatile__ (                                          \
271         ".set\tnoreorder\n\t"                                           \
272         cs_init                                                         \
273         "syscall\n\t"                                                   \
274         ".set\treorder"                                                 \
275         : "=r" (__v0), "+r" (__a3)                                      \
276         : input, "r" (__a0), "r" (__a1), "r" (__a2)                     \
277         : __SYSCALL_CLOBBERS);                                          \
278         err = __a3;                                                     \
279         _sys_result = __v0;                                             \
280         }                                                               \
281         _sys_result;                                                    \
282 })
283
284 /* We need to use a frame pointer for the functions in which we
285    adjust $sp around the syscall, or debug information and unwind
286    information will be $sp relative and thus wrong during the syscall.  As
287    of GCC 3.4.3, this is sufficient.  */
288 #define FORCE_FRAME_POINTER alloca (4)
289
290 #undef internal_syscall5
291 #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\
292 ({                                                                      \
293         long _sys_result;                                               \
294                                                                         \
295         FORCE_FRAME_POINTER;                                            \
296         {                                                               \
297         register long __v0 __asm__("$2") ncs_init;                      \
298         register long __a0 __asm__("$4") = (long) arg1;                 \
299         register long __a1 __asm__("$5") = (long) arg2;                 \
300         register long __a2 __asm__("$6") = (long) arg3;                 \
301         register long __a3 __asm__("$7") = (long) arg4;                 \
302         __asm__ __volatile__ (                                          \
303         ".set\tnoreorder\n\t"                                           \
304         "subu\t$29, 32\n\t"                                             \
305         "sw\t%6, 16($29)\n\t"                                           \
306         cs_init                                                         \
307         "syscall\n\t"                                                   \
308         "addiu\t$29, 32\n\t"                                            \
309         ".set\treorder"                                                 \
310         : "=r" (__v0), "+r" (__a3)                                      \
311         : input, "r" (__a0), "r" (__a1), "r" (__a2),                    \
312           "r" ((long)arg5)                                              \
313         : __SYSCALL_CLOBBERS);                                          \
314         err = __a3;                                                     \
315         _sys_result = __v0;                                             \
316         }                                                               \
317         _sys_result;                                                    \
318 })
319
320 #undef internal_syscall6
321 #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\
322 ({                                                                      \
323         long _sys_result;                                               \
324                                                                         \
325         FORCE_FRAME_POINTER;                                            \
326         {                                                               \
327         register long __v0 __asm__("$2") ncs_init;                      \
328         register long __a0 __asm__("$4") = (long) arg1;                 \
329         register long __a1 __asm__("$5") = (long) arg2;                 \
330         register long __a2 __asm__("$6") = (long) arg3;                 \
331         register long __a3 __asm__("$7") = (long) arg4;                 \
332         __asm__ __volatile__ (                                          \
333         ".set\tnoreorder\n\t"                                           \
334         "subu\t$29, 32\n\t"                                             \
335         "sw\t%6, 16($29)\n\t"                                           \
336         "sw\t%7, 20($29)\n\t"                                           \
337         cs_init                                                         \
338         "syscall\n\t"                                                   \
339         "addiu\t$29, 32\n\t"                                            \
340         ".set\treorder"                                                 \
341         : "=r" (__v0), "+r" (__a3)                                      \
342         : input, "r" (__a0), "r" (__a1), "r" (__a2),                    \
343           "r" ((long)arg5), "r" ((long)arg6)                            \
344         : __SYSCALL_CLOBBERS);                                          \
345         err = __a3;                                                     \
346         _sys_result = __v0;                                             \
347         }                                                               \
348         _sys_result;                                                    \
349 })
350
351 #undef internal_syscall7
352 #define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
353 ({                                                                      \
354         long _sys_result;                                               \
355                                                                         \
356         FORCE_FRAME_POINTER;                                            \
357         {                                                               \
358         register long __v0 __asm__("$2") ncs_init;                      \
359         register long __a0 __asm__("$4") = (long) arg1;                 \
360         register long __a1 __asm__("$5") = (long) arg2;                 \
361         register long __a2 __asm__("$6") = (long) arg3;                 \
362         register long __a3 __asm__("$7") = (long) arg4;                 \
363         __asm__ __volatile__ (                                          \
364         ".set\tnoreorder\n\t"                                           \
365         "subu\t$29, 32\n\t"                                             \
366         "sw\t%6, 16($29)\n\t"                                           \
367         "sw\t%7, 20($29)\n\t"                                           \
368         "sw\t%8, 24($29)\n\t"                                           \
369         cs_init                                                         \
370         "syscall\n\t"                                                   \
371         "addiu\t$29, 32\n\t"                                            \
372         ".set\treorder"                                                 \
373         : "=r" (__v0), "+r" (__a3)                                      \
374         : input, "r" (__a0), "r" (__a1), "r" (__a2),                    \
375           "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7)          \
376         : __SYSCALL_CLOBBERS);                                          \
377         err = __a3;                                                     \
378         _sys_result = __v0;                                             \
379         }                                                               \
380         _sys_result;                                                    \
381 })
382
383 #undef __SYSCALL_CLOBBERS
384 #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
385         "$14", "$15", "$24", "$25", "memory"
386
387 /* Pointer mangling is not yet supported for MIPS.  */
388 #define PTR_MANGLE(var) (void) (var)
389 #define PTR_DEMANGLE(var) (void) (var)
390
391 #endif  /* __ASSEMBLER__ */
392 #endif /* _LINUX_MIPS_SYSDEP_H */