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.
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.
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.
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. */
20 #ifndef _LINUX_I386_SYSDEP_H
21 #define _LINUX_I386_SYSDEP_H 1
23 /* There is some commonality. */
24 #include <sysdeps/unix/i386/sysdep.h>
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. */
32 # define SYS_ify(syscall_name) __NR_##syscall_name
34 # define SYS_ify(syscall_name) __NR_/**/syscall_name
40 /* Linux uses a negative return value to indicate syscall errors, unlike
41 most Unices, which use the condition codes' carry flag. */
43 #define PSEUDO(name, syscall_name, args) \
45 SYSCALL_ERROR_HANDLER \
47 DO_CALL (args, syscall_name); \
52 #define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
54 /* Store (- %eax) into errno through the GOT. */
55 #ifdef _LIBC_REENTRANT
56 #define SYSCALL_ERROR_HANDLER \
57 .type syscall_error,@function; \
63 addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx; \
65 movl errno@GOT(%ebx), %ecx; \
68 call __errno_location@PLT; \
75 #define SYSCALL_ERROR_HANDLER \
76 .type syscall_error,@function; \
81 addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ecx; \
83 movl errno@GOT(%ecx), %ecx; \
87 #endif /* _LIBC_REENTRANT */
90 /* Linux takes system call arguments in registers:
92 syscall number %eax call-clobbered
94 arg 2 %ecx call-clobbered
95 arg 3 %edx call-clobbered
99 The stack layout upon entering the function is:
106 (%esp) Return address
108 (Of course a function with say 3 arguments does not have entries for
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
114 2 * xchg is more expensive than pushl + movl + popl
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.
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).
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.
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. */
135 #define DO_CALL(args, syscall_name) \
138 movl $SYS_ify (syscall_name), %eax; \
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. */
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
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
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
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
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
184 #endif /* ASSEMBLER */
186 #endif /* linux/i386/sysdep.h */