mips/sysdep.h: Unify mips sysdep.h
[uclibc-ng.git] / libc / sysdeps / linux / mips / sysdep.h
blob0c30e20d7e0d9a2ae540e323bbc78dc3adefe699
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).
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.
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.
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. */
21 #ifndef _LINUX_MIPS_SYSDEP_H
22 #define _LINUX_MIPS_SYSDEP_H 1
24 #include <sgidefs.h>
25 #include <common/sysdep.h>
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. */
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
39 #ifdef __ASSEMBLER__
41 #include <regdef.h>
43 #define ENTRY(name) \
44 .globl name; \
45 .align 2; \
46 .ent name,0; \
47 name##:
49 #undef END
50 #define END(function) \
51 .end function; \
52 .size function,.-function
54 #define ret j ra ; nop
56 #undef PSEUDO_END
57 #define PSEUDO_END(sym) .end sym; .size sym,.-sym
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
66 #undef PSEUDO_END_NOERRNO
67 #define PSEUDO_END_NOERRNO(sym) .end sym; .size sym,.-sym
69 #define ret_NOERRNO ret
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
78 #undef PSEUDO_END_ERRVAL
79 #define PSEUDO_END_ERRVAL(sym) .end sym; .size sym,.-sym
81 #define ret_ERRVAL ret
83 #define r0 v0
84 #define r1 v1
85 /* The mips move insn is d,s. */
86 #define MOVE(x,y) move y , x
88 #if _MIPS_SIM == _ABIO32
89 # define L(label) $L ## label
90 #else
91 # define L(label) .L ## label
92 #endif
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. */
98 #ifdef __PIC__
99 #define PSEUDO(name, syscall_name, args) \
100 .align 2; \
101 99: 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: j __syscall_error; \
116 nop; \
117 ENTRY(name) \
118 .set noreorder; \
119 li v0, SYS_ify(syscall_name); \
120 syscall; \
121 .set reorder; \
122 bne a3, zero, 99b; \
123 L(syse1):
124 #endif
126 /* We don't want the label for the error handler to be visible in the symbol
127 table when we define it here. */
128 #ifdef __PIC__
129 # define SYSCALL_ERROR_LABEL 99b
130 #endif
132 #else /* ! __ASSEMBLER__ */
134 /* Define a macro which expands into the inline wrapper code for a system
135 call. */
136 #undef INLINE_SYSCALL
137 #define INLINE_SYSCALL(name, nr, args...) \
138 ({ INTERNAL_SYSCALL_DECL(err); \
139 long result_var = INTERNAL_SYSCALL (name, err, nr, args); \
140 if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \
142 __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \
143 result_var = -1L; \
145 result_var; })
147 #undef INTERNAL_SYSCALL_DECL
148 #define INTERNAL_SYSCALL_DECL(err) long err
150 #undef INTERNAL_SYSCALL_ERROR_P
151 #define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err))
153 #undef INTERNAL_SYSCALL_ERRNO
154 #define INTERNAL_SYSCALL_ERRNO(val, err) (val)
156 #undef INTERNAL_SYSCALL
157 #define INTERNAL_SYSCALL(name, err, nr, args...) \
158 internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \
159 "i" (SYS_ify (name)), err, args)
161 #undef INTERNAL_SYSCALL_NCS
162 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
163 internal_syscall##nr (= number, , "r" (__v0), err, args)
164 #undef internal_syscall0
165 #define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \
166 ({ \
167 long _sys_result; \
170 register long __v0 __asm__("$2") ncs_init; \
171 register long __a3 __asm__("$7"); \
172 __asm__ volatile ( \
173 ".set\tnoreorder\n\t" \
174 cs_init \
175 "syscall\n\t" \
176 ".set reorder" \
177 : "=r" (__v0), "=r" (__a3) \
178 : input \
179 : __SYSCALL_CLOBBERS); \
180 err = __a3; \
181 _sys_result = __v0; \
183 _sys_result; \
186 #undef internal_syscall1
187 #define internal_syscall1(ncs_init, cs_init, input, err, arg1) \
188 ({ \
189 long _sys_result; \
192 register long __v0 __asm__("$2") ncs_init; \
193 register long __a0 __asm__("$4") = (long) arg1; \
194 register long __a3 __asm__("$7"); \
195 __asm__ volatile ( \
196 ".set\tnoreorder\n\t" \
197 cs_init \
198 "syscall\n\t" \
199 ".set reorder" \
200 : "=r" (__v0), "=r" (__a3) \
201 : input, "r" (__a0) \
202 : __SYSCALL_CLOBBERS); \
203 err = __a3; \
204 _sys_result = __v0; \
206 _sys_result; \
209 #undef internal_syscall2
210 #define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \
211 ({ \
212 long _sys_result; \
215 register long __v0 __asm__("$2") ncs_init; \
216 register long __a0 __asm__("$4") = (long) arg1; \
217 register long __a1 __asm__("$5") = (long) arg2; \
218 register long __a3 __asm__("$7"); \
219 __asm__ volatile ( \
220 ".set\tnoreorder\n\t" \
221 cs_init \
222 "syscall\n\t" \
223 ".set\treorder" \
224 : "=r" (__v0), "=r" (__a3) \
225 : input, "r" (__a0), "r" (__a1) \
226 : __SYSCALL_CLOBBERS); \
227 err = __a3; \
228 _sys_result = __v0; \
230 _sys_result; \
233 #undef internal_syscall3
234 #define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\
235 ({ \
236 long _sys_result; \
239 register long __v0 __asm__("$2") ncs_init; \
240 register long __a0 __asm__("$4") = (long) arg1; \
241 register long __a1 __asm__("$5") = (long) arg2; \
242 register long __a2 __asm__("$6") = (long) arg3; \
243 register long __a3 __asm__("$7"); \
244 __asm__ volatile ( \
245 ".set\tnoreorder\n\t" \
246 cs_init \
247 "syscall\n\t" \
248 ".set\treorder" \
249 : "=r" (__v0), "=r" (__a3) \
250 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
251 : __SYSCALL_CLOBBERS); \
252 err = __a3; \
253 _sys_result = __v0; \
255 _sys_result; \
258 #undef internal_syscall4
259 #define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\
260 ({ \
261 long _sys_result; \
264 register long __v0 __asm__("$2") ncs_init; \
265 register long __a0 __asm__("$4") = (long) arg1; \
266 register long __a1 __asm__("$5") = (long) arg2; \
267 register long __a2 __asm__("$6") = (long) arg3; \
268 register long __a3 __asm__("$7") = (long) arg4; \
269 __asm__ volatile ( \
270 ".set\tnoreorder\n\t" \
271 cs_init \
272 "syscall\n\t" \
273 ".set\treorder" \
274 : "=r" (__v0), "+r" (__a3) \
275 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
276 : __SYSCALL_CLOBBERS); \
277 err = __a3; \
278 _sys_result = __v0; \
280 _sys_result; \
283 /* We need to use a frame pointer for the functions in which we
284 adjust $sp around the syscall, or debug information and unwind
285 information will be $sp relative and thus wrong during the syscall. As
286 of GCC 3.4.3, this is sufficient. */
287 #define FORCE_FRAME_POINTER alloca (4)
289 #undef internal_syscall5
290 #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\
291 ({ \
292 long _sys_result; \
294 FORCE_FRAME_POINTER; \
296 register long __v0 __asm__("$2") ncs_init; \
297 register long __a0 __asm__("$4") = (long) arg1; \
298 register long __a1 __asm__("$5") = (long) arg2; \
299 register long __a2 __asm__("$6") = (long) arg3; \
300 register long __a3 __asm__("$7") = (long) arg4; \
301 __asm__ volatile ( \
302 ".set\tnoreorder\n\t" \
303 "subu\t$29, 32\n\t" \
304 "sw\t%6, 16($29)\n\t" \
305 cs_init \
306 "syscall\n\t" \
307 "addiu\t$29, 32\n\t" \
308 ".set\treorder" \
309 : "=r" (__v0), "+r" (__a3) \
310 : input, "r" (__a0), "r" (__a1), "r" (__a2), \
311 "r" ((long)arg5) \
312 : __SYSCALL_CLOBBERS); \
313 err = __a3; \
314 _sys_result = __v0; \
316 _sys_result; \
319 #undef internal_syscall6
320 #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\
321 ({ \
322 long _sys_result; \
324 FORCE_FRAME_POINTER; \
326 register long __v0 __asm__("$2") ncs_init; \
327 register long __a0 __asm__("$4") = (long) arg1; \
328 register long __a1 __asm__("$5") = (long) arg2; \
329 register long __a2 __asm__("$6") = (long) arg3; \
330 register long __a3 __asm__("$7") = (long) arg4; \
331 __asm__ volatile ( \
332 ".set\tnoreorder\n\t" \
333 "subu\t$29, 32\n\t" \
334 "sw\t%6, 16($29)\n\t" \
335 "sw\t%7, 20($29)\n\t" \
336 cs_init \
337 "syscall\n\t" \
338 "addiu\t$29, 32\n\t" \
339 ".set\treorder" \
340 : "=r" (__v0), "+r" (__a3) \
341 : input, "r" (__a0), "r" (__a1), "r" (__a2), \
342 "r" ((long)arg5), "r" ((long)arg6) \
343 : __SYSCALL_CLOBBERS); \
344 err = __a3; \
345 _sys_result = __v0; \
347 _sys_result; \
350 #undef internal_syscall7
351 #define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
352 ({ \
353 long _sys_result; \
355 FORCE_FRAME_POINTER; \
357 register long __v0 __asm__("$2") ncs_init; \
358 register long __a0 __asm__("$4") = (long) arg1; \
359 register long __a1 __asm__("$5") = (long) arg2; \
360 register long __a2 __asm__("$6") = (long) arg3; \
361 register long __a3 __asm__("$7") = (long) arg4; \
362 __asm__ volatile ( \
363 ".set\tnoreorder\n\t" \
364 "subu\t$29, 32\n\t" \
365 "sw\t%6, 16($29)\n\t" \
366 "sw\t%7, 20($29)\n\t" \
367 "sw\t%8, 24($29)\n\t" \
368 cs_init \
369 "syscall\n\t" \
370 "addiu\t$29, 32\n\t" \
371 ".set\treorder" \
372 : "=r" (__v0), "+r" (__a3) \
373 : input, "r" (__a0), "r" (__a1), "r" (__a2), \
374 "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \
375 : __SYSCALL_CLOBBERS); \
376 err = __a3; \
377 _sys_result = __v0; \
379 _sys_result; \
382 #undef __SYSCALL_CLOBBERS
383 #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
384 "$14", "$15", "$24", "$25", "memory"
387 #endif /* __ASSEMBLER__ */
388 #endif /* _LINUX_MIPS_SYSDEP_H */