]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/i386/sysdep.h
(LDFLAGS): Remove.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / i386 / sysdep.h
CommitLineData
ae828bc6 1/* Copyright (C) 1992, 93, 95, 96, 97, 98 Free Software Foundation, Inc.
bfbc5754
UD
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 not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
d2f5be2a 19
ec4b0518
UD
20#ifndef _LINUX_I386_SYSDEP_H
21#define _LINUX_I386_SYSDEP_H 1
22
d2f5be2a
UD
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
6ed0492f 31#define SYS_ify(syscall_name) __NR_##syscall_name
d2f5be2a 32
8fb3e007
UD
33/* ELF-like local names start with `.L'. */
34#undef L
35#define L(name) .L##name
d2f5be2a 36
66715f83 37#ifdef __ASSEMBLER__
d2f5be2a 38
cccda09f
UD
39/* Linux uses a negative return value to indicate syscall errors,
40 unlike most Unices, which use the condition codes' carry flag.
41
42 Since version 2.1 the return value of a system call might be
43 negative even if the call succeeded. E.g., the `lseek' system call
44 might return a large offset. Therefore we must not anymore test
45 for < 0, but test for a real error by making sure the value in %eax
b5791037
UD
46 is a real error number. Linus said he will make sure the no syscall
47 returns a value in -1 .. -4095 as a valid result so we can savely
48 test with -4095. */
c0fb8a56
UD
49
50/* We don't want the label for the error handle to be global when we define
51 it here. */
52#ifdef PIC
53# define SYSCALL_ERROR_LABEL 0f
54#else
55# define SYSCALL_ERROR_LABEL syscall_error
56#endif
57
d2f5be2a
UD
58#undef PSEUDO
59#define PSEUDO(name, syscall_name, args) \
60 .text; \
d2f5be2a 61 ENTRY (name) \
c14e4c32 62 DO_CALL (args, syscall_name); \
b5791037 63 cmpl $-4095, %eax; \
c0fb8a56 64 jae SYSCALL_ERROR_LABEL; \
ae828bc6 65 L(pseudo_end):
d2f5be2a 66
6ed0492f
UD
67#undef PSEUDO_END
68#define PSEUDO_END(name) \
69 SYSCALL_ERROR_HANDLER \
70 END (name)
71
edf5b2d7 72#ifndef PIC
03a75825
RM
73#define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
74#else
75/* Store (- %eax) into errno through the GOT. */
edf5b2d7 76#ifdef _LIBC_REENTRANT
03a75825 77#define SYSCALL_ERROR_HANDLER \
c0fb8a56
UD
780:pushl %ebx; \
79 call 1f; \
801:popl %ebx; \
edf5b2d7 81 xorl %edx, %edx; \
c0fb8a56 82 addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx; \
edf5b2d7 83 subl %eax, %edx; \
edf5b2d7
UD
84 pushl %edx; \
85 call __errno_location@PLT; \
86 popl %ecx; \
87 popl %ebx; \
88 movl %ecx, (%eax); \
89 movl $-1, %eax; \
c0fb8a56 90 jmp L(pseudo_end);
c4029823 91/* A quick note: it is assumed that the call to `__errno_location' does
cccda09f 92 not modify the stack! */
edf5b2d7
UD
93#else
94#define SYSCALL_ERROR_HANDLER \
c0fb8a56
UD
950:call 1f; \
961:popl %ecx; \
edf5b2d7 97 xorl %edx, %edx; \
c0fb8a56 98 addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx; \
edf5b2d7 99 subl %eax, %edx; \
03a75825 100 movl errno@GOT(%ecx), %ecx; \
edf5b2d7 101 movl %edx, (%ecx); \
03a75825 102 movl $-1, %eax; \
c0fb8a56 103 jmp L(pseudo_end);
edf5b2d7
UD
104#endif /* _LIBC_REENTRANT */
105#endif /* PIC */
03a75825 106
d2f5be2a
UD
107/* Linux takes system call arguments in registers:
108
109 syscall number %eax call-clobbered
110 arg 1 %ebx call-saved
111 arg 2 %ecx call-clobbered
112 arg 3 %edx call-clobbered
113 arg 4 %esi call-saved
114 arg 5 %edi call-saved
115
116 The stack layout upon entering the function is:
117
118 20(%esp) Arg# 5
119 16(%esp) Arg# 4
120 12(%esp) Arg# 3
121 8(%esp) Arg# 2
122 4(%esp) Arg# 1
123 (%esp) Return address
124
125 (Of course a function with say 3 arguments does not have entries for
126 arguments 4 and 5.)
127
6ed0492f 128 The following code tries hard to be optimal. A general assumption
03a75825 129 (which is true according to the data books I have) is that
d2f5be2a
UD
130
131 2 * xchg is more expensive than pushl + movl + popl
132
133 Beside this a neat trick is used. The calling conventions for Linux
134 tell that among the registers used for parameters %ecx and %edx need
135 not be saved. Beside this we may clobber this registers even when
136 they are not used for parameter passing.
137
138 As a result one can see below that we save the content of the %ebx
139 register in the %edx register when we have less than 3 arguments
140 (2 * movl is less expensive than pushl + popl).
141
142 Second unlike for the other registers we don't save the content of
6ed0492f 143 %ecx and %edx when we have more than 1 and 2 registers resp.
8f5ca04b
RM
144
145 The code below might look a bit long but we have to take care for
63bda0c1 146 the pipelined processors (i586). Here the `pushl' and `popl'
8f5ca04b
RM
147 instructions are marked as NP (not pairable) but the exception is
148 two consecutive of these instruction. This gives no penalty on
63bda0c1 149 other processors though. */
d2f5be2a
UD
150
151#undef DO_CALL
c14e4c32 152#define DO_CALL(args, syscall_name) \
8f5ca04b 153 PUSHARGS_##args \
d2f5be2a 154 DOARGS_##args \
c14e4c32 155 movl $SYS_ify (syscall_name), %eax; \
8f5ca04b
RM
156 int $0x80 \
157 POPARGS_##args
d2f5be2a 158
8f5ca04b 159#define PUSHARGS_0 /* No arguments to push. */
d2f5be2a 160#define DOARGS_0 /* No arguments to frob. */
8f5ca04b
RM
161#define POPARGS_0 /* No arguments to pop. */
162#define _PUSHARGS_0 /* No arguments to push. */
163#define _DOARGS_0(n) /* No arguments to frob. */
164#define _POPARGS_0 /* No arguments to pop. */
165
166#define PUSHARGS_1 movl %ebx, %edx; PUSHARGS_0
167#define DOARGS_1 _DOARGS_1 (4)
168#define POPARGS_1 POPARGS_0; movl %edx, %ebx
169#define _PUSHARGS_1 pushl %ebx; _PUSHARGS_0
170#define _DOARGS_1(n) movl n(%esp), %ebx; _DOARGS_0(n-4)
171#define _POPARGS_1 _POPARGS_0; popl %ebx
172
173#define PUSHARGS_2 PUSHARGS_1
174#define DOARGS_2 _DOARGS_2 (8)
175#define POPARGS_2 POPARGS_1
176#define _PUSHARGS_2 _PUSHARGS_1
d2f5be2a 177#define _DOARGS_2(n) movl n(%esp), %ecx; _DOARGS_1 (n-4)
8f5ca04b 178#define _POPARGS_2 _POPARGS_1
d2f5be2a 179
8f5ca04b
RM
180#define PUSHARGS_3 _PUSHARGS_2
181#define DOARGS_3 _DOARGS_3 (16)
182#define POPARGS_3 _POPARGS_3
183#define _PUSHARGS_3 _PUSHARGS_2
d2f5be2a 184#define _DOARGS_3(n) movl n(%esp), %edx; _DOARGS_2 (n-4)
8f5ca04b
RM
185#define _POPARGS_3 _POPARGS_2
186
187#define PUSHARGS_4 _PUSHARGS_4
188#define DOARGS_4 _DOARGS_4 (24)
189#define POPARGS_4 _POPARGS_4
190#define _PUSHARGS_4 pushl %esi; _PUSHARGS_3
191#define _DOARGS_4(n) movl n(%esp), %esi; _DOARGS_3 (n-4)
192#define _POPARGS_4 _POPARGS_3; popl %esi
193
194#define PUSHARGS_5 _PUSHARGS_5
195#define DOARGS_5 _DOARGS_5 (32)
196#define POPARGS_5 _POPARGS_5
197#define _PUSHARGS_5 pushl %edi; _PUSHARGS_4
198#define _DOARGS_5(n) movl n(%esp), %edi; _DOARGS_4 (n-4)
199#define _POPARGS_5 _POPARGS_4; popl %edi
d2f5be2a 200
66715f83 201#endif /* __ASSEMBLER__ */
ec4b0518
UD
202
203#endif /* linux/i386/sysdep.h */