Define ret_NOERRNO.
[glibc.git] / sysdeps / unix / sysv / linux / m68k / sysdep.h
blobaabd46fe0d122ff0d50956c4da1b564b6c70b7f2
1 /* Copyright (C) 1996, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Written by Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>,
4 December 1995.
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 #include <sysdeps/unix/sysdep.h>
22 #include <sysdeps/m68k/sysdep.h>
24 /* Defines RTLD_PRIVATE_ERRNO. */
25 #include <dl-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. */
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
38 #ifdef __ASSEMBLER__
40 /* Linux uses a negative return value to indicate syscall errors, unlike
41 most Unices, which use the condition codes' carry flag.
43 Since version 2.1 the return value of a system call might be negative
44 even if the call succeeded. E.g., the `lseek' system call might return
45 a large offset. Therefore we must not anymore test for < 0, but test
46 for a real error by making sure the value in %d0 is a real error
47 number. Linus said he will make sure the no syscall returns a value
48 in -1 .. -4095 as a valid result so we can savely test with -4095. */
50 /* We don't want the label for the error handler to be visible in the symbol
51 table when we define it here. */
52 #ifdef PIC
53 #define SYSCALL_ERROR_LABEL .Lsyscall_error
54 #else
55 #define SYSCALL_ERROR_LABEL __syscall_error
56 #endif
58 #undef PSEUDO
59 #define PSEUDO(name, syscall_name, args) \
60 .text; \
61 ENTRY (name) \
62 DO_CALL (syscall_name, args); \
63 cmp.l &-4095, %d0; \
64 jcc SYSCALL_ERROR_LABEL
66 #undef PSEUDO_END
67 #define PSEUDO_END(name) \
68 SYSCALL_ERROR_HANDLER; \
69 END (name)
71 #undef PSEUDO_NOERRNO
72 #define PSEUDO_NOERRNO(name, syscall_name, args) \
73 .text; \
74 ENTRY (name) \
75 DO_CALL (syscall_name, args)
77 #undef PSEUDO_END_NOERRNO
78 #define PSEUDO_END_NOERRNO(name) \
79 END (name)
81 #define ret_NOERRNO ret
83 #ifdef PIC
84 # if RTLD_PRIVATE_ERRNO
85 # define SYSCALL_ERROR_HANDLER \
86 SYSCALL_ERROR_LABEL: \
87 lea (errno, %pc), %a0; \
88 neg.l %d0; \
89 move.l %d0, (%a0); \
90 move.l &-1, %d0; \
91 /* Copy return value to %a0 for syscalls that are declared to return \
92 a pointer (e.g., mmap). */ \
93 move.l %d0, %a0; \
94 rts;
95 # else /* !RTLD_PRIVATE_ERRNO */
96 /* Store (- %d0) into errno through the GOT. */
97 # if defined _LIBC_REENTRANT
98 # define SYSCALL_ERROR_HANDLER \
99 SYSCALL_ERROR_LABEL: \
100 neg.l %d0; \
101 move.l %d0, -(%sp); \
102 jbsr __errno_location@PLTPC; \
103 move.l (%sp)+, (%a0); \
104 move.l &-1, %d0; \
105 /* Copy return value to %a0 for syscalls that are declared to return \
106 a pointer (e.g., mmap). */ \
107 move.l %d0, %a0; \
108 rts;
109 # else /* !_LIBC_REENTRANT */
110 # define SYSCALL_ERROR_HANDLER \
111 SYSCALL_ERROR_LABEL: \
112 move.l (errno@GOTPC, %pc), %a0; \
113 neg.l %d0; \
114 move.l %d0, (%a0); \
115 move.l &-1, %d0; \
116 /* Copy return value to %a0 for syscalls that are declared to return \
117 a pointer (e.g., mmap). */ \
118 move.l %d0, %a0; \
119 rts;
120 # endif /* _LIBC_REENTRANT */
121 # endif /* RTLD_PRIVATE_ERRNO */
122 #else
123 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
124 #endif /* PIC */
126 /* Linux takes system call arguments in registers:
128 syscall number %d0 call-clobbered
129 arg 1 %d1 call-clobbered
130 arg 2 %d2 call-saved
131 arg 3 %d3 call-saved
132 arg 4 %d4 call-saved
133 arg 5 %d5 call-saved
135 The stack layout upon entering the function is:
137 20(%sp) Arg# 5
138 16(%sp) Arg# 4
139 12(%sp) Arg# 3
140 8(%sp) Arg# 2
141 4(%sp) Arg# 1
142 (%sp) Return address
144 (Of course a function with say 3 arguments does not have entries for
145 arguments 4 and 5.)
147 Separate move's are faster than movem, but need more space. Since
148 speed is more important, we don't use movem. Since %a0 and %a1 are
149 scratch registers, we can use them for saving as well. */
151 #define DO_CALL(syscall_name, args) \
152 move.l &SYS_ify(syscall_name), %d0; \
153 DOARGS_##args \
154 trap &0; \
155 UNDOARGS_##args
157 #define DOARGS_0 /* No arguments to frob. */
158 #define UNDOARGS_0 /* No arguments to unfrob. */
159 #define _DOARGS_0(n) /* No arguments to frob. */
161 #define DOARGS_1 _DOARGS_1 (4)
162 #define _DOARGS_1(n) move.l n(%sp), %d1; _DOARGS_0 (n)
163 #define UNDOARGS_1 UNDOARGS_0
165 #define DOARGS_2 _DOARGS_2 (8)
166 #define _DOARGS_2(n) move.l %d2, %a0; move.l n(%sp), %d2; _DOARGS_1 (n-4)
167 #define UNDOARGS_2 UNDOARGS_1; move.l %a0, %d2
169 #define DOARGS_3 _DOARGS_3 (12)
170 #define _DOARGS_3(n) move.l %d3, %a1; move.l n(%sp), %d3; _DOARGS_2 (n-4)
171 #define UNDOARGS_3 UNDOARGS_2; move.l %a1, %d3
173 #define DOARGS_4 _DOARGS_4 (16)
174 #define _DOARGS_4(n) move.l %d4, -(%sp); move.l n+4(%sp), %d4; _DOARGS_3 (n)
175 #define UNDOARGS_4 UNDOARGS_3; move.l (%sp)+, %d4
177 #define DOARGS_5 _DOARGS_5 (20)
178 #define _DOARGS_5(n) move.l %d5, -(%sp); move.l n+4(%sp), %d5; _DOARGS_4 (n)
179 #define UNDOARGS_5 UNDOARGS_4; move.l (%sp)+, %d5
182 #define ret rts
183 #if 0 /* Not used by Linux */
184 #define r0 %d0
185 #define r1 %d1
186 #define MOVE(x,y) movel x , y
187 #endif
189 #else /* not __ASSEMBLER__ */
191 /* Define a macro which expands into the inline wrapper code for a system
192 call. */
193 #undef INLINE_SYSCALL
194 #define INLINE_SYSCALL(name, nr, args...) \
195 ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args); \
196 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))\
198 __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \
199 _sys_result = (unsigned int) -1; \
201 (int) _sys_result; })
203 #undef INTERNAL_SYSCALL_DECL
204 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
206 /* Define a macro which expands inline into the wrapper code for a system
207 call. This use is for internal calls that do not need to handle errors
208 normally. It will never touch errno. This returns just what the kernel
209 gave back. */
210 #undef INTERNAL_SYSCALL
211 #define INTERNAL_SYSCALL(name, err, nr, args...) \
212 ({ unsigned int _sys_result; \
214 LOAD_ARGS_##nr (args) \
215 register int _d0 asm ("%d0") = __NR_##name; \
216 asm volatile ("trap #0" \
217 : "=d" (_d0) \
218 : "0" (_d0) ASM_ARGS_##nr \
219 : "memory"); \
220 _sys_result = _d0; \
222 (int) _sys_result; })
224 #undef INTERNAL_SYSCALL_ERROR_P
225 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
226 ((unsigned int) (val) >= -4095U)
228 #undef INTERNAL_SYSCALL_ERRNO
229 #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
231 #define LOAD_ARGS_0()
232 #define ASM_ARGS_0
233 #define LOAD_ARGS_1(a1) \
234 register int _d1 asm ("d1") = (int) (a1); \
235 LOAD_ARGS_0 ()
236 #define ASM_ARGS_1 ASM_ARGS_0, "d" (_d1)
237 #define LOAD_ARGS_2(a1, a2) \
238 register int _d2 asm ("d2") = (int) (a2); \
239 LOAD_ARGS_1 (a1)
240 #define ASM_ARGS_2 ASM_ARGS_1, "d" (_d2)
241 #define LOAD_ARGS_3(a1, a2, a3) \
242 register int _d3 asm ("d3") = (int) (a3); \
243 LOAD_ARGS_2 (a1, a2)
244 #define ASM_ARGS_3 ASM_ARGS_2, "d" (_d3)
245 #define LOAD_ARGS_4(a1, a2, a3, a4) \
246 register int _d4 asm ("d4") = (int) (a4); \
247 LOAD_ARGS_3 (a1, a2, a3)
248 #define ASM_ARGS_4 ASM_ARGS_3, "d" (_d4)
249 #define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
250 register int _d5 asm ("d5") = (int) (a5); \
251 LOAD_ARGS_4 (a1, a2, a3, a4)
252 #define ASM_ARGS_5 ASM_ARGS_4, "d" (_d5)
253 #define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \
254 register int _a0 asm ("a0") = (int) (a6); \
255 LOAD_ARGS_5 (a1, a2, a3, a4, a5)
256 #define ASM_ARGS_6 ASM_ARGS_5, "a" (_a0)
258 #endif /* not __ASSEMBLER__ */