]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/i386/sysdep.h
* sysdeps/i386/dl-machine.h (elf_machine_rel): Use +=, not =, to
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / i386 / sysdep.h
CommitLineData
d2f5be2a
UD
1/* Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
2This file is part of the GNU C Library.
3Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995.
4
5The GNU C Library is free software; you can redistribute it and/or
6modify it under the terms of the GNU Library General Public License as
7published by the Free Software Foundation; either version 2 of the
8License, or (at your option) any later version.
9
10The GNU C Library is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13Library General Public License for more details.
14
15You should have received a copy of the GNU Library General Public
16License along with the GNU C Library; see the file COPYING.LIB. If
17not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18Cambridge, 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 */