1 /* Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Written by Jes Sorensen, <Jes.Sorensen@cern.ch>, April 1999.
4 Based on code originally written by David Mosberger-Tang
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_IA64_SYSDEP_H
22 #define _LINUX_IA64_SYSDEP_H 1
24 #include <sysdeps/unix/sysdep.h>
25 #include <sysdeps/ia64/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. */
33 # define SYS_ify(syscall_name) __NR_##syscall_name
35 # define SYS_ify(syscall_name) __NR_/**/syscall_name
38 /* This is a kludge to make syscalls.list find these under the names
39 pread and pwrite, since some kernel headers define those names
40 and some define the *64 names for the same system calls. */
41 #if !defined __NR_pread && defined __NR_pread64
42 # define __NR_pread __NR_pread64
44 #if !defined __NR_pwrite && defined __NR_pwrite64
45 # define __NR_pwrite __NR_pwrite64
52 # define CALL_MCOUNT \
54 1: data8 0; /* XXX fixme: use .xdata8 once labels work */ \
58 alloc out0 = ar.pfs, 8, 0, 4, 0; \
64 addl out3 = @ltoff(1b), gp; \
65 br.call.sptk.many rp = _mcount \
68 # define CALL_MCOUNT /* Do nothing. */
71 /* Linux uses a negative return value to indicate syscall errors, unlike
72 most Unices, which use the condition codes' carry flag.
74 Since version 2.1 the return value of a system call might be negative
75 even if the call succeeded. E.g., the `lseek' system call might return
76 a large offset. Therefore we must not anymore test for < 0, but test
77 for a real error by making sure the value in %d0 is a real error
78 number. Linus said he will make sure the no syscall returns a value
79 in -1 .. -4095 as a valid result so we can savely test with -4095. */
81 /* We don't want the label for the error handler to be visible in the symbol
82 table when we define it here. */
83 #define SYSCALL_ERROR_LABEL __syscall_error
86 #define PSEUDO(name, syscall_name, args) \
88 DO_CALL (SYS_ify(syscall_name)); \
89 cmp.eq p6,p0=-1,r10; \
90 (p6) br.cond.spnt.few __syscall_error;
92 #define DO_CALL(num) \
94 break __BREAK_SYSCALL;
97 #define PSEUDO_END(name) .endp C_SYMBOL_NAME(name);
101 .size C_SYMBOL_NAME(name), . - C_SYMBOL_NAME(name) ; \
102 .endp C_SYMBOL_NAME(name)
104 #define ret br.ret.sptk.few b0
106 #else /* not __ASSEMBLER__ */
108 /* On IA-64 we have stacked registers for passing arguments. The
109 "out" registers end up being the called function's "in"
112 Also, since we have plenty of registers we have two return values
113 from a syscall. r10 is set to -1 on error, whilst r8 contains the
114 (non-negative) errno on error or the return value on success.
116 #undef INLINE_SYSCALL
117 #define INLINE_SYSCALL(name, nr, args...) \
119 register long _r8 asm ("r8"); \
120 register long _r10 asm ("r10"); \
121 register long _r15 asm ("r15") = __NR_##name; \
123 LOAD_ARGS_##nr (args); \
124 __asm __volatile ("break %3;;\n\t" \
125 : "=r" (_r8), "=r" (_r10), "=r" (_r15) \
126 : "i" (__BREAK_SYSCALL), "2" (_r15) \
128 : "memory" ASM_CLOBBERS_##nr); \
132 __set_errno (_retval); \
137 #undef INTERNAL_SYSCALL_DECL
138 #define INTERNAL_SYSCALL_DECL(err) long int err
140 #undef INTERNAL_SYSCALL
141 #define INTERNAL_SYSCALL(name, err, nr, args...) \
143 register long _r8 asm ("r8"); \
144 register long _r10 asm ("r10"); \
145 register long _r15 asm ("r15") = __NR_##name; \
147 LOAD_ARGS_##nr (args); \
148 __asm __volatile ("break %3;;\n\t" \
149 : "=r" (_r8), "=r" (_r10), "=r" (_r15) \
150 : "i" (__BREAK_SYSCALL), "2" (_r15) \
152 : "memory" ASM_CLOBBERS_##nr); \
157 #undef INTERNAL_SYSCALL_ERROR_P
158 #define INTERNAL_SYSCALL_ERROR_P(val, err) (err == -1)
160 #undef INTERNAL_SYSCALL_ERRNO
161 #define INTERNAL_SYSCALL_ERRNO(val, err) (val)
163 #define LOAD_ARGS_0() do { } while (0)
164 #define LOAD_ARGS_1(out0) \
165 register long _out0 asm ("out0") = (long) (out0); \
167 #define LOAD_ARGS_2(out0, out1) \
168 register long _out1 asm ("out1") = (long) (out1); \
170 #define LOAD_ARGS_3(out0, out1, out2) \
171 register long _out2 asm ("out2") = (long) (out2); \
172 LOAD_ARGS_2 (out0, out1)
173 #define LOAD_ARGS_4(out0, out1, out2, out3) \
174 register long _out3 asm ("out3") = (long) (out3); \
175 LOAD_ARGS_3 (out0, out1, out2)
176 #define LOAD_ARGS_5(out0, out1, out2, out3, out4) \
177 register long _out4 asm ("out4") = (long) (out4); \
178 LOAD_ARGS_4 (out0, out1, out2, out3)
181 #define ASM_ARGS_1 ASM_ARGS_0, "r" (_out0)
182 #define ASM_ARGS_2 ASM_ARGS_1, "r" (_out1)
183 #define ASM_ARGS_3 ASM_ARGS_2, "r" (_out2)
184 #define ASM_ARGS_4 ASM_ARGS_3, "r" (_out3)
185 #define ASM_ARGS_5 ASM_ARGS_4, "r" (_out4)
187 #define ASM_CLOBBERS_0 ASM_CLOBBERS_1, "out0"
188 #define ASM_CLOBBERS_1 ASM_CLOBBERS_2, "out1"
189 #define ASM_CLOBBERS_2 ASM_CLOBBERS_3, "out2"
190 #define ASM_CLOBBERS_3 ASM_CLOBBERS_4, "out3"
191 #define ASM_CLOBBERS_4 ASM_CLOBBERS_5, "out4"
192 #define ASM_CLOBBERS_5 , "out5", "out6", "out7", \
193 /* Non-stacked integer registers, minus r8, r10, r15. */ \
194 "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \
195 "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \
196 "r28", "r29", "r30", "r31", \
197 /* Predicate registers. */ \
198 "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \
199 /* Non-rotating fp registers. */ \
200 "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
201 /* Branch registers. */ \
204 #endif /* not __ASSEMBLER__ */
206 #endif /* linux/ia64/sysdep.h */