]>
Commit | Line | Data |
---|---|---|
a182affd | 1 | /* Copyright (C) 1992, 93, 95, 96 Free Software Foundation, Inc. |
d2f5be2a 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 | |
17 | not, write to the Free Software Foundation, Inc., 675 Mass Ave, | |
18 | Cambridge, MA 02139, USA. */ | |
19 | ||
d2f5be2a UD |
20 | /* There is some commonality. */ |
21 | #include <sysdeps/unix/i386/sysdep.h> | |
22 | ||
23 | /* For Linux we can use the system call table in the header file | |
24 | /usr/include/asm/unistd.h | |
25 | of the kernel. But these symbols do not follow the SYS_* syntax | |
26 | so we have to redefine the `SYS_ify' macro here. */ | |
27 | #undef SYS_ify | |
28 | #ifdef __STDC__ | |
29 | # define SYS_ify(syscall_name) __NR_##syscall_name | |
30 | #else | |
31 | # define SYS_ify(syscall_name) __NR_/**/syscall_name | |
32 | #endif | |
33 | ||
34 | ||
35 | #ifdef ASSEMBLER | |
36 | ||
37 | /* Linux uses a negative return value to indicate syscall errors, unlike | |
38 | most Unices, which use the condition codes' carry flag. */ | |
39 | #undef PSEUDO | |
40 | #define PSEUDO(name, syscall_name, args) \ | |
41 | .text; \ | |
03a75825 | 42 | SYSCALL_ERROR_HANDLER \ |
d2f5be2a | 43 | ENTRY (name) \ |
c14e4c32 | 44 | DO_CALL (args, syscall_name); \ |
d2f5be2a | 45 | testl %eax, %eax; \ |
03a75825 | 46 | jl syscall_error; |
d2f5be2a | 47 | |
03a75825 RM |
48 | #ifndef PIC |
49 | #define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ | |
50 | #else | |
51 | /* Store (- %eax) into errno through the GOT. */ | |
52 | #define SYSCALL_ERROR_HANDLER \ | |
53 | syscall_error: \ | |
54 | call 0f; \ | |
55 | 0:popl %ecx; \ | |
56 | negl %eax; \ | |
57 | addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ecx; \ | |
58 | movl errno@GOT(%ecx), %ecx; \ | |
59 | movl %eax, (%ecx); \ | |
60 | movl $-1, %eax; \ | |
c14e4c32 | 61 | ret; |
03a75825 RM |
62 | #endif |
63 | ||
d2f5be2a UD |
64 | /* Linux takes system call arguments in registers: |
65 | ||
66 | syscall number %eax call-clobbered | |
67 | arg 1 %ebx call-saved | |
68 | arg 2 %ecx call-clobbered | |
69 | arg 3 %edx call-clobbered | |
70 | arg 4 %esi call-saved | |
71 | arg 5 %edi call-saved | |
72 | ||
73 | The stack layout upon entering the function is: | |
74 | ||
75 | 20(%esp) Arg# 5 | |
76 | 16(%esp) Arg# 4 | |
77 | 12(%esp) Arg# 3 | |
78 | 8(%esp) Arg# 2 | |
79 | 4(%esp) Arg# 1 | |
80 | (%esp) Return address | |
81 | ||
82 | (Of course a function with say 3 arguments does not have entries for | |
83 | arguments 4 and 5.) | |
84 | ||
85 | The following code tries hard to be optimal. A general assuption | |
03a75825 | 86 | (which is true according to the data books I have) is that |
d2f5be2a UD |
87 | |
88 | 2 * xchg is more expensive than pushl + movl + popl | |
89 | ||
90 | Beside this a neat trick is used. The calling conventions for Linux | |
91 | tell that among the registers used for parameters %ecx and %edx need | |
92 | not be saved. Beside this we may clobber this registers even when | |
93 | they are not used for parameter passing. | |
94 | ||
95 | As a result one can see below that we save the content of the %ebx | |
96 | register in the %edx register when we have less than 3 arguments | |
97 | (2 * movl is less expensive than pushl + popl). | |
98 | ||
99 | Second unlike for the other registers we don't save the content of | |
8f5ca04b RM |
100 | %ecx and %edx when we have than 1 and 2 registers resp. |
101 | ||
102 | The code below might look a bit long but we have to take care for | |
103 | the pipelined processors (i586 and up). Here the `pushl' and `popl' | |
104 | instructions are marked as NP (not pairable) but the exception is | |
105 | two consecutive of these instruction. This gives no penalty on | |
106 | i386 and i486 processors though. */ | |
d2f5be2a UD |
107 | |
108 | #undef DO_CALL | |
c14e4c32 | 109 | #define DO_CALL(args, syscall_name) \ |
8f5ca04b | 110 | PUSHARGS_##args \ |
d2f5be2a | 111 | DOARGS_##args \ |
c14e4c32 | 112 | movl $SYS_ify (syscall_name), %eax; \ |
8f5ca04b RM |
113 | int $0x80 \ |
114 | POPARGS_##args | |
d2f5be2a | 115 | |
8f5ca04b | 116 | #define PUSHARGS_0 /* No arguments to push. */ |
d2f5be2a | 117 | #define DOARGS_0 /* No arguments to frob. */ |
8f5ca04b RM |
118 | #define POPARGS_0 /* No arguments to pop. */ |
119 | #define _PUSHARGS_0 /* No arguments to push. */ | |
120 | #define _DOARGS_0(n) /* No arguments to frob. */ | |
121 | #define _POPARGS_0 /* No arguments to pop. */ | |
122 | ||
123 | #define PUSHARGS_1 movl %ebx, %edx; PUSHARGS_0 | |
124 | #define DOARGS_1 _DOARGS_1 (4) | |
125 | #define POPARGS_1 POPARGS_0; movl %edx, %ebx | |
126 | #define _PUSHARGS_1 pushl %ebx; _PUSHARGS_0 | |
127 | #define _DOARGS_1(n) movl n(%esp), %ebx; _DOARGS_0(n-4) | |
128 | #define _POPARGS_1 _POPARGS_0; popl %ebx | |
129 | ||
130 | #define PUSHARGS_2 PUSHARGS_1 | |
131 | #define DOARGS_2 _DOARGS_2 (8) | |
132 | #define POPARGS_2 POPARGS_1 | |
133 | #define _PUSHARGS_2 _PUSHARGS_1 | |
d2f5be2a | 134 | #define _DOARGS_2(n) movl n(%esp), %ecx; _DOARGS_1 (n-4) |
8f5ca04b | 135 | #define _POPARGS_2 _POPARGS_1 |
d2f5be2a | 136 | |
8f5ca04b RM |
137 | #define PUSHARGS_3 _PUSHARGS_2 |
138 | #define DOARGS_3 _DOARGS_3 (16) | |
139 | #define POPARGS_3 _POPARGS_3 | |
140 | #define _PUSHARGS_3 _PUSHARGS_2 | |
d2f5be2a | 141 | #define _DOARGS_3(n) movl n(%esp), %edx; _DOARGS_2 (n-4) |
8f5ca04b RM |
142 | #define _POPARGS_3 _POPARGS_2 |
143 | ||
144 | #define PUSHARGS_4 _PUSHARGS_4 | |
145 | #define DOARGS_4 _DOARGS_4 (24) | |
146 | #define POPARGS_4 _POPARGS_4 | |
147 | #define _PUSHARGS_4 pushl %esi; _PUSHARGS_3 | |
148 | #define _DOARGS_4(n) movl n(%esp), %esi; _DOARGS_3 (n-4) | |
149 | #define _POPARGS_4 _POPARGS_3; popl %esi | |
150 | ||
151 | #define PUSHARGS_5 _PUSHARGS_5 | |
152 | #define DOARGS_5 _DOARGS_5 (32) | |
153 | #define POPARGS_5 _POPARGS_5 | |
154 | #define _PUSHARGS_5 pushl %edi; _PUSHARGS_4 | |
155 | #define _DOARGS_5(n) movl n(%esp), %edi; _DOARGS_4 (n-4) | |
156 | #define _POPARGS_5 _POPARGS_4; popl %edi | |
d2f5be2a UD |
157 | |
158 | #endif /* ASSEMBLER */ |