OSDN Git Service

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