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