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
21 #ifndef _LINUX_MIPS_SYSDEP_H
22 #define _LINUX_MIPS_SYSDEP_H 1
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. */
34 # define SYS_ify(syscall_name) __NR_##syscall_name
36 # define SYS_ify(syscall_name) __NR_/**/syscall_name
41 #include <sys/regdef.h>
50 #define END(function) \
52 .size function,.-function
54 #define ret j ra ; nop
57 #define PSEUDO_END(sym) .end sym; .size sym,.-sym
59 #define PSEUDO_NOERRNO(name, syscall_name, args) \
63 li v0, SYS_ify(syscall_name); \
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) \
75 li v0, SYS_ify(syscall_name); \
78 #undef PSEUDO_END_ERRVAL
79 #define PSEUDO_END_ERRVAL(sym) .end sym; .size sym,.-sym
81 #define ret_ERRVAL ret
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
91 # define L(label) .L ## label
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. */
99 #define PSEUDO(name, syscall_name, args) \
102 la t9,__syscall_error; \
107 li v0, SYS_ify(syscall_name); \
113 #define PSEUDO(name, syscall_name, args) \
121 li v0, SYS_ify(syscall_name); \
128 /* We don't want the label for the error handler to be visible in the symbol
129 table when we define it here. */
131 # define SYSCALL_ERROR_LABEL 99b
134 #else /* ! __ASSEMBLER__ */
136 /* Define a macro which expands into the inline wrapper code for a system
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) ) \
144 __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \
149 #undef INTERNAL_SYSCALL_DECL
150 #define INTERNAL_SYSCALL_DECL(err) long err
152 #undef INTERNAL_SYSCALL_ERROR_P
153 #define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err))
155 #undef INTERNAL_SYSCALL_ERRNO
156 #define INTERNAL_SYSCALL_ERRNO(val, err) (val)
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)
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...) \
172 register long __v0 __asm__("$2") ncs_init; \
173 register long __a3 __asm__("$7"); \
174 __asm__ __volatile__ ( \
175 ".set\tnoreorder\n\t" \
179 : "=r" (__v0), "=r" (__a3) \
181 : __SYSCALL_CLOBBERS); \
183 _sys_result = __v0; \
188 #undef internal_syscall1
189 #define internal_syscall1(ncs_init, cs_init, input, err, arg1) \
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" \
202 : "=r" (__v0), "=r" (__a3) \
203 : input, "r" (__a0) \
204 : __SYSCALL_CLOBBERS); \
206 _sys_result = __v0; \
211 #undef internal_syscall2
212 #define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \
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" \
226 : "=r" (__v0), "=r" (__a3) \
227 : input, "r" (__a0), "r" (__a1) \
228 : __SYSCALL_CLOBBERS); \
230 _sys_result = __v0; \
235 #undef internal_syscall3
236 #define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\
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" \
251 : "=r" (__v0), "=r" (__a3) \
252 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
253 : __SYSCALL_CLOBBERS); \
255 _sys_result = __v0; \
260 #undef internal_syscall4
261 #define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\
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" \
276 : "=r" (__v0), "+r" (__a3) \
277 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
278 : __SYSCALL_CLOBBERS); \
280 _sys_result = __v0; \
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)
291 #undef internal_syscall5
292 #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\
296 FORCE_FRAME_POINTER; \
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" \
309 "addiu\t$29, 32\n\t" \
311 : "=r" (__v0), "+r" (__a3) \
312 : input, "r" (__a0), "r" (__a1), "r" (__a2), \
314 : __SYSCALL_CLOBBERS); \
316 _sys_result = __v0; \
321 #undef internal_syscall6
322 #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\
326 FORCE_FRAME_POINTER; \
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" \
340 "addiu\t$29, 32\n\t" \
342 : "=r" (__v0), "+r" (__a3) \
343 : input, "r" (__a0), "r" (__a1), "r" (__a2), \
344 "r" ((long)arg5), "r" ((long)arg6) \
345 : __SYSCALL_CLOBBERS); \
347 _sys_result = __v0; \
352 #undef internal_syscall7
353 #define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
357 FORCE_FRAME_POINTER; \
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" \
372 "addiu\t$29, 32\n\t" \
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); \
379 _sys_result = __v0; \
384 #undef __SYSCALL_CLOBBERS
385 #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
386 "$14", "$15", "$24", "$25", "memory"
388 /* Pointer mangling is not yet supported for MIPS. */
389 #define PTR_MANGLE(var) (void) (var)
390 #define PTR_DEMANGLE(var) (void) (var)
392 #endif /* __ASSEMBLER__ */
393 #endif /* _LINUX_MIPS_SYSDEP_H */