]>
Commit | Line | Data |
---|---|---|
d2f5be2a UD |
1 | /* Copyright (C) 1992, 1993, 1995 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 | /* In the Linux/ELF world, C symbols are asm symbols. */ | |
21 | #define NO_UNDERSCORES | |
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 | #ifdef __STDC__ | |
32 | # define SYS_ify(syscall_name) __NR_##syscall_name | |
33 | #else | |
34 | # define SYS_ify(syscall_name) __NR_/**/syscall_name | |
35 | #endif | |
36 | ||
37 | ||
38 | #ifdef ASSEMBLER | |
39 | ||
40 | /* Linux uses a negative return value to indicate syscall errors, unlike | |
41 | most Unices, which use the condition codes' carry flag. */ | |
42 | #undef PSEUDO | |
43 | #define PSEUDO(name, syscall_name, args) \ | |
44 | .text; \ | |
45 | .globl syscall_error; \ | |
46 | ENTRY (name) \ | |
47 | movl $SYS_ify (syscall_name), %eax; \ | |
48 | DO_CALL (args); \ | |
49 | testl %eax, %eax; \ | |
50 | jl JUMPTARGET (syscall_error) | |
51 | ||
52 | /* We define our own ENTRY macro because the alignment should be 16 for ELF. */ | |
53 | #undef ENTRY | |
54 | #define ENTRY(name) \ | |
55 | ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (name); \ | |
56 | ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME (name), @function) \ | |
57 | .align 16; \ | |
58 | C_LABEL (name) | |
59 | ||
60 | /* Linux takes system call arguments in registers: | |
61 | ||
62 | syscall number %eax call-clobbered | |
63 | arg 1 %ebx call-saved | |
64 | arg 2 %ecx call-clobbered | |
65 | arg 3 %edx call-clobbered | |
66 | arg 4 %esi call-saved | |
67 | arg 5 %edi call-saved | |
68 | ||
69 | The stack layout upon entering the function is: | |
70 | ||
71 | 20(%esp) Arg# 5 | |
72 | 16(%esp) Arg# 4 | |
73 | 12(%esp) Arg# 3 | |
74 | 8(%esp) Arg# 2 | |
75 | 4(%esp) Arg# 1 | |
76 | (%esp) Return address | |
77 | ||
78 | (Of course a function with say 3 arguments does not have entries for | |
79 | arguments 4 and 5.) | |
80 | ||
81 | The following code tries hard to be optimal. A general assuption | |
82 | (which is true accoriding to the data books I have) is that | |
83 | ||
84 | 2 * xchg is more expensive than pushl + movl + popl | |
85 | ||
86 | Beside this a neat trick is used. The calling conventions for Linux | |
87 | tell that among the registers used for parameters %ecx and %edx need | |
88 | not be saved. Beside this we may clobber this registers even when | |
89 | they are not used for parameter passing. | |
90 | ||
91 | As a result one can see below that we save the content of the %ebx | |
92 | register in the %edx register when we have less than 3 arguments | |
93 | (2 * movl is less expensive than pushl + popl). | |
94 | ||
95 | Second unlike for the other registers we don't save the content of | |
96 | %ecx and %edx when we have than 1 and 2 registers resp. */ | |
97 | ||
98 | #undef DO_CALL | |
99 | #define DO_CALL(args) \ | |
100 | DOARGS_##args \ | |
101 | int $0x80; \ | |
102 | UNDOARGS_##args | |
103 | ||
104 | #define DOARGS_0 /* No arguments to frob. */ | |
105 | #define UNDOARGS_0 /* No arguments to unfrob. */ | |
106 | #define _DOARGS_0(n) /* No arguments to frob. */ | |
107 | #define _UNDOARGS_0 /* No arguments to unfrob. */ | |
108 | ||
109 | #define DOARGS_1 movl %ebx, %edx; movl 4(%esp), %ebx; DOARGS_0 | |
110 | #define UNDOARGS_1 UNDOARGS_0; movl %edx, %ebx | |
111 | #define _DOARGS_1(n) pushl %ebx; movl n+4(%esp), %ebx; _DOARGS_0 (n) | |
112 | #define _UNDOARGS_1 _UNDOARGS_0; popl %ebx | |
113 | ||
114 | #define DOARGS_2 movl 8(%esp), %ecx; DOARGS_1 | |
115 | #define UNDOARGS_2 UNDOARGS_1 | |
116 | #define _DOARGS_2(n) movl n(%esp), %ecx; _DOARGS_1 (n-4) | |
117 | #define _UNDOARGS_2 _UNDOARGS_1 | |
118 | ||
119 | #define DOARGS_3 _DOARGS_3 (12) | |
120 | #define UNDOARGS_3 _UNDOARGS_3 | |
121 | #define _DOARGS_3(n) movl n(%esp), %edx; _DOARGS_2 (n-4) | |
122 | #define _UNDOARGS_3 _UNDOARGS_2 | |
123 | ||
124 | #define DOARGS_4 _DOARGS_4 (16) | |
125 | #define UNDOARGS_4 _UNDOARGS_4 | |
126 | #define _DOARGS_4(n) pushl %esi; movl n+4(%esp), %esi; _DOARGS_3 (n) | |
127 | #define _UNDOARGS_4 _UNDOARGS_3; popl %esi | |
128 | ||
129 | #define DOARGS_5 _DOARGS_5 (20) | |
130 | #define UNDOARGS_5 _UNDOARGS_5 | |
131 | #define _DOARGS_5(n) pushl %edi; movl n+4(%esp), %edi; _DOARGS_4 (n) | |
132 | #define _UNDOARGS_5 _UNDOARGS_4; popl %edi | |
133 | ||
134 | ||
135 | #endif /* ASSEMBLER */ |