091dfc9c7d3e0c06c42472c565c438a8d1001087
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / linux / m68k / sysdep.h
1 /* Copyright (C) 1996, 1997, 1998, 2000, 2003, 2004 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.
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 #include <sysdeps/unix/sysdep.h>
22 #include <sysdeps/m68k/sysdep.h>
23
24 /* Defines RTLD_PRIVATE_ERRNO.  */
25 #include <dl-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 #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
37
38 #ifdef __ASSEMBLER__
39
40 /* Linux uses a negative return value to indicate syscall errors, unlike
41    most Unices, which use the condition codes' carry flag.
42
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.  */
49
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
57
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
65
66 #undef PSEUDO_END
67 #define PSEUDO_END(name)                                                      \
68   SYSCALL_ERROR_HANDLER;                                                      \
69   END (name)
70
71 #undef PSEUDO_NOERRNO
72 #define PSEUDO_NOERRNO(name, syscall_name, args)                              \
73   .text;                                                                      \
74   ENTRY (name)                                                                \
75     DO_CALL (syscall_name, args)
76
77 #undef PSEUDO_END_NOERRNO
78 #define PSEUDO_END_NOERRNO(name)                                              \
79   END (name)
80
81 #define ret_NOERRNO rts
82
83 /* The function has to return the error code.  */
84 #undef  PSEUDO_ERRVAL
85 #define PSEUDO_ERRVAL(name, syscall_name, args) \
86   .text;                                                                      \
87   ENTRY (name)                                                                \
88     DO_CALL (syscall_name, args);                                             \
89     negl %d0
90
91 #undef  PSEUDO_END_ERRVAL
92 #define PSEUDO_END_ERRVAL(name) \
93   END (name)
94
95 #define ret_ERRVAL rts
96
97 #ifdef PIC
98 # if RTLD_PRIVATE_ERRNO
99 #  define SYSCALL_ERROR_HANDLER                                               \
100 SYSCALL_ERROR_LABEL:                                                          \
101     lea (rtld_errno, %pc), %a0;                                               \
102     neg.l %d0;                                                                \
103     move.l %d0, (%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 /* !RTLD_PRIVATE_ERRNO */
110 /* Store (- %d0) into errno through the GOT.  */
111 #  if defined _LIBC_REENTRANT
112 #   define SYSCALL_ERROR_HANDLER                                              \
113 SYSCALL_ERROR_LABEL:                                                          \
114     neg.l %d0;                                                                \
115     move.l %d0, -(%sp);                                                       \
116     jbsr __errno_location@PLTPC;                                              \
117     move.l (%sp)+, (%a0);                                                     \
118     move.l &-1, %d0;                                                          \
119     /* Copy return value to %a0 for syscalls that are declared to return      \
120        a pointer (e.g., mmap).  */                                            \
121     move.l %d0, %a0;                                                          \
122     rts;
123 #  else /* !_LIBC_REENTRANT */
124 #   define SYSCALL_ERROR_HANDLER                                              \
125 SYSCALL_ERROR_LABEL:                                                          \
126     move.l (errno@GOTPC, %pc), %a0;                                           \
127     neg.l %d0;                                                                \
128     move.l %d0, (%a0);                                                        \
129     move.l &-1, %d0;                                                          \
130     /* Copy return value to %a0 for syscalls that are declared to return      \
131        a pointer (e.g., mmap).  */                                            \
132     move.l %d0, %a0;                                                          \
133     rts;
134 #  endif /* _LIBC_REENTRANT */
135 # endif /* RTLD_PRIVATE_ERRNO */
136 #else
137 # define SYSCALL_ERROR_HANDLER  /* Nothing here; code in sysdep.S is used.  */
138 #endif /* PIC */
139
140 /* Linux takes system call arguments in registers:
141
142         syscall number  %d0          call-clobbered
143         arg 1           %d1          call-clobbered
144         arg 2           %d2          call-saved
145         arg 3           %d3          call-saved
146         arg 4           %d4          call-saved
147         arg 5           %d5          call-saved
148
149    The stack layout upon entering the function is:
150
151         20(%sp)         Arg# 5
152         16(%sp)         Arg# 4
153         12(%sp)         Arg# 3
154          8(%sp)         Arg# 2
155          4(%sp)         Arg# 1
156           (%sp)         Return address
157
158    (Of course a function with say 3 arguments does not have entries for
159    arguments 4 and 5.)
160
161    Separate move's are faster than movem, but need more space.  Since
162    speed is more important, we don't use movem.  Since %a0 and %a1 are
163    scratch registers, we can use them for saving as well.  */
164
165 #define DO_CALL(syscall_name, args)                                           \
166     move.l &SYS_ify(syscall_name), %d0;                                       \
167     DOARGS_##args                                                             \
168     trap &0;                                                                  \
169     UNDOARGS_##args
170
171 #define DOARGS_0        /* No arguments to frob.  */
172 #define UNDOARGS_0      /* No arguments to unfrob.  */
173 #define _DOARGS_0(n)    /* No arguments to frob.  */
174
175 #define DOARGS_1        _DOARGS_1 (4)
176 #define _DOARGS_1(n)    move.l n(%sp), %d1; _DOARGS_0 (n)
177 #define UNDOARGS_1      UNDOARGS_0
178
179 #define DOARGS_2        _DOARGS_2 (8)
180 #define _DOARGS_2(n)    move.l %d2, %a0; move.l n(%sp), %d2; _DOARGS_1 (n-4)
181 #define UNDOARGS_2      UNDOARGS_1; move.l %a0, %d2
182
183 #define DOARGS_3        _DOARGS_3 (12)
184 #define _DOARGS_3(n)    move.l %d3, %a1; move.l n(%sp), %d3; _DOARGS_2 (n-4)
185 #define UNDOARGS_3      UNDOARGS_2; move.l %a1, %d3
186
187 #define DOARGS_4        _DOARGS_4 (16)
188 #define _DOARGS_4(n)    move.l %d4, -(%sp); move.l n+4(%sp), %d4; _DOARGS_3 (n)
189 #define UNDOARGS_4      UNDOARGS_3; move.l (%sp)+, %d4
190
191 #define DOARGS_5        _DOARGS_5 (20)
192 #define _DOARGS_5(n)    move.l %d5, -(%sp); move.l n+4(%sp), %d5; _DOARGS_4 (n)
193 #define UNDOARGS_5      UNDOARGS_4; move.l (%sp)+, %d5
194
195
196 #define ret     rts
197 #if 0 /* Not used by Linux */
198 #define r0      %d0
199 #define r1      %d1
200 #define MOVE(x,y)       movel x , y
201 #endif
202
203 #else /* not __ASSEMBLER__ */
204
205 /* Define a macro which expands into the inline wrapper code for a system
206    call.  */
207 #undef INLINE_SYSCALL
208 #define INLINE_SYSCALL(name, nr, args...)                               \
209   ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args);    \
210      if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))\
211        {                                                                \
212          __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, ));          \
213          _sys_result = (unsigned int) -1;                               \
214        }                                                                \
215      (int) _sys_result; })
216
217 #undef INTERNAL_SYSCALL_DECL
218 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
219
220 /* Define a macro which expands inline into the wrapper code for a system
221    call.  This use is for internal calls that do not need to handle errors
222    normally.  It will never touch errno.  This returns just what the kernel
223    gave back.  */
224 #undef INTERNAL_SYSCALL
225 #define INTERNAL_SYSCALL(name, err, nr, args...)        \
226   ({ unsigned int _sys_result;                          \
227      {                                                  \
228        /* Load argument values in temporary variables
229           to perform side effects like function calls
230           before the call used registers are set.  */   \
231        LOAD_ARGS_##nr (args)                            \
232        LOAD_REGS_##nr                                   \
233        register int _d0 asm ("%d0") = __NR_##name;      \
234        asm volatile ("trap #0"                          \
235                      : "=d" (_d0)                       \
236                      : "0" (_d0) ASM_ARGS_##nr          \
237                      : "memory");                       \
238        _sys_result = _d0;                               \
239      }                                                  \
240      (int) _sys_result; })
241
242 #undef INTERNAL_SYSCALL_ERROR_P
243 #define INTERNAL_SYSCALL_ERROR_P(val, err)              \
244   ((unsigned int) (val) >= -4095U)
245
246 #undef INTERNAL_SYSCALL_ERRNO
247 #define INTERNAL_SYSCALL_ERRNO(val, err)        (-(val))
248
249 #define LOAD_ARGS_0()
250 #define LOAD_REGS_0
251 #define ASM_ARGS_0
252 #define LOAD_ARGS_1(a1)                         \
253   LOAD_ARGS_0 ()                                \
254   int __arg1 = (int) (a1);
255 #define LOAD_REGS_1                             \
256   register int _d1 asm ("d1") = __arg1;         \
257   LOAD_REGS_0
258 #define ASM_ARGS_1      ASM_ARGS_0, "d" (_d1)
259 #define LOAD_ARGS_2(a1, a2)                     \
260   LOAD_ARGS_1 (a1)                              \
261   int __arg2 = (int) (a2);
262 #define LOAD_REGS_2                             \
263   register int _d2 asm ("d2") = __arg2;         \
264   LOAD_REGS_1
265 #define ASM_ARGS_2      ASM_ARGS_1, "d" (_d2)
266 #define LOAD_ARGS_3(a1, a2, a3)                 \
267   LOAD_ARGS_2 (a1, a2)                          \
268   int __arg3 = (int) (a3);
269 #define LOAD_REGS_3                             \
270   register int _d3 asm ("d3") = __arg3;         \
271   LOAD_REGS_2
272 #define ASM_ARGS_3      ASM_ARGS_2, "d" (_d3)
273 #define LOAD_ARGS_4(a1, a2, a3, a4)             \
274   LOAD_ARGS_3 (a1, a2, a3)                      \
275   int __arg4 = (int) (a4);
276 #define LOAD_REGS_4                             \
277   register int _d4 asm ("d4") = __arg4;         \
278   LOAD_REGS_3
279 #define ASM_ARGS_4      ASM_ARGS_3, "d" (_d4)
280 #define LOAD_ARGS_5(a1, a2, a3, a4, a5)         \
281   LOAD_ARGS_4 (a1, a2, a3, a4)                  \
282   int __arg5 = (int) (a5);
283 #define LOAD_REGS_5                             \
284   register int _d5 asm ("d5") = __arg5;         \
285   LOAD_REGS_4
286 #define ASM_ARGS_5      ASM_ARGS_4, "d" (_d5)
287 #define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)     \
288   LOAD_ARGS_5 (a1, a2, a3, a4, a5)              \
289   int __arg6 = (int) (a6);
290 #define LOAD_REGS_6                             \
291   register int _a0 asm ("a0") = __arg6;         \
292   LOAD_REGS_5
293 #define ASM_ARGS_6      ASM_ARGS_5, "a" (_a0)
294
295 #endif /* not __ASSEMBLER__ */