update from main archive 960919
[platform/upstream/linaro-glibc.git] / sysdeps / unix / sysv / linux / i386 / sysdep.h
1 /* Copyright (C) 1992, 93, 95, 96 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, 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 Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, 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
26 /* For Linux we can use the system call table in the header file
27         /usr/include/asm/unistd.h
28    of the kernel.  But these symbols do not follow the SYS_* syntax
29    so we have to redefine the `SYS_ify' macro here.  */
30 #undef SYS_ify
31 #ifdef __STDC__
32 # define SYS_ify(syscall_name)  __NR_##syscall_name
33 #else
34 # define SYS_ify(syscall_name)  __NR_/**/syscall_name
35 #endif
36
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 #undef  PSEUDO
43 #define PSEUDO(name, syscall_name, args)                                      \
44   .text;                                                                      \
45   SYSCALL_ERROR_HANDLER                                                       \
46   ENTRY (name)                                                                \
47     DO_CALL (args, syscall_name);                                             \
48     testl %eax, %eax;                                                         \
49     jl syscall_error;
50
51 #ifndef PIC
52 #define SYSCALL_ERROR_HANDLER   /* Nothing here; code in sysdep.S is used.  */
53 #else
54 /* Store (- %eax) into errno through the GOT.  */
55 #ifdef _LIBC_REENTRANT
56 #define SYSCALL_ERROR_HANDLER                                                 \
57   .type syscall_error,@function;                                              \
58 syscall_error:                                                                \
59   pushl %ebx;                                                                 \
60   call 0f;                                                                    \
61 0:popl %ebx;                                                                  \
62   xorl %edx, %edx;                                                            \
63   addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx;                                   \
64   subl %eax, %edx;                                                            \
65   movl errno@GOT(%ebx), %ecx;                                                 \
66   movl %edx, (%ecx);                                                          \
67   pushl %edx;                                                                 \
68   call __errno_location@PLT;                                                  \
69   popl %ecx;                                                                  \
70   popl %ebx;                                                                  \
71   movl %ecx, (%eax);                                                          \
72   movl $-1, %eax;                                                             \
73   ret;
74 #else
75 #define SYSCALL_ERROR_HANDLER                                                 \
76   .type syscall_error,@function;                                              \
77 syscall_error:                                                                \
78   call 0f;                                                                    \
79 0:popl %ecx;                                                                  \
80   xorl %edx, %edx;                                                            \
81   addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ecx;                                   \
82   subl %eax, %edx;                                                            \
83   movl errno@GOT(%ecx), %ecx;                                                 \
84   movl %edx, (%ecx);                                                          \
85   movl $-1, %eax;                                                             \
86   ret;
87 #endif  /* _LIBC_REENTRANT */
88 #endif  /* PIC */
89
90 /* Linux takes system call arguments in registers:
91
92         syscall number  %eax         call-clobbered
93         arg 1           %ebx         call-saved
94         arg 2           %ecx         call-clobbered
95         arg 3           %edx         call-clobbered
96         arg 4           %esi         call-saved
97         arg 5           %edi         call-saved
98
99    The stack layout upon entering the function is:
100
101         20(%esp)        Arg# 5
102         16(%esp)        Arg# 4
103         12(%esp)        Arg# 3
104          8(%esp)        Arg# 2
105          4(%esp)        Arg# 1
106           (%esp)        Return address
107
108    (Of course a function with say 3 arguments does not have entries for
109    arguments 4 and 5.)
110
111    The following code tries hard to be optimal.  A general assuption
112    (which is true according to the data books I have) is that
113
114         2 * xchg        is more expensive than  pushl + movl + popl
115
116    Beside this a neat trick is used.  The calling conventions for Linux
117    tell that among the registers used for parameters %ecx and %edx need
118    not be saved.  Beside this we may clobber this registers even when
119    they are not used for parameter passing.
120
121    As a result one can see below that we save the content of the %ebx
122    register in the %edx register when we have less than 3 arguments
123    (2 * movl is less expensive than pushl + popl).
124
125    Second unlike for the other registers we don't save the content of
126    %ecx and %edx when we have than 1 and 2 registers resp.
127
128    The code below might look a bit long but we have to take care for
129    the pipelined processors (i586 and up).  Here the `pushl' and `popl'
130    instructions are marked as NP (not pairable) but the exception is
131    two consecutive of these instruction.  This gives no penalty on
132    i386 and i486 processors though.  */
133
134 #undef  DO_CALL
135 #define DO_CALL(args, syscall_name)                                           \
136     PUSHARGS_##args                                                           \
137     DOARGS_##args                                                             \
138     movl $SYS_ify (syscall_name), %eax;                                       \
139     int $0x80                                                                 \
140     POPARGS_##args
141
142 #define PUSHARGS_0      /* No arguments to push.  */
143 #define DOARGS_0        /* No arguments to frob.  */
144 #define POPARGS_0       /* No arguments to pop.  */
145 #define _PUSHARGS_0     /* No arguments to push.  */
146 #define _DOARGS_0(n)    /* No arguments to frob.  */
147 #define _POPARGS_0      /* No arguments to pop.  */
148
149 #define PUSHARGS_1      movl %ebx, %edx; PUSHARGS_0
150 #define DOARGS_1        _DOARGS_1 (4)
151 #define POPARGS_1       POPARGS_0; movl %edx, %ebx
152 #define _PUSHARGS_1     pushl %ebx; _PUSHARGS_0
153 #define _DOARGS_1(n)    movl n(%esp), %ebx; _DOARGS_0(n-4)
154 #define _POPARGS_1      _POPARGS_0; popl %ebx
155
156 #define PUSHARGS_2      PUSHARGS_1
157 #define DOARGS_2        _DOARGS_2 (8)
158 #define POPARGS_2       POPARGS_1
159 #define _PUSHARGS_2     _PUSHARGS_1
160 #define _DOARGS_2(n)    movl n(%esp), %ecx; _DOARGS_1 (n-4)
161 #define _POPARGS_2      _POPARGS_1
162
163 #define PUSHARGS_3      _PUSHARGS_2
164 #define DOARGS_3        _DOARGS_3 (16)
165 #define POPARGS_3       _POPARGS_3
166 #define _PUSHARGS_3     _PUSHARGS_2
167 #define _DOARGS_3(n)    movl n(%esp), %edx; _DOARGS_2 (n-4)
168 #define _POPARGS_3      _POPARGS_2
169
170 #define PUSHARGS_4      _PUSHARGS_4
171 #define DOARGS_4        _DOARGS_4 (24)
172 #define POPARGS_4       _POPARGS_4
173 #define _PUSHARGS_4     pushl %esi; _PUSHARGS_3
174 #define _DOARGS_4(n)    movl n(%esp), %esi; _DOARGS_3 (n-4)
175 #define _POPARGS_4      _POPARGS_3; popl %esi
176
177 #define PUSHARGS_5      _PUSHARGS_5
178 #define DOARGS_5        _DOARGS_5 (32)
179 #define POPARGS_5       _POPARGS_5
180 #define _PUSHARGS_5     pushl %edi; _PUSHARGS_4
181 #define _DOARGS_5(n)    movl n(%esp), %edi; _DOARGS_4 (n-4)
182 #define _POPARGS_5      _POPARGS_4; popl %edi
183
184 #endif  /* ASSEMBLER */
185
186 #endif /* linux/i386/sysdep.h */