]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/i386/sysdep.h
Update.
[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
UD
36
37#ifdef ASSEMBLER
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. */
d2f5be2a
UD
49#undef PSEUDO
50#define PSEUDO(name, syscall_name, args) \
51 .text; \
d2f5be2a 52 ENTRY (name) \
c14e4c32 53 DO_CALL (args, syscall_name); \
b5791037 54 cmpl $-4095, %eax; \
ae828bc6
UD
55 jae syscall_error; \
56 L(pseudo_end):
d2f5be2a 57
6ed0492f
UD
58#undef PSEUDO_END
59#define PSEUDO_END(name) \
60 SYSCALL_ERROR_HANDLER \
61 END (name)
62
edf5b2d7 63#ifndef PIC
03a75825
RM
64#define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
65#else
66/* Store (- %eax) into errno through the GOT. */
edf5b2d7 67#ifdef _LIBC_REENTRANT
03a75825 68#define SYSCALL_ERROR_HANDLER \
714a562f 69 .type syscall_error,@function; \
edf5b2d7
UD
70syscall_error: \
71 pushl %ebx; \
72 call 0f; \
730:popl %ebx; \
74 xorl %edx, %edx; \
75 addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx; \
76 subl %eax, %edx; \
edf5b2d7
UD
77 pushl %edx; \
78 call __errno_location@PLT; \
79 popl %ecx; \
80 popl %ebx; \
81 movl %ecx, (%eax); \
82 movl $-1, %eax; \
ae828bc6 83 jmp L(pseudo_end); \
714a562f 84 .size syscall_error,.-syscall_error;
c4029823 85/* A quick note: it is assumed that the call to `__errno_location' does
cccda09f 86 not modify the stack! */
edf5b2d7
UD
87#else
88#define SYSCALL_ERROR_HANDLER \
714a562f 89 .type syscall_error,@function; \
03a75825
RM
90syscall_error: \
91 call 0f; \
920:popl %ecx; \
edf5b2d7 93 xorl %edx, %edx; \
03a75825 94 addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ecx; \
edf5b2d7 95 subl %eax, %edx; \
03a75825 96 movl errno@GOT(%ecx), %ecx; \
edf5b2d7 97 movl %edx, (%ecx); \
03a75825 98 movl $-1, %eax; \
ae828bc6 99 jmp L(pseudo_end); \
714a562f 100 .size syscall_error,.-syscall_error;
edf5b2d7
UD
101#endif /* _LIBC_REENTRANT */
102#endif /* PIC */
03a75825 103
d2f5be2a
UD
104/* Linux takes system call arguments in registers:
105
106 syscall number %eax call-clobbered
107 arg 1 %ebx call-saved
108 arg 2 %ecx call-clobbered
109 arg 3 %edx call-clobbered
110 arg 4 %esi call-saved
111 arg 5 %edi call-saved
112
113 The stack layout upon entering the function is:
114
115 20(%esp) Arg# 5
116 16(%esp) Arg# 4
117 12(%esp) Arg# 3
118 8(%esp) Arg# 2
119 4(%esp) Arg# 1
120 (%esp) Return address
121
122 (Of course a function with say 3 arguments does not have entries for
123 arguments 4 and 5.)
124
6ed0492f 125 The following code tries hard to be optimal. A general assumption
03a75825 126 (which is true according to the data books I have) is that
d2f5be2a
UD
127
128 2 * xchg is more expensive than pushl + movl + popl
129
130 Beside this a neat trick is used. The calling conventions for Linux
131 tell that among the registers used for parameters %ecx and %edx need
132 not be saved. Beside this we may clobber this registers even when
133 they are not used for parameter passing.
134
135 As a result one can see below that we save the content of the %ebx
136 register in the %edx register when we have less than 3 arguments
137 (2 * movl is less expensive than pushl + popl).
138
139 Second unlike for the other registers we don't save the content of
6ed0492f 140 %ecx and %edx when we have more than 1 and 2 registers resp.
8f5ca04b
RM
141
142 The code below might look a bit long but we have to take care for
143 the pipelined processors (i586 and up). Here the `pushl' and `popl'
144 instructions are marked as NP (not pairable) but the exception is
145 two consecutive of these instruction. This gives no penalty on
146 i386 and i486 processors though. */
d2f5be2a
UD
147
148#undef DO_CALL
c14e4c32 149#define DO_CALL(args, syscall_name) \
8f5ca04b 150 PUSHARGS_##args \
d2f5be2a 151 DOARGS_##args \
c14e4c32 152 movl $SYS_ify (syscall_name), %eax; \
8f5ca04b
RM
153 int $0x80 \
154 POPARGS_##args
d2f5be2a 155
8f5ca04b 156#define PUSHARGS_0 /* No arguments to push. */
d2f5be2a 157#define DOARGS_0 /* No arguments to frob. */
8f5ca04b
RM
158#define POPARGS_0 /* No arguments to pop. */
159#define _PUSHARGS_0 /* No arguments to push. */
160#define _DOARGS_0(n) /* No arguments to frob. */
161#define _POPARGS_0 /* No arguments to pop. */
162
163#define PUSHARGS_1 movl %ebx, %edx; PUSHARGS_0
164#define DOARGS_1 _DOARGS_1 (4)
165#define POPARGS_1 POPARGS_0; movl %edx, %ebx
166#define _PUSHARGS_1 pushl %ebx; _PUSHARGS_0
167#define _DOARGS_1(n) movl n(%esp), %ebx; _DOARGS_0(n-4)
168#define _POPARGS_1 _POPARGS_0; popl %ebx
169
170#define PUSHARGS_2 PUSHARGS_1
171#define DOARGS_2 _DOARGS_2 (8)
172#define POPARGS_2 POPARGS_1
173#define _PUSHARGS_2 _PUSHARGS_1
d2f5be2a 174#define _DOARGS_2(n) movl n(%esp), %ecx; _DOARGS_1 (n-4)
8f5ca04b 175#define _POPARGS_2 _POPARGS_1
d2f5be2a 176
8f5ca04b
RM
177#define PUSHARGS_3 _PUSHARGS_2
178#define DOARGS_3 _DOARGS_3 (16)
179#define POPARGS_3 _POPARGS_3
180#define _PUSHARGS_3 _PUSHARGS_2
d2f5be2a 181#define _DOARGS_3(n) movl n(%esp), %edx; _DOARGS_2 (n-4)
8f5ca04b
RM
182#define _POPARGS_3 _POPARGS_2
183
184#define PUSHARGS_4 _PUSHARGS_4
185#define DOARGS_4 _DOARGS_4 (24)
186#define POPARGS_4 _POPARGS_4
187#define _PUSHARGS_4 pushl %esi; _PUSHARGS_3
188#define _DOARGS_4(n) movl n(%esp), %esi; _DOARGS_3 (n-4)
189#define _POPARGS_4 _POPARGS_3; popl %esi
190
191#define PUSHARGS_5 _PUSHARGS_5
192#define DOARGS_5 _DOARGS_5 (32)
193#define POPARGS_5 _POPARGS_5
194#define _PUSHARGS_5 pushl %edi; _PUSHARGS_4
195#define _DOARGS_5(n) movl n(%esp), %edi; _DOARGS_4 (n-4)
196#define _POPARGS_5 _POPARGS_4; popl %edi
d2f5be2a
UD
197
198#endif /* ASSEMBLER */
ec4b0518
UD
199
200#endif /* linux/i386/sysdep.h */