2002-10-16 Jakub Jelinek <jakub@redhat.com>
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / linux / i386 / sysdep.h
1 /* Copyright (C) 1992,93,95,96,97,98,99,2000,02 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #ifndef _LINUX_I386_SYSDEP_H
21 #define _LINUX_I386_SYSDEP_H 1
22
23 /* There is some commonality.  */
24 #include <sysdeps/unix/i386/sysdep.h>
25 #include <bp-sym.h>
26 #include <bp-asm.h>
27 #include <tls.h>
28
29
30 #ifdef IS_IN_rtld
31 # include <dl-sysdep.h>         /* Defines RTLD_PRIVATE_ERRNO.  */
32 #endif
33
34
35 /* For Linux we can use the system call table in the header file
36         /usr/include/asm/unistd.h
37    of the kernel.  But these symbols do not follow the SYS_* syntax
38    so we have to redefine the `SYS_ify' macro here.  */
39 #undef SYS_ify
40 #define SYS_ify(syscall_name)   __NR_##syscall_name
41
42 #ifdef __ASSEMBLER__
43
44 /* Linux uses a negative return value to indicate syscall errors,
45    unlike most Unices, which use the condition codes' carry flag.
46
47    Since version 2.1 the return value of a system call might be
48    negative even if the call succeeded.  E.g., the `lseek' system call
49    might return a large offset.  Therefore we must not anymore test
50    for < 0, but test for a real error by making sure the value in %eax
51    is a real error number.  Linus said he will make sure the no syscall
52    returns a value in -1 .. -4095 as a valid result so we can savely
53    test with -4095.  */
54
55 /* We don't want the label for the error handle to be global when we define
56    it here.  */
57 #ifdef PIC
58 # define SYSCALL_ERROR_LABEL 0f
59 #else
60 # define SYSCALL_ERROR_LABEL syscall_error
61 #endif
62
63 #undef  PSEUDO
64 #define PSEUDO(name, syscall_name, args)                                      \
65   .text;                                                                      \
66   ENTRY (name)                                                                \
67     DO_CALL (syscall_name, args);                                             \
68     cmpl $-4095, %eax;                                                        \
69     jae SYSCALL_ERROR_LABEL;                                                  \
70   L(pseudo_end):
71
72 #undef  PSEUDO_END
73 #define PSEUDO_END(name)                                                      \
74   SYSCALL_ERROR_HANDLER                                                       \
75   END (name)
76
77 #ifndef PIC
78 # define SYSCALL_ERROR_HANDLER  /* Nothing here; code in sysdep.S is used.  */
79 #else
80
81 # ifndef HAVE_HIDDEN
82 #  define SETUP_PIC_REG(reg) \
83   call 1f;                                                                    \
84   .subsection 1;                                                              \
85 1:movl (%esp), %e##reg;                                                       \
86   ret;                                                                        \
87   .previous
88 # else
89 #  define SETUP_PIC_REG(reg) \
90   .section .gnu.linkonce.t.__i686.get_pc_thunk.reg,"ax",@progbits;            \
91   .globl __i686.get_pc_thunk.reg;                                             \
92   .hidden __i686.get_pc_thunk.reg;                                            \
93   .type __i686.get_pc_thunk.reg,@function;                                    \
94 __i686.get_pc_thunk.reg:                                                      \
95   movl (%esp), %e##reg;                                                       \
96   ret;                                                                        \
97   .previous;                                                                  \
98   call __i686.get_pc_thunk.reg
99 # endif
100
101 # if RTLD_PRIVATE_ERRNO
102 #  define SYSCALL_ERROR_HANDLER                                               \
103 0:SETUP_PIC_REG(cx);                                                          \
104   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                          \
105   xorl %edx, %edx;                                                            \
106   subl %eax, %edx;                                                            \
107   movl %edx, errno@GOTOFF(%ecx);                                              \
108   orl $-1, %eax;                                                              \
109   jmp L(pseudo_end);
110
111 # elif defined _LIBC_REENTRANT
112
113 #  if USE___THREAD
114 #   define SYSCALL_ERROR_HANDLER                                              \
115 0:SETUP_PIC_REG (cx);                                                         \
116   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                          \
117   movl __libc_errno@GOTNTPOFF(%ecx), %ecx;                                    \
118   xorl %edx, %edx;                                                            \
119   subl %eax, %edx;                                                            \
120   movl %edx, %gs:0(%ecx);                                                     \
121   orl $-1, %eax;                                                              \
122   jmp L(pseudo_end);
123 #  else
124 #   define SYSCALL_ERROR_HANDLER                                              \
125 0:pushl %ebx;                                                                 \
126   SETUP_PIC_REG (bx);                                                         \
127   addl $_GLOBAL_OFFSET_TABLE_, %ebx;                                          \
128   xorl %edx, %edx;                                                            \
129   subl %eax, %edx;                                                            \
130   pushl %edx;                                                                 \
131   PUSH_ERRNO_LOCATION_RETURN;                                                 \
132   call BP_SYM (__errno_location)@PLT;                                         \
133   POP_ERRNO_LOCATION_RETURN;                                                  \
134   popl %ecx;                                                                  \
135   popl %ebx;                                                                  \
136   movl %ecx, (%eax);                                                          \
137   orl $-1, %eax;                                                              \
138   jmp L(pseudo_end);
139 /* A quick note: it is assumed that the call to `__errno_location' does
140    not modify the stack!  */
141 #  endif
142 # else
143 /* Store (- %eax) into errno through the GOT.  */
144 #  define SYSCALL_ERROR_HANDLER                                               \
145 0:SETUP_PIC_REG(cx);                                                  \
146   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                          \
147   xorl %edx, %edx;                                                            \
148   subl %eax, %edx;                                                            \
149   movl errno@GOT(%ecx), %ecx;                                                 \
150   movl %edx, (%ecx);                                                          \
151   orl $-1, %eax;                                                              \
152   jmp L(pseudo_end);
153 # endif /* _LIBC_REENTRANT */
154 #endif  /* PIC */
155
156 /* Linux takes system call arguments in registers:
157
158         syscall number  %eax         call-clobbered
159         arg 1           %ebx         call-saved
160         arg 2           %ecx         call-clobbered
161         arg 3           %edx         call-clobbered
162         arg 4           %esi         call-saved
163         arg 5           %edi         call-saved
164
165    The stack layout upon entering the function is:
166
167         20(%esp)        Arg# 5
168         16(%esp)        Arg# 4
169         12(%esp)        Arg# 3
170          8(%esp)        Arg# 2
171          4(%esp)        Arg# 1
172           (%esp)        Return address
173
174    (Of course a function with say 3 arguments does not have entries for
175    arguments 4 and 5.)
176
177    The following code tries hard to be optimal.  A general assumption
178    (which is true according to the data books I have) is that
179
180         2 * xchg        is more expensive than  pushl + movl + popl
181
182    Beside this a neat trick is used.  The calling conventions for Linux
183    tell that among the registers used for parameters %ecx and %edx need
184    not be saved.  Beside this we may clobber this registers even when
185    they are not used for parameter passing.
186
187    As a result one can see below that we save the content of the %ebx
188    register in the %edx register when we have less than 3 arguments
189    (2 * movl is less expensive than pushl + popl).
190
191    Second unlike for the other registers we don't save the content of
192    %ecx and %edx when we have more than 1 and 2 registers resp.
193
194    The code below might look a bit long but we have to take care for
195    the pipelined processors (i586).  Here the `pushl' and `popl'
196    instructions are marked as NP (not pairable) but the exception is
197    two consecutive of these instruction.  This gives no penalty on
198    other processors though.  */
199
200 #undef  DO_CALL
201 #define DO_CALL(syscall_name, args)                                           \
202     PUSHARGS_##args                                                           \
203     DOARGS_##args                                                             \
204     movl $SYS_ify (syscall_name), %eax;                                       \
205     int $0x80                                                                 \
206     POPARGS_##args
207
208 #define PUSHARGS_0      /* No arguments to push.  */
209 #define DOARGS_0        /* No arguments to frob.  */
210 #define POPARGS_0       /* No arguments to pop.  */
211 #define _PUSHARGS_0     /* No arguments to push.  */
212 #define _DOARGS_0(n)    /* No arguments to frob.  */
213 #define _POPARGS_0      /* No arguments to pop.  */
214
215 #define PUSHARGS_1      movl %ebx, %edx; PUSHARGS_0
216 #define DOARGS_1        _DOARGS_1 (4)
217 #define POPARGS_1       POPARGS_0; movl %edx, %ebx
218 #define _PUSHARGS_1     pushl %ebx; _PUSHARGS_0
219 #define _DOARGS_1(n)    movl n(%esp), %ebx; _DOARGS_0(n-4)
220 #define _POPARGS_1      _POPARGS_0; popl %ebx
221
222 #define PUSHARGS_2      PUSHARGS_1
223 #define DOARGS_2        _DOARGS_2 (8)
224 #define POPARGS_2       POPARGS_1
225 #define _PUSHARGS_2     _PUSHARGS_1
226 #define _DOARGS_2(n)    movl n(%esp), %ecx; _DOARGS_1 (n-4)
227 #define _POPARGS_2      _POPARGS_1
228
229 #define PUSHARGS_3      _PUSHARGS_2
230 #define DOARGS_3        _DOARGS_3 (16)
231 #define POPARGS_3       _POPARGS_3
232 #define _PUSHARGS_3     _PUSHARGS_2
233 #define _DOARGS_3(n)    movl n(%esp), %edx; _DOARGS_2 (n-4)
234 #define _POPARGS_3      _POPARGS_2
235
236 #define PUSHARGS_4      _PUSHARGS_4
237 #define DOARGS_4        _DOARGS_4 (24)
238 #define POPARGS_4       _POPARGS_4
239 #define _PUSHARGS_4     pushl %esi; _PUSHARGS_3
240 #define _DOARGS_4(n)    movl n(%esp), %esi; _DOARGS_3 (n-4)
241 #define _POPARGS_4      _POPARGS_3; popl %esi
242
243 #define PUSHARGS_5      _PUSHARGS_5
244 #define DOARGS_5        _DOARGS_5 (32)
245 #define POPARGS_5       _POPARGS_5
246 #define _PUSHARGS_5     pushl %edi; _PUSHARGS_4
247 #define _DOARGS_5(n)    movl n(%esp), %edi; _DOARGS_4 (n-4)
248 #define _POPARGS_5      _POPARGS_4; popl %edi
249
250 #else   /* !__ASSEMBLER__ */
251
252 /* We need some help from the assembler to generate optimal code.  We
253    define some macros here which later will be used.  */
254 asm (".L__X'%ebx = 1\n\t"
255      ".L__X'%ecx = 2\n\t"
256      ".L__X'%edx = 2\n\t"
257      ".L__X'%eax = 3\n\t"
258      ".L__X'%esi = 3\n\t"
259      ".L__X'%edi = 3\n\t"
260      ".L__X'%ebp = 3\n\t"
261      ".L__X'%esp = 3\n\t"
262      ".macro bpushl name reg\n\t"
263      ".if 1 - \\name\n\t"
264      ".if 2 - \\name\n\t"
265      "pushl %ebx\n\t"
266      ".else\n\t"
267      "xchgl \\reg, %ebx\n\t"
268      ".endif\n\t"
269      ".endif\n\t"
270      ".endm\n\t"
271      ".macro bpopl name reg\n\t"
272      ".if 1 - \\name\n\t"
273      ".if 2 - \\name\n\t"
274      "popl %ebx\n\t"
275      ".else\n\t"
276      "xchgl \\reg, %ebx\n\t"
277      ".endif\n\t"
278      ".endif\n\t"
279      ".endm\n\t"
280      ".macro bmovl name reg\n\t"
281      ".if 1 - \\name\n\t"
282      ".if 2 - \\name\n\t"
283      "movl \\reg, %ebx\n\t"
284      ".endif\n\t"
285      ".endif\n\t"
286      ".endm\n\t");
287
288 /* Define a macro which expands inline into the wrapper code for a system
289    call.  */
290 #undef INLINE_SYSCALL
291 #define INLINE_SYSCALL(name, nr, args...) \
292   ({                                                                          \
293     unsigned int resultvar = INTERNAL_SYSCALL (name, nr, args);               \
294     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar), 0))           \
295       {                                                                       \
296         __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar));                     \
297         resultvar = 0xffffffff;                                               \
298       }                                                                       \
299     (int) resultvar; })
300
301 /* Define a macro which expands inline into the wrapper code for a system
302    call.  This use is for internal calls that do not need to handle errors
303    normally.  It will never touch errno.  This returns just what the kernel
304    gave back.  */
305 #undef INTERNAL_SYSCALL
306 #define INTERNAL_SYSCALL(name, nr, args...) \
307   ({                                                                          \
308     unsigned int resultvar;                                                   \
309     asm volatile (                                                            \
310     LOADARGS_##nr                                                             \
311     "movl %1, %%eax\n\t"                                                      \
312     "int $0x80\n\t"                                                           \
313     RESTOREARGS_##nr                                                          \
314     : "=a" (resultvar)                                                        \
315     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                  \
316     (int) resultvar; })
317
318 #undef INTERNAL_SYSCALL_ERROR_P
319 #define INTERNAL_SYSCALL_ERROR_P(val)   ((unsigned int) (val) >= 0xfffff001u)
320
321 #undef INTERNAL_SYSCALL_ERRNO
322 #define INTERNAL_SYSCALL_ERRNO(val)     (-(val))
323
324 #define LOADARGS_0
325 #define LOADARGS_1 \
326     "bpushl .L__X'%k2, %k2\n\t"                                               \
327     "bmovl .L__X'%k2, %k2\n\t"
328 #define LOADARGS_2      LOADARGS_1
329 #define LOADARGS_3      LOADARGS_1
330 #define LOADARGS_4      LOADARGS_1
331 #define LOADARGS_5      LOADARGS_1
332
333 #define RESTOREARGS_0
334 #define RESTOREARGS_1 \
335     "bpopl .L__X'%k2, %k2\n\t"
336 #define RESTOREARGS_2   RESTOREARGS_1
337 #define RESTOREARGS_3   RESTOREARGS_1
338 #define RESTOREARGS_4   RESTOREARGS_1
339 #define RESTOREARGS_5   RESTOREARGS_1
340
341 #define ASMFMT_0()
342 #define ASMFMT_1(arg1) \
343         , "acdSD" (arg1)
344 #define ASMFMT_2(arg1, arg2) \
345         , "adCD" (arg1), "c" (arg2)
346 #define ASMFMT_3(arg1, arg2, arg3) \
347         , "aCD" (arg1), "c" (arg2), "d" (arg3)
348 #define ASMFMT_4(arg1, arg2, arg3, arg4) \
349         , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
350 #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
351         , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
352
353 #endif  /* __ASSEMBLER__ */
354
355 #endif /* linux/i386/sysdep.h */