Updated to fedora-glibc-20041005T0745
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / linux / i386 / sysdep.h
1 /* Copyright (C) 1992,1993,1995-2000,2002,2003,2004
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper, <drepper@gnu.org>, August 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 #ifndef _LINUX_I386_SYSDEP_H
22 #define _LINUX_I386_SYSDEP_H 1
23
24 /* There is some commonality.  */
25 #include <sysdeps/unix/i386/sysdep.h>
26 #include <bp-sym.h>
27 #include <bp-asm.h>
28 /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO.  */
29 #include <dl-sysdep.h>
30 #include <tls.h>
31
32
33 /* For Linux we can use the system call table in the header file
34         /usr/include/asm/unistd.h
35    of the kernel.  But these symbols do not follow the SYS_* syntax
36    so we have to redefine the `SYS_ify' macro here.  */
37 #undef SYS_ify
38 #define SYS_ify(syscall_name)   __NR_##syscall_name
39
40 #if defined USE_DL_SYSINFO \
41     && (!defined NOT_IN_libc || defined IS_IN_libpthread)
42 # define I386_USE_SYSENTER      1
43 #else
44 # undef I386_USE_SYSENTER
45 #endif
46
47 #ifdef __ASSEMBLER__
48
49 /* Linux uses a negative return value to indicate syscall errors,
50    unlike most Unices, which use the condition codes' carry flag.
51
52    Since version 2.1 the return value of a system call might be
53    negative even if the call succeeded.  E.g., the `lseek' system call
54    might return a large offset.  Therefore we must not anymore test
55    for < 0, but test for a real error by making sure the value in %eax
56    is a real error number.  Linus said he will make sure the no syscall
57    returns a value in -1 .. -4095 as a valid result so we can savely
58    test with -4095.  */
59
60 /* We don't want the label for the error handle to be global when we define
61    it here.  */
62 #ifdef PIC
63 # define SYSCALL_ERROR_LABEL 0f
64 #else
65 # define SYSCALL_ERROR_LABEL syscall_error
66 #endif
67
68 #undef  PSEUDO
69 #define PSEUDO(name, syscall_name, args)                                      \
70   .text;                                                                      \
71   ENTRY (name)                                                                \
72     DO_CALL (syscall_name, args);                                             \
73     cmpl $-4095, %eax;                                                        \
74     jae SYSCALL_ERROR_LABEL;                                                  \
75   L(pseudo_end):
76
77 #undef  PSEUDO_END
78 #define PSEUDO_END(name)                                                      \
79   SYSCALL_ERROR_HANDLER                                                       \
80   END (name)
81
82 #undef  PSEUDO_NOERRNO
83 #define PSEUDO_NOERRNO(name, syscall_name, args)                              \
84   .text;                                                                      \
85   ENTRY (name)                                                                \
86     DO_CALL (syscall_name, args)
87
88 #undef  PSEUDO_END_NOERRNO
89 #define PSEUDO_END_NOERRNO(name)                                              \
90   END (name)
91
92 #define ret_NOERRNO ret
93
94 /* The function has to return the error code.  */
95 #undef  PSEUDO_ERRVAL
96 #define PSEUDO_ERRVAL(name, syscall_name, args) \
97   .text;                                                                      \
98   ENTRY (name)                                                                \
99     DO_CALL (syscall_name, args);                                             \
100     negl %eax
101
102 #undef  PSEUDO_END_ERRVAL
103 #define PSEUDO_END_ERRVAL(name) \
104   END (name)
105
106 #define ret_ERRVAL ret
107
108 #ifndef PIC
109 # define SYSCALL_ERROR_HANDLER  /* Nothing here; code in sysdep.S is used.  */
110 #else
111
112 # ifndef HAVE_HIDDEN
113 #  define SETUP_PIC_REG(reg) \
114   call 1f;                                                                    \
115   .subsection 1;                                                              \
116 1:movl (%esp), %e##reg;                                                       \
117   ret;                                                                        \
118   .previous
119 # else
120 #  define SETUP_PIC_REG(reg) \
121   .section .gnu.linkonce.t.__i686.get_pc_thunk.reg,"ax",@progbits;            \
122   .globl __i686.get_pc_thunk.reg;                                             \
123   .hidden __i686.get_pc_thunk.reg;                                            \
124   .type __i686.get_pc_thunk.reg,@function;                                    \
125 __i686.get_pc_thunk.reg:                                                      \
126   movl (%esp), %e##reg;                                                       \
127   ret;                                                                        \
128   .size __i686.get_pc_thunk.reg, . - __i686.get_pc_thunk.reg;                 \
129   .previous;                                                                  \
130   call __i686.get_pc_thunk.reg
131 # endif
132
133 # if RTLD_PRIVATE_ERRNO
134 #  define SYSCALL_ERROR_HANDLER                                               \
135 0:SETUP_PIC_REG(cx);                                                          \
136   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                          \
137   xorl %edx, %edx;                                                            \
138   subl %eax, %edx;                                                            \
139   movl %edx, rtld_errno@GOTOFF(%ecx);                                         \
140   orl $-1, %eax;                                                              \
141   jmp L(pseudo_end);
142
143 # elif defined _LIBC_REENTRANT
144
145 #  if USE___THREAD
146 #   ifndef NOT_IN_libc
147 #    define SYSCALL_ERROR_ERRNO __libc_errno
148 #   else
149 #    define SYSCALL_ERROR_ERRNO errno
150 #   endif
151 #   define SYSCALL_ERROR_HANDLER                                              \
152 0:SETUP_PIC_REG (cx);                                                         \
153   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                          \
154   movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx;                             \
155   xorl %edx, %edx;                                                            \
156   subl %eax, %edx;                                                            \
157   movl %edx, %gs:0(%ecx);                                                     \
158   orl $-1, %eax;                                                              \
159   jmp L(pseudo_end);
160 #  else
161 #   define SYSCALL_ERROR_HANDLER                                              \
162 0:pushl %ebx;                                                                 \
163   SETUP_PIC_REG (bx);                                                         \
164   addl $_GLOBAL_OFFSET_TABLE_, %ebx;                                          \
165   xorl %edx, %edx;                                                            \
166   subl %eax, %edx;                                                            \
167   pushl %edx;                                                                 \
168   PUSH_ERRNO_LOCATION_RETURN;                                                 \
169   call BP_SYM (__errno_location)@PLT;                                         \
170   POP_ERRNO_LOCATION_RETURN;                                                  \
171   popl %ecx;                                                                  \
172   popl %ebx;                                                                  \
173   movl %ecx, (%eax);                                                          \
174   orl $-1, %eax;                                                              \
175   jmp L(pseudo_end);
176 /* A quick note: it is assumed that the call to `__errno_location' does
177    not modify the stack!  */
178 #  endif
179 # else
180 /* Store (- %eax) into errno through the GOT.  */
181 #  define SYSCALL_ERROR_HANDLER                                               \
182 0:SETUP_PIC_REG(cx);                                                          \
183   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                          \
184   xorl %edx, %edx;                                                            \
185   subl %eax, %edx;                                                            \
186   movl errno@GOT(%ecx), %ecx;                                                 \
187   movl %edx, (%ecx);                                                          \
188   orl $-1, %eax;                                                              \
189   jmp L(pseudo_end);
190 # endif /* _LIBC_REENTRANT */
191 #endif  /* PIC */
192
193
194 /* The original calling convention for system calls on Linux/i386 is
195    to use int $0x80.  */
196 #ifdef I386_USE_SYSENTER
197 # ifdef SHARED
198 #  define ENTER_KERNEL call *%gs:SYSINFO_OFFSET
199 # else
200 #  define ENTER_KERNEL call *_dl_sysinfo
201 # endif
202 #else
203 # define ENTER_KERNEL int $0x80
204 #endif
205
206 /* Linux takes system call arguments in registers:
207
208         syscall number  %eax         call-clobbered
209         arg 1           %ebx         call-saved
210         arg 2           %ecx         call-clobbered
211         arg 3           %edx         call-clobbered
212         arg 4           %esi         call-saved
213         arg 5           %edi         call-saved
214
215    The stack layout upon entering the function is:
216
217         20(%esp)        Arg# 5
218         16(%esp)        Arg# 4
219         12(%esp)        Arg# 3
220          8(%esp)        Arg# 2
221          4(%esp)        Arg# 1
222           (%esp)        Return address
223
224    (Of course a function with say 3 arguments does not have entries for
225    arguments 4 and 5.)
226
227    The following code tries hard to be optimal.  A general assumption
228    (which is true according to the data books I have) is that
229
230         2 * xchg        is more expensive than  pushl + movl + popl
231
232    Beside this a neat trick is used.  The calling conventions for Linux
233    tell that among the registers used for parameters %ecx and %edx need
234    not be saved.  Beside this we may clobber this registers even when
235    they are not used for parameter passing.
236
237    As a result one can see below that we save the content of the %ebx
238    register in the %edx register when we have less than 3 arguments
239    (2 * movl is less expensive than pushl + popl).
240
241    Second unlike for the other registers we don't save the content of
242    %ecx and %edx when we have more than 1 and 2 registers resp.
243
244    The code below might look a bit long but we have to take care for
245    the pipelined processors (i586).  Here the `pushl' and `popl'
246    instructions are marked as NP (not pairable) but the exception is
247    two consecutive of these instruction.  This gives no penalty on
248    other processors though.  */
249
250 #undef  DO_CALL
251 #define DO_CALL(syscall_name, args)                                           \
252     PUSHARGS_##args                                                           \
253     DOARGS_##args                                                             \
254     movl $SYS_ify (syscall_name), %eax;                                       \
255     ENTER_KERNEL                                                              \
256     POPARGS_##args
257
258 #define PUSHARGS_0      /* No arguments to push.  */
259 #define DOARGS_0        /* No arguments to frob.  */
260 #define POPARGS_0       /* No arguments to pop.  */
261 #define _PUSHARGS_0     /* No arguments to push.  */
262 #define _DOARGS_0(n)    /* No arguments to frob.  */
263 #define _POPARGS_0      /* No arguments to pop.  */
264
265 #define PUSHARGS_1      movl %ebx, %edx; L(SAVEBX1): PUSHARGS_0
266 #define DOARGS_1        _DOARGS_1 (4)
267 #define POPARGS_1       POPARGS_0; movl %edx, %ebx; L(RESTBX1):
268 #define _PUSHARGS_1     pushl %ebx; L(PUSHBX1): _PUSHARGS_0
269 #define _DOARGS_1(n)    movl n(%esp), %ebx; _DOARGS_0(n-4)
270 #define _POPARGS_1      _POPARGS_0; popl %ebx; L(POPBX1):
271
272 #define PUSHARGS_2      PUSHARGS_1
273 #define DOARGS_2        _DOARGS_2 (8)
274 #define POPARGS_2       POPARGS_1
275 #define _PUSHARGS_2     _PUSHARGS_1
276 #define _DOARGS_2(n)    movl n(%esp), %ecx; _DOARGS_1 (n-4)
277 #define _POPARGS_2      _POPARGS_1
278
279 #define PUSHARGS_3      _PUSHARGS_2
280 #define DOARGS_3        _DOARGS_3 (16)
281 #define POPARGS_3       _POPARGS_3
282 #define _PUSHARGS_3     _PUSHARGS_2
283 #define _DOARGS_3(n)    movl n(%esp), %edx; _DOARGS_2 (n-4)
284 #define _POPARGS_3      _POPARGS_2
285
286 #define PUSHARGS_4      _PUSHARGS_4
287 #define DOARGS_4        _DOARGS_4 (24)
288 #define POPARGS_4       _POPARGS_4
289 #define _PUSHARGS_4     pushl %esi; L(PUSHSI1): _PUSHARGS_3
290 #define _DOARGS_4(n)    movl n(%esp), %esi; _DOARGS_3 (n-4)
291 #define _POPARGS_4      _POPARGS_3; popl %esi; L(POPSI1):
292
293 #define PUSHARGS_5      _PUSHARGS_5
294 #define DOARGS_5        _DOARGS_5 (32)
295 #define POPARGS_5       _POPARGS_5
296 #define _PUSHARGS_5     pushl %edi; L(PUSHDI1): _PUSHARGS_4
297 #define _DOARGS_5(n)    movl n(%esp), %edi; _DOARGS_4 (n-4)
298 #define _POPARGS_5      _POPARGS_4; popl %edi; L(POPDI1):
299
300 #else   /* !__ASSEMBLER__ */
301
302 /* We need some help from the assembler to generate optimal code.  We
303    define some macros here which later will be used.  */
304 asm (".L__X'%ebx = 1\n\t"
305      ".L__X'%ecx = 2\n\t"
306      ".L__X'%edx = 2\n\t"
307      ".L__X'%eax = 3\n\t"
308      ".L__X'%esi = 3\n\t"
309      ".L__X'%edi = 3\n\t"
310      ".L__X'%ebp = 3\n\t"
311      ".L__X'%esp = 3\n\t"
312      ".macro bpushl name reg\n\t"
313      ".if 1 - \\name\n\t"
314      ".if 2 - \\name\n\t"
315      "error\n\t"
316      ".else\n\t"
317      "xchgl \\reg, %ebx\n\t"
318      ".endif\n\t"
319      ".endif\n\t"
320      ".endm\n\t"
321      ".macro bpopl name reg\n\t"
322      ".if 1 - \\name\n\t"
323      ".if 2 - \\name\n\t"
324      "error\n\t"
325      ".else\n\t"
326      "xchgl \\reg, %ebx\n\t"
327      ".endif\n\t"
328      ".endif\n\t"
329      ".endm\n\t");
330
331 /* Define a macro which expands inline into the wrapper code for a system
332    call.  */
333 #undef INLINE_SYSCALL
334 #define INLINE_SYSCALL(name, nr, args...) \
335   ({                                                                          \
336     unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);             \
337     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))         \
338       {                                                                       \
339         __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));                   \
340         resultvar = 0xffffffff;                                               \
341       }                                                                       \
342     (int) resultvar; })
343
344 /* Define a macro which expands inline into the wrapper code for a system
345    call.  This use is for internal calls that do not need to handle errors
346    normally.  It will never touch errno.  This returns just what the kernel
347    gave back.
348
349    The _NCS variant allows non-constant syscall numbers but it is not
350    possible to use more than four parameters.  */
351 #undef INTERNAL_SYSCALL
352 #ifdef I386_USE_SYSENTER
353 # ifdef SHARED
354 #  define INTERNAL_SYSCALL(name, err, nr, args...) \
355   ({                                                                          \
356     register unsigned int resultvar;                                          \
357     EXTRAVAR_##nr                                                             \
358     asm volatile (                                                            \
359     LOADARGS_##nr                                                             \
360     "movl %1, %%eax\n\t"                                                      \
361     "call *%%gs:%P2\n\t"                                                      \
362     RESTOREARGS_##nr                                                          \
363     : "=a" (resultvar)                                                        \
364     : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))                  \
365       ASMFMT_##nr(args) : "memory", "cc");                                    \
366     (int) resultvar; })
367 #  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
368   ({                                                                          \
369     register unsigned int resultvar;                                          \
370     EXTRAVAR_##nr                                                             \
371     asm volatile (                                                            \
372     LOADARGS_##nr                                                             \
373     "call *%%gs:%P2\n\t"                                                      \
374     RESTOREARGS_##nr                                                          \
375     : "=a" (resultvar)                                                        \
376     : "0" (name), "i" (offsetof (tcbhead_t, sysinfo))                         \
377       ASMFMT_##nr(args) : "memory", "cc");                                    \
378     (int) resultvar; })
379 # else
380 #  define INTERNAL_SYSCALL(name, err, nr, args...) \
381   ({                                                                          \
382     register unsigned int resultvar;                                          \
383     EXTRAVAR_##nr                                                             \
384     asm volatile (                                                            \
385     LOADARGS_##nr                                                             \
386     "movl %1, %%eax\n\t"                                                      \
387     "call *_dl_sysinfo\n\t"                                                   \
388     RESTOREARGS_##nr                                                          \
389     : "=a" (resultvar)                                                        \
390     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                  \
391     (int) resultvar; })
392 #  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
393   ({                                                                          \
394     register unsigned int resultvar;                                          \
395     EXTRAVAR_##nr                                                             \
396     asm volatile (                                                            \
397     LOADARGS_##nr                                                             \
398     "call *_dl_sysinfo\n\t"                                                   \
399     RESTOREARGS_##nr                                                          \
400     : "=a" (resultvar)                                                        \
401     : "0" (name) ASMFMT_##nr(args) : "memory", "cc");                         \
402     (int) resultvar; })
403 # endif
404 #else
405 # define INTERNAL_SYSCALL(name, err, nr, args...) \
406   ({                                                                          \
407     register unsigned int resultvar;                                          \
408     EXTRAVAR_##nr                                                             \
409     asm volatile (                                                            \
410     LOADARGS_##nr                                                             \
411     "movl %1, %%eax\n\t"                                                      \
412     "int $0x80\n\t"                                                           \
413     RESTOREARGS_##nr                                                          \
414     : "=a" (resultvar)                                                        \
415     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                  \
416     (int) resultvar; })
417 # define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
418   ({                                                                          \
419     register unsigned int resultvar;                                          \
420     EXTRAVAR_##nr                                                             \
421     asm volatile (                                                            \
422     LOADARGS_##nr                                                             \
423     "int $0x80\n\t"                                                           \
424     RESTOREARGS_##nr                                                          \
425     : "=a" (resultvar)                                                        \
426     : "0" (name) ASMFMT_##nr(args) : "memory", "cc");                         \
427     (int) resultvar; })
428 #endif
429
430 #undef INTERNAL_SYSCALL_DECL
431 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
432
433 #undef INTERNAL_SYSCALL_ERROR_P
434 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
435   ((unsigned int) (val) >= 0xfffff001u)
436
437 #undef INTERNAL_SYSCALL_ERRNO
438 #define INTERNAL_SYSCALL_ERRNO(val, err)        (-(val))
439
440 #define LOADARGS_0
441 #ifdef __PIC__
442 # if defined I386_USE_SYSENTER
443 #  define LOADARGS_1 \
444     "bpushl .L__X'%k3, %k3\n\t"
445 #  define LOADARGS_5 \
446     "movl %%ebx, %4\n\t"                                                      \
447     "movl %3, %%ebx\n\t"
448 # else
449 #  define LOADARGS_1 \
450     "bpushl .L__X'%k2, %k2\n\t"
451 #  define LOADARGS_5 \
452     "movl %%ebx, %3\n\t"                                                      \
453     "movl %2, %%ebx\n\t"
454 # endif
455 # define LOADARGS_2     LOADARGS_1
456 # define LOADARGS_3 \
457     "xchgl %%ebx, %%edi\n\t"
458 # define LOADARGS_4     LOADARGS_3
459 #else
460 # define LOADARGS_1
461 # define LOADARGS_2
462 # define LOADARGS_3
463 # define LOADARGS_4
464 # define LOADARGS_5
465 #endif
466
467 #define RESTOREARGS_0
468 #ifdef __PIC__
469 # if defined I386_USE_SYSENTER && defined SHARED
470 #  define RESTOREARGS_1 \
471     "bpopl .L__X'%k3, %k3\n\t"
472 #  define RESTOREARGS_5 \
473     "movl %4, %%ebx"
474 # else
475 #  define RESTOREARGS_1 \
476     "bpopl .L__X'%k2, %k2\n\t"
477 #  define RESTOREARGS_5 \
478     "movl %3, %%ebx"
479 # endif
480 # define RESTOREARGS_2  RESTOREARGS_1
481 # define RESTOREARGS_3 \
482     "xchgl %%edi, %%ebx\n\t"
483 # define RESTOREARGS_4  RESTOREARGS_3
484 #else
485 # define RESTOREARGS_1
486 # define RESTOREARGS_2
487 # define RESTOREARGS_3
488 # define RESTOREARGS_4
489 # define RESTOREARGS_5
490 #endif
491
492 #define ASMFMT_0()
493 #ifdef __PIC__
494 # define ASMFMT_1(arg1) \
495         , "cd" (arg1)
496 # define ASMFMT_2(arg1, arg2) \
497         , "d" (arg1), "c" (arg2)
498 # define ASMFMT_3(arg1, arg2, arg3) \
499         , "D" (arg1), "c" (arg2), "d" (arg3)
500 # define ASMFMT_4(arg1, arg2, arg3, arg4) \
501         , "D" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
502 # define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
503         , "0" (arg1), "m" (_xv), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
504 #else
505 # define ASMFMT_1(arg1) \
506         , "b" (arg1)
507 # define ASMFMT_2(arg1, arg2) \
508         , "b" (arg1), "c" (arg2)
509 # define ASMFMT_3(arg1, arg2, arg3) \
510         , "b" (arg1), "c" (arg2), "d" (arg3)
511 # define ASMFMT_4(arg1, arg2, arg3, arg4) \
512         , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
513 # define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
514         , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
515 #endif
516
517 #define EXTRAVAR_0
518 #define EXTRAVAR_1
519 #define EXTRAVAR_2
520 #define EXTRAVAR_3
521 #define EXTRAVAR_4
522 #ifdef __PIC__
523 # define EXTRAVAR_5 int _xv;
524 #else
525 # define EXTRAVAR_5
526 #endif
527
528 #endif  /* __ASSEMBLER__ */
529
530 #endif /* linux/i386/sysdep.h */