i386/bits/syscalls.h: more compact, but stack-hungry syscall code. disabled so far
[uclibc-ng.git] / libc / sysdeps / linux / i386 / bits / syscalls.h
blob0427d91cdad4c3480d10563aebc89b0f080c113e
1 #ifndef _BITS_SYSCALLS_H
2 #define _BITS_SYSCALLS_H
4 #ifndef _SYSCALL_H
5 # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
6 #endif
8 /*
9 * Some of the sneaky macros in the code were taken from
10 * glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h
13 #ifndef __ASSEMBLER__
15 #include <errno.h>
17 #define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
18 ({ \
19 register unsigned int resultvar; \
20 __asm__ __volatile__ ( \
21 LOADARGS_##nr \
22 "movl %1, %%eax\n\t" \
23 "int $0x80\n\t" \
24 RESTOREARGS_##nr \
25 : "=a" (resultvar) \
26 : "i" (name) ASMFMT_##nr(args) : "memory", "cc" \
27 ); \
28 (int) resultvar; \
32 #if 1 /* defined __PIC__ || defined __pic__ */
34 /* This code avoids pushing/popping ebx as much as possible.
35 * I think the main reason was that older GCCs had problems
36 * with proper saving/restoring of ebx if "b" constraint was used,
37 * which was breaking -fPIC code really badly.
38 * At least gcc 4.2.x seems to not need these tricks anymore,
39 * but this code is still useful because it often avoids
40 * using stack for saving ebx.
41 * Keeping it unconditionally enabled for now.
44 /* We need some help from the assembler to generate optimal code.
45 * We define some macros here which later will be used. */
47 __asm__ (
48 #ifdef __DOMULTI__
49 /* Protect against asm macro redefinition (happens in __DOMULTI__ mode).
50 * Unfortunately, it ends up visible in .o files. */
51 ".ifndef _BITS_SYSCALLS_ASM\n\t"
52 ".set _BITS_SYSCALLS_ASM,1\n\t"
53 #endif
54 ".L__X'%ebx = 1\n\t"
55 ".L__X'%ecx = 2\n\t"
56 ".L__X'%edx = 2\n\t"
57 ".L__X'%eax = 3\n\t"
58 ".L__X'%esi = 3\n\t"
59 ".L__X'%edi = 3\n\t"
60 ".L__X'%ebp = 3\n\t"
61 ".L__X'%esp = 3\n\t"
63 /* Loading param #1 (ebx) is done by loading it into
64 * another register, and then performing bpushl+bmovl,
65 * since we must preserve ebx */
67 ".macro bpushl name reg\n\t"
68 ".if 1 - \\name\n\t" /* if reg!=ebx... */
69 ".if 2 - \\name\n\t" /* if reg can't be clobbered... */
70 "pushl %ebx\n\t" /* save ebx on stack */
71 ".else\n\t"
72 "xchgl \\reg, %ebx\n\t" /* else save ebx in reg, and load reg to ebx */
73 ".endif\n\t"
74 ".endif\n\t"
75 ".endm\n\t"
77 ".macro bmovl name reg\n\t"
78 ".if 1 - \\name\n\t"
79 ".if 2 - \\name\n\t" /* if reg can't be clobbered... */
80 "movl \\reg, %ebx\n\t" /* load reg to ebx */
81 ".endif\n\t"
82 ".endif\n\t"
83 ".endm\n\t"
85 ".macro bpopl name reg\n\t"
86 ".if 1 - \\name\n\t"
87 ".if 2 - \\name\n\t" /* if reg can't be clobbered... */
88 "popl %ebx\n\t" /* restore ebx from stack */
89 ".else\n\t"
90 "xchgl \\reg, %ebx\n\t" /* else restore ebx from reg */
91 ".endif\n\t"
92 ".endif\n\t"
93 ".endm\n\t"
95 #ifdef __DOMULTI__
96 ".endif\n\t" /* _BITS_SYSCALLS_ASM */
97 #endif
100 #define LOADARGS_0
101 #define LOADARGS_1 "bpushl .L__X'%k2, %k2\n\t" "bmovl .L__X'%k2, %k2\n\t"
102 #define LOADARGS_2 LOADARGS_1
103 #define LOADARGS_3 LOADARGS_1
104 #define LOADARGS_4 LOADARGS_1
105 #define LOADARGS_5 LOADARGS_1
106 #define LOADARGS_6 LOADARGS_1 "push %%ebp\n\t" "movl %7, %%ebp\n\t"
108 #define RESTOREARGS_0
109 #define RESTOREARGS_1 "bpopl .L__X'%k2, %k2\n\t"
110 #define RESTOREARGS_2 RESTOREARGS_1
111 #define RESTOREARGS_3 RESTOREARGS_1
112 #define RESTOREARGS_4 RESTOREARGS_1
113 #define RESTOREARGS_5 RESTOREARGS_1
114 #define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1
116 #define ASMFMT_0()
117 /* "acdSD" constraint would work too, but "SD" would use esi/edi and cause
118 * them to be pushed/popped by compiler, "a" would use eax and cause ebx
119 * to be saved/restored on stack, not in register. Narrowing choice down
120 * to "ecx or edx" results in smaller and faster code: */
121 #define ASMFMT_1(arg1) \
122 , "cd" (arg1)
123 /* Can use "adSD" constraint here: */
124 #define ASMFMT_2(arg1, arg2) \
125 , "d" (arg1), "c" (arg2)
126 /* Can use "aSD" constraint here: */
127 #define ASMFMT_3(arg1, arg2, arg3) \
128 , "a" (arg1), "c" (arg2), "d" (arg3)
129 /* Can use "aD" constraint here: */
130 #define ASMFMT_4(arg1, arg2, arg3, arg4) \
131 , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
132 #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
133 , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
134 #define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \
135 , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6)
137 #else /* !PIC */
139 /* Simpler code which just uses "b" constraint to load ebx.
140 * Seems to work with gc 4.2.x, and generates slightly smaller,
141 * but slightly slower code. Example (time syscall):
143 * - 8b 4c 24 04 mov 0x4(%esp),%ecx
144 * - 87 cb xchg %ecx,%ebx
145 * + 53 push %ebx
146 * + 8b 5c 24 08 mov 0x8(%esp),%ebx
147 * b8 0d 00 00 00 mov $0xd,%eax
148 * cd 80 int $0x80
149 * - 87 cb xchg %ecx,%ebx
150 * + 5b pop %ebx
151 * c3 ret
153 * 2 bytes smaller, but uses stack via "push/pop ebx"
156 #define LOADARGS_0
157 #define LOADARGS_1
158 #define LOADARGS_2
159 #define LOADARGS_3
160 #define LOADARGS_4
161 #define LOADARGS_5
162 #define LOADARGS_6 "push %%ebp\n\t" "movl %7, %%ebp\n\t"
164 #define RESTOREARGS_0
165 #define RESTOREARGS_1
166 #define RESTOREARGS_2
167 #define RESTOREARGS_3
168 #define RESTOREARGS_4
169 #define RESTOREARGS_5
170 #define RESTOREARGS_6 "pop %%ebp\n\t"
172 #define ASMFMT_0()
173 #define ASMFMT_1(arg1) \
174 , "b" (arg1)
175 #define ASMFMT_2(arg1, arg2) \
176 , "b" (arg1), "c" (arg2)
177 #define ASMFMT_3(arg1, arg2, arg3) \
178 , "b" (arg1), "c" (arg2), "d" (arg3)
179 #define ASMFMT_4(arg1, arg2, arg3, arg4) \
180 , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
181 #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
182 , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
183 #define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \
184 , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6)
186 #endif /* !PIC */
188 #endif /* __ASSEMBLER__ */
189 #endif /* _BITS_SYSCALLS_H */