]>
Commit | Line | Data |
---|---|---|
d063d164 UD |
1 | /* Copyright (C) 1992,1993,1995-2000,2002-2006,2007,2011 |
2 | Free Software Foundation, Inc. | |
bfbc5754 | 3 | This file is part of the GNU C Library. |
44129238 | 4 | Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995. |
bfbc5754 UD |
5 | |
6 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
bfbc5754 UD |
10 | |
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 14 | Lesser General Public License for more details. |
bfbc5754 | 15 | |
41bdb6e2 AJ |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with the GNU C Library; if not, write to the Free | |
18 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
19 | 02111-1307 USA. */ | |
d2f5be2a | 20 | |
ec4b0518 UD |
21 | #ifndef _LINUX_I386_SYSDEP_H |
22 | #define _LINUX_I386_SYSDEP_H 1 | |
23 | ||
d2f5be2a UD |
24 | /* There is some commonality. */ |
25 | #include <sysdeps/unix/i386/sysdep.h> | |
ee63ca21 GM |
26 | #include <bp-sym.h> |
27 | #include <bp-asm.h> | |
131fd126 | 28 | /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */ |
5f5843e3 | 29 | #include <dl-sysdep.h> |
739d440d | 30 | #include <tls.h> |
d2f5be2a | 31 | |
ce460d04 | 32 | |
d2f5be2a UD |
33 | /* For Linux we can use the system call table in the header file |
34 | /usr/include/asm/unistd.h | |
35 | of the kernel. But these symbols do not follow the SYS_* syntax | |
36 | so we have to redefine the `SYS_ify' macro here. */ | |
37 | #undef SYS_ify | |
6ed0492f | 38 | #define SYS_ify(syscall_name) __NR_##syscall_name |
d2f5be2a | 39 | |
131fd126 UD |
40 | #if defined USE_DL_SYSINFO \ |
41 | && (!defined NOT_IN_libc || defined IS_IN_libpthread) | |
5f5843e3 UD |
42 | # define I386_USE_SYSENTER 1 |
43 | #else | |
44 | # undef I386_USE_SYSENTER | |
45 | #endif | |
46 | ||
c2afe833 RM |
47 | #ifdef __ASSEMBLER__ |
48 | ||
cccda09f UD |
49 | /* Linux uses a negative return value to indicate syscall errors, |
50 | unlike most Unices, which use the condition codes' carry flag. | |
51 | ||
52 | Since version 2.1 the return value of a system call might be | |
53 | negative even if the call succeeded. E.g., the `lseek' system call | |
54 | might return a large offset. Therefore we must not anymore test | |
55 | for < 0, but test for a real error by making sure the value in %eax | |
b5791037 UD |
56 | is a real error number. Linus said he will make sure the no syscall |
57 | returns a value in -1 .. -4095 as a valid result so we can savely | |
58 | test with -4095. */ | |
c0fb8a56 UD |
59 | |
60 | /* We don't want the label for the error handle to be global when we define | |
61 | it here. */ | |
62 | #ifdef PIC | |
63 | # define SYSCALL_ERROR_LABEL 0f | |
64 | #else | |
65 | # define SYSCALL_ERROR_LABEL syscall_error | |
66 | #endif | |
67 | ||
d2f5be2a UD |
68 | #undef PSEUDO |
69 | #define PSEUDO(name, syscall_name, args) \ | |
70 | .text; \ | |
d2f5be2a | 71 | ENTRY (name) \ |
ffa8d2a0 | 72 | DO_CALL (syscall_name, args); \ |
b5791037 | 73 | cmpl $-4095, %eax; \ |
c0fb8a56 | 74 | jae SYSCALL_ERROR_LABEL; \ |
ae828bc6 | 75 | L(pseudo_end): |
d2f5be2a | 76 | |
6ed0492f UD |
77 | #undef PSEUDO_END |
78 | #define PSEUDO_END(name) \ | |
79 | SYSCALL_ERROR_HANDLER \ | |
80 | END (name) | |
81 | ||
9eb88290 UD |
82 | #undef PSEUDO_NOERRNO |
83 | #define PSEUDO_NOERRNO(name, syscall_name, args) \ | |
84 | .text; \ | |
85 | ENTRY (name) \ | |
86 | DO_CALL (syscall_name, args) | |
87 | ||
88 | #undef PSEUDO_END_NOERRNO | |
89 | #define PSEUDO_END_NOERRNO(name) \ | |
90 | END (name) | |
91 | ||
92 | #define ret_NOERRNO ret | |
93 | ||
bfef9264 UD |
94 | /* The function has to return the error code. */ |
95 | #undef PSEUDO_ERRVAL | |
96 | #define PSEUDO_ERRVAL(name, syscall_name, args) \ | |
97 | .text; \ | |
98 | ENTRY (name) \ | |
99 | DO_CALL (syscall_name, args); \ | |
100 | negl %eax | |
101 | ||
102 | #undef PSEUDO_END_ERRVAL | |
103 | #define PSEUDO_END_ERRVAL(name) \ | |
104 | END (name) | |
105 | ||
106 | #define ret_ERRVAL ret | |
107 | ||
edf5b2d7 | 108 | #ifndef PIC |
739d440d | 109 | # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ |
03a75825 | 110 | #else |
9bd64602 | 111 | |
ce460d04 RM |
112 | # if RTLD_PRIVATE_ERRNO |
113 | # define SYSCALL_ERROR_HANDLER \ | |
114 | 0:SETUP_PIC_REG(cx); \ | |
115 | addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ | |
116 | xorl %edx, %edx; \ | |
117 | subl %eax, %edx; \ | |
96c82b3f | 118 | movl %edx, rtld_errno@GOTOFF(%ecx); \ |
ce460d04 RM |
119 | orl $-1, %eax; \ |
120 | jmp L(pseudo_end); | |
739d440d | 121 | |
ce460d04 RM |
122 | # elif defined _LIBC_REENTRANT |
123 | ||
d063d164 UD |
124 | # ifndef NOT_IN_libc |
125 | # define SYSCALL_ERROR_ERRNO __libc_errno | |
126 | # else | |
127 | # define SYSCALL_ERROR_ERRNO errno | |
128 | # endif | |
129 | # define SYSCALL_ERROR_HANDLER \ | |
739d440d UD |
130 | 0:SETUP_PIC_REG (cx); \ |
131 | addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ | |
ac2dc598 | 132 | movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx; \ |
739d440d UD |
133 | xorl %edx, %edx; \ |
134 | subl %eax, %edx; \ | |
70a8119b | 135 | SYSCALL_ERROR_HANDLER_TLS_STORE (%edx, %ecx); \ |
739d440d UD |
136 | orl $-1, %eax; \ |
137 | jmp L(pseudo_end); | |
d063d164 UD |
138 | # ifndef NO_TLS_DIRECT_SEG_REFS |
139 | # define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff) \ | |
24992143 | 140 | movl src, %gs:(destoff) |
d063d164 UD |
141 | # else |
142 | # define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff) \ | |
70a8119b RM |
143 | addl %gs:0, destoff; \ |
144 | movl src, (destoff) | |
739d440d | 145 | # endif |
9bd64602 | 146 | # else |
ce460d04 | 147 | /* Store (- %eax) into errno through the GOT. */ |
739d440d | 148 | # define SYSCALL_ERROR_HANDLER \ |
09d65ff3 | 149 | 0:SETUP_PIC_REG(cx); \ |
b44e3016 | 150 | addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ |
edf5b2d7 | 151 | xorl %edx, %edx; \ |
edf5b2d7 | 152 | subl %eax, %edx; \ |
03a75825 | 153 | movl errno@GOT(%ecx), %ecx; \ |
edf5b2d7 | 154 | movl %edx, (%ecx); \ |
b259e746 | 155 | orl $-1, %eax; \ |
c0fb8a56 | 156 | jmp L(pseudo_end); |
739d440d | 157 | # endif /* _LIBC_REENTRANT */ |
edf5b2d7 | 158 | #endif /* PIC */ |
03a75825 | 159 | |
f051627f UD |
160 | |
161 | /* The original calling convention for system calls on Linux/i386 is | |
162 | to use int $0x80. */ | |
5f5843e3 UD |
163 | #ifdef I386_USE_SYSENTER |
164 | # ifdef SHARED | |
165 | # define ENTER_KERNEL call *%gs:SYSINFO_OFFSET | |
166 | # else | |
167 | # define ENTER_KERNEL call *_dl_sysinfo | |
168 | # endif | |
169 | #else | |
170 | # define ENTER_KERNEL int $0x80 | |
171 | #endif | |
f051627f | 172 | |
d2f5be2a UD |
173 | /* Linux takes system call arguments in registers: |
174 | ||
175 | syscall number %eax call-clobbered | |
176 | arg 1 %ebx call-saved | |
177 | arg 2 %ecx call-clobbered | |
178 | arg 3 %edx call-clobbered | |
179 | arg 4 %esi call-saved | |
180 | arg 5 %edi call-saved | |
b2bcd249 | 181 | arg 6 %ebp call-saved |
d2f5be2a UD |
182 | |
183 | The stack layout upon entering the function is: | |
184 | ||
b2bcd249 | 185 | 24(%esp) Arg# 6 |
d2f5be2a UD |
186 | 20(%esp) Arg# 5 |
187 | 16(%esp) Arg# 4 | |
188 | 12(%esp) Arg# 3 | |
189 | 8(%esp) Arg# 2 | |
190 | 4(%esp) Arg# 1 | |
191 | (%esp) Return address | |
192 | ||
193 | (Of course a function with say 3 arguments does not have entries for | |
b2bcd249 | 194 | arguments 4, 5, and 6.) |
d2f5be2a | 195 | |
6ed0492f | 196 | The following code tries hard to be optimal. A general assumption |
03a75825 | 197 | (which is true according to the data books I have) is that |
d2f5be2a UD |
198 | |
199 | 2 * xchg is more expensive than pushl + movl + popl | |
200 | ||
201 | Beside this a neat trick is used. The calling conventions for Linux | |
202 | tell that among the registers used for parameters %ecx and %edx need | |
203 | not be saved. Beside this we may clobber this registers even when | |
204 | they are not used for parameter passing. | |
205 | ||
206 | As a result one can see below that we save the content of the %ebx | |
207 | register in the %edx register when we have less than 3 arguments | |
208 | (2 * movl is less expensive than pushl + popl). | |
209 | ||
210 | Second unlike for the other registers we don't save the content of | |
6ed0492f | 211 | %ecx and %edx when we have more than 1 and 2 registers resp. |
8f5ca04b RM |
212 | |
213 | The code below might look a bit long but we have to take care for | |
63bda0c1 | 214 | the pipelined processors (i586). Here the `pushl' and `popl' |
8f5ca04b RM |
215 | instructions are marked as NP (not pairable) but the exception is |
216 | two consecutive of these instruction. This gives no penalty on | |
63bda0c1 | 217 | other processors though. */ |
d2f5be2a UD |
218 | |
219 | #undef DO_CALL | |
ffa8d2a0 | 220 | #define DO_CALL(syscall_name, args) \ |
8f5ca04b | 221 | PUSHARGS_##args \ |
d2f5be2a | 222 | DOARGS_##args \ |
c14e4c32 | 223 | movl $SYS_ify (syscall_name), %eax; \ |
f051627f | 224 | ENTER_KERNEL \ |
8f5ca04b | 225 | POPARGS_##args |
d2f5be2a | 226 | |
8f5ca04b | 227 | #define PUSHARGS_0 /* No arguments to push. */ |
d2f5be2a | 228 | #define DOARGS_0 /* No arguments to frob. */ |
8f5ca04b RM |
229 | #define POPARGS_0 /* No arguments to pop. */ |
230 | #define _PUSHARGS_0 /* No arguments to push. */ | |
231 | #define _DOARGS_0(n) /* No arguments to frob. */ | |
232 | #define _POPARGS_0 /* No arguments to pop. */ | |
233 | ||
bd4f43b4 | 234 | #define PUSHARGS_1 movl %ebx, %edx; L(SAVEBX1): PUSHARGS_0 |
8f5ca04b | 235 | #define DOARGS_1 _DOARGS_1 (4) |
bd4f43b4 | 236 | #define POPARGS_1 POPARGS_0; movl %edx, %ebx; L(RESTBX1): |
62d01985 UD |
237 | #define _PUSHARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ |
238 | cfi_rel_offset (ebx, 0); L(PUSHBX1): _PUSHARGS_0 | |
8f5ca04b | 239 | #define _DOARGS_1(n) movl n(%esp), %ebx; _DOARGS_0(n-4) |
62d01985 UD |
240 | #define _POPARGS_1 _POPARGS_0; popl %ebx; cfi_adjust_cfa_offset (-4); \ |
241 | cfi_restore (ebx); L(POPBX1): | |
8f5ca04b RM |
242 | |
243 | #define PUSHARGS_2 PUSHARGS_1 | |
244 | #define DOARGS_2 _DOARGS_2 (8) | |
245 | #define POPARGS_2 POPARGS_1 | |
246 | #define _PUSHARGS_2 _PUSHARGS_1 | |
d2f5be2a | 247 | #define _DOARGS_2(n) movl n(%esp), %ecx; _DOARGS_1 (n-4) |
8f5ca04b | 248 | #define _POPARGS_2 _POPARGS_1 |
d2f5be2a | 249 | |
8f5ca04b RM |
250 | #define PUSHARGS_3 _PUSHARGS_2 |
251 | #define DOARGS_3 _DOARGS_3 (16) | |
252 | #define POPARGS_3 _POPARGS_3 | |
253 | #define _PUSHARGS_3 _PUSHARGS_2 | |
d2f5be2a | 254 | #define _DOARGS_3(n) movl n(%esp), %edx; _DOARGS_2 (n-4) |
8f5ca04b RM |
255 | #define _POPARGS_3 _POPARGS_2 |
256 | ||
257 | #define PUSHARGS_4 _PUSHARGS_4 | |
258 | #define DOARGS_4 _DOARGS_4 (24) | |
259 | #define POPARGS_4 _POPARGS_4 | |
62d01985 UD |
260 | #define _PUSHARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ |
261 | cfi_rel_offset (esi, 0); L(PUSHSI1): _PUSHARGS_3 | |
8f5ca04b | 262 | #define _DOARGS_4(n) movl n(%esp), %esi; _DOARGS_3 (n-4) |
62d01985 UD |
263 | #define _POPARGS_4 _POPARGS_3; popl %esi; cfi_adjust_cfa_offset (-4); \ |
264 | cfi_restore (esi); L(POPSI1): | |
8f5ca04b RM |
265 | |
266 | #define PUSHARGS_5 _PUSHARGS_5 | |
267 | #define DOARGS_5 _DOARGS_5 (32) | |
268 | #define POPARGS_5 _POPARGS_5 | |
62d01985 UD |
269 | #define _PUSHARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ |
270 | cfi_rel_offset (edi, 0); L(PUSHDI1): _PUSHARGS_4 | |
8f5ca04b | 271 | #define _DOARGS_5(n) movl n(%esp), %edi; _DOARGS_4 (n-4) |
62d01985 UD |
272 | #define _POPARGS_5 _POPARGS_4; popl %edi; cfi_adjust_cfa_offset (-4); \ |
273 | cfi_restore (edi); L(POPDI1): | |
d2f5be2a | 274 | |
0da7bcc5 | 275 | #define PUSHARGS_6 _PUSHARGS_6 |
46c38bd7 | 276 | #define DOARGS_6 _DOARGS_6 (40) |
0da7bcc5 | 277 | #define POPARGS_6 _POPARGS_6 |
62d01985 UD |
278 | #define _PUSHARGS_6 pushl %ebp; cfi_adjust_cfa_offset (4); \ |
279 | cfi_rel_offset (ebp, 0); L(PUSHBP1): _PUSHARGS_5 | |
0da7bcc5 | 280 | #define _DOARGS_6(n) movl n(%esp), %ebp; _DOARGS_5 (n-4) |
62d01985 UD |
281 | #define _POPARGS_6 _POPARGS_5; popl %ebp; cfi_adjust_cfa_offset (-4); \ |
282 | cfi_restore (ebp); L(POPBP1): | |
0da7bcc5 | 283 | |
adcb550c UD |
284 | #else /* !__ASSEMBLER__ */ |
285 | ||
78e5779b UD |
286 | /* We need some help from the assembler to generate optimal code. We |
287 | define some macros here which later will be used. */ | |
e3e35cfc UD |
288 | asm (".L__X'%ebx = 1\n\t" |
289 | ".L__X'%ecx = 2\n\t" | |
290 | ".L__X'%edx = 2\n\t" | |
291 | ".L__X'%eax = 3\n\t" | |
292 | ".L__X'%esi = 3\n\t" | |
293 | ".L__X'%edi = 3\n\t" | |
294 | ".L__X'%ebp = 3\n\t" | |
295 | ".L__X'%esp = 3\n\t" | |
78e5779b UD |
296 | ".macro bpushl name reg\n\t" |
297 | ".if 1 - \\name\n\t" | |
298 | ".if 2 - \\name\n\t" | |
7a114794 | 299 | "error\n\t" |
78e5779b UD |
300 | ".else\n\t" |
301 | "xchgl \\reg, %ebx\n\t" | |
302 | ".endif\n\t" | |
303 | ".endif\n\t" | |
304 | ".endm\n\t" | |
305 | ".macro bpopl name reg\n\t" | |
306 | ".if 1 - \\name\n\t" | |
307 | ".if 2 - \\name\n\t" | |
7a114794 | 308 | "error\n\t" |
78e5779b UD |
309 | ".else\n\t" |
310 | "xchgl \\reg, %ebx\n\t" | |
311 | ".endif\n\t" | |
312 | ".endif\n\t" | |
78e5779b UD |
313 | ".endm\n\t"); |
314 | ||
adcb550c UD |
315 | /* Define a macro which expands inline into the wrapper code for a system |
316 | call. */ | |
317 | #undef INLINE_SYSCALL | |
318 | #define INLINE_SYSCALL(name, nr, args...) \ | |
ce460d04 | 319 | ({ \ |
6aca81bb UD |
320 | unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args); \ |
321 | if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0)) \ | |
ce460d04 | 322 | { \ |
6aca81bb | 323 | __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \ |
ce460d04 RM |
324 | resultvar = 0xffffffff; \ |
325 | } \ | |
326 | (int) resultvar; }) | |
327 | ||
328 | /* Define a macro which expands inline into the wrapper code for a system | |
329 | call. This use is for internal calls that do not need to handle errors | |
330 | normally. It will never touch errno. This returns just what the kernel | |
2edb61e3 UD |
331 | gave back. |
332 | ||
333 | The _NCS variant allows non-constant syscall numbers but it is not | |
334 | possible to use more than four parameters. */ | |
ce460d04 | 335 | #undef INTERNAL_SYSCALL |
5f5843e3 UD |
336 | #ifdef I386_USE_SYSENTER |
337 | # ifdef SHARED | |
6aca81bb | 338 | # define INTERNAL_SYSCALL(name, err, nr, args...) \ |
5f5843e3 | 339 | ({ \ |
7a114794 UD |
340 | register unsigned int resultvar; \ |
341 | EXTRAVAR_##nr \ | |
5f5843e3 UD |
342 | asm volatile ( \ |
343 | LOADARGS_##nr \ | |
344 | "movl %1, %%eax\n\t" \ | |
345 | "call *%%gs:%P2\n\t" \ | |
346 | RESTOREARGS_##nr \ | |
347 | : "=a" (resultvar) \ | |
348 | : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo)) \ | |
349 | ASMFMT_##nr(args) : "memory", "cc"); \ | |
350 | (int) resultvar; }) | |
2edb61e3 UD |
351 | # define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ |
352 | ({ \ | |
353 | register unsigned int resultvar; \ | |
354 | EXTRAVAR_##nr \ | |
355 | asm volatile ( \ | |
356 | LOADARGS_##nr \ | |
357 | "call *%%gs:%P2\n\t" \ | |
358 | RESTOREARGS_##nr \ | |
359 | : "=a" (resultvar) \ | |
360 | : "0" (name), "i" (offsetof (tcbhead_t, sysinfo)) \ | |
361 | ASMFMT_##nr(args) : "memory", "cc"); \ | |
362 | (int) resultvar; }) | |
5f5843e3 | 363 | # else |
6aca81bb | 364 | # define INTERNAL_SYSCALL(name, err, nr, args...) \ |
adcb550c | 365 | ({ \ |
7a114794 UD |
366 | register unsigned int resultvar; \ |
367 | EXTRAVAR_##nr \ | |
adcb550c | 368 | asm volatile ( \ |
44129238 | 369 | LOADARGS_##nr \ |
78e5779b | 370 | "movl %1, %%eax\n\t" \ |
5f5843e3 | 371 | "call *_dl_sysinfo\n\t" \ |
44129238 | 372 | RESTOREARGS_##nr \ |
adcb550c | 373 | : "=a" (resultvar) \ |
78e5779b | 374 | : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc"); \ |
adcb550c | 375 | (int) resultvar; }) |
2edb61e3 UD |
376 | # define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ |
377 | ({ \ | |
378 | register unsigned int resultvar; \ | |
379 | EXTRAVAR_##nr \ | |
380 | asm volatile ( \ | |
381 | LOADARGS_##nr \ | |
382 | "call *_dl_sysinfo\n\t" \ | |
383 | RESTOREARGS_##nr \ | |
384 | : "=a" (resultvar) \ | |
385 | : "0" (name) ASMFMT_##nr(args) : "memory", "cc"); \ | |
386 | (int) resultvar; }) | |
5f5843e3 UD |
387 | # endif |
388 | #else | |
6aca81bb | 389 | # define INTERNAL_SYSCALL(name, err, nr, args...) \ |
5f5843e3 | 390 | ({ \ |
7a114794 UD |
391 | register unsigned int resultvar; \ |
392 | EXTRAVAR_##nr \ | |
5f5843e3 UD |
393 | asm volatile ( \ |
394 | LOADARGS_##nr \ | |
395 | "movl %1, %%eax\n\t" \ | |
7a114794 | 396 | "int $0x80\n\t" \ |
5f5843e3 UD |
397 | RESTOREARGS_##nr \ |
398 | : "=a" (resultvar) \ | |
399 | : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc"); \ | |
400 | (int) resultvar; }) | |
2edb61e3 UD |
401 | # define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ |
402 | ({ \ | |
403 | register unsigned int resultvar; \ | |
404 | EXTRAVAR_##nr \ | |
405 | asm volatile ( \ | |
406 | LOADARGS_##nr \ | |
407 | "int $0x80\n\t" \ | |
408 | RESTOREARGS_##nr \ | |
409 | : "=a" (resultvar) \ | |
410 | : "0" (name) ASMFMT_##nr(args) : "memory", "cc"); \ | |
411 | (int) resultvar; }) | |
5f5843e3 | 412 | #endif |
adcb550c | 413 | |
6aca81bb UD |
414 | #undef INTERNAL_SYSCALL_DECL |
415 | #define INTERNAL_SYSCALL_DECL(err) do { } while (0) | |
416 | ||
f4447671 | 417 | #undef INTERNAL_SYSCALL_ERROR_P |
6aca81bb UD |
418 | #define INTERNAL_SYSCALL_ERROR_P(val, err) \ |
419 | ((unsigned int) (val) >= 0xfffff001u) | |
f4447671 UD |
420 | |
421 | #undef INTERNAL_SYSCALL_ERRNO | |
6aca81bb | 422 | #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) |
f4447671 | 423 | |
44129238 | 424 | #define LOADARGS_0 |
7a114794 | 425 | #ifdef __PIC__ |
a44cffaa | 426 | # if defined I386_USE_SYSENTER && defined SHARED |
7a114794 UD |
427 | # define LOADARGS_1 \ |
428 | "bpushl .L__X'%k3, %k3\n\t" | |
429 | # define LOADARGS_5 \ | |
430 | "movl %%ebx, %4\n\t" \ | |
431 | "movl %3, %%ebx\n\t" | |
432 | # else | |
433 | # define LOADARGS_1 \ | |
434 | "bpushl .L__X'%k2, %k2\n\t" | |
435 | # define LOADARGS_5 \ | |
436 | "movl %%ebx, %3\n\t" \ | |
437 | "movl %2, %%ebx\n\t" | |
438 | # endif | |
439 | # define LOADARGS_2 LOADARGS_1 | |
440 | # define LOADARGS_3 \ | |
441 | "xchgl %%ebx, %%edi\n\t" | |
442 | # define LOADARGS_4 LOADARGS_3 | |
5f5843e3 | 443 | #else |
7a114794 UD |
444 | # define LOADARGS_1 |
445 | # define LOADARGS_2 | |
446 | # define LOADARGS_3 | |
447 | # define LOADARGS_4 | |
448 | # define LOADARGS_5 | |
5f5843e3 | 449 | #endif |
44129238 UD |
450 | |
451 | #define RESTOREARGS_0 | |
7a114794 UD |
452 | #ifdef __PIC__ |
453 | # if defined I386_USE_SYSENTER && defined SHARED | |
454 | # define RESTOREARGS_1 \ | |
5f5843e3 | 455 | "bpopl .L__X'%k3, %k3\n\t" |
7a114794 UD |
456 | # define RESTOREARGS_5 \ |
457 | "movl %4, %%ebx" | |
458 | # else | |
459 | # define RESTOREARGS_1 \ | |
44129238 | 460 | "bpopl .L__X'%k2, %k2\n\t" |
7a114794 UD |
461 | # define RESTOREARGS_5 \ |
462 | "movl %3, %%ebx" | |
463 | # endif | |
464 | # define RESTOREARGS_2 RESTOREARGS_1 | |
465 | # define RESTOREARGS_3 \ | |
466 | "xchgl %%edi, %%ebx\n\t" | |
467 | # define RESTOREARGS_4 RESTOREARGS_3 | |
468 | #else | |
469 | # define RESTOREARGS_1 | |
470 | # define RESTOREARGS_2 | |
471 | # define RESTOREARGS_3 | |
472 | # define RESTOREARGS_4 | |
473 | # define RESTOREARGS_5 | |
5f5843e3 | 474 | #endif |
44129238 | 475 | |
7bb38c70 | 476 | #define ASMFMT_0() |
7a114794 UD |
477 | #ifdef __PIC__ |
478 | # define ASMFMT_1(arg1) \ | |
479 | , "cd" (arg1) | |
480 | # define ASMFMT_2(arg1, arg2) \ | |
3a370de8 | 481 | , "d" (arg1), "c" (arg2) |
7a114794 UD |
482 | # define ASMFMT_3(arg1, arg2, arg3) \ |
483 | , "D" (arg1), "c" (arg2), "d" (arg3) | |
484 | # define ASMFMT_4(arg1, arg2, arg3, arg4) \ | |
485 | , "D" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) | |
486 | # define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ | |
487 | , "0" (arg1), "m" (_xv), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) | |
488 | #else | |
489 | # define ASMFMT_1(arg1) \ | |
490 | , "b" (arg1) | |
491 | # define ASMFMT_2(arg1, arg2) \ | |
492 | , "b" (arg1), "c" (arg2) | |
493 | # define ASMFMT_3(arg1, arg2, arg3) \ | |
494 | , "b" (arg1), "c" (arg2), "d" (arg3) | |
495 | # define ASMFMT_4(arg1, arg2, arg3, arg4) \ | |
496 | , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) | |
497 | # define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ | |
498 | , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) | |
499 | #endif | |
500 | ||
501 | #define EXTRAVAR_0 | |
502 | #define EXTRAVAR_1 | |
503 | #define EXTRAVAR_2 | |
504 | #define EXTRAVAR_3 | |
505 | #define EXTRAVAR_4 | |
506 | #ifdef __PIC__ | |
507 | # define EXTRAVAR_5 int _xv; | |
508 | #else | |
509 | # define EXTRAVAR_5 | |
510 | #endif | |
adcb550c | 511 | |
dbfc1e02 UD |
512 | /* Consistency check for position-independent code. */ |
513 | #ifdef __PIC__ | |
514 | # define check_consistency() \ | |
515 | ({ int __res; \ | |
516 | __asm__ __volatile__ \ | |
517 | ("call __i686.get_pc_thunk.cx;" \ | |
518 | "addl $_GLOBAL_OFFSET_TABLE_, %%ecx;" \ | |
519 | "subl %%ebx, %%ecx;" \ | |
520 | "je 1f;" \ | |
521 | "ud2;" \ | |
522 | "1:\n" \ | |
523 | ".section .gnu.linkonce.t.__i686.get_pc_thunk.cx,\"ax\",@progbits;" \ | |
524 | ".globl __i686.get_pc_thunk.cx;" \ | |
525 | ".hidden __i686.get_pc_thunk.cx;" \ | |
526 | ".type __i686.get_pc_thunk.cx,@function;" \ | |
527 | "__i686.get_pc_thunk.cx:" \ | |
528 | "movl (%%esp), %%ecx;" \ | |
529 | "ret;" \ | |
530 | ".previous" \ | |
531 | : "=c" (__res)); \ | |
532 | __res; }) | |
533 | #endif | |
534 | ||
66715f83 | 535 | #endif /* __ASSEMBLER__ */ |
ec4b0518 | 536 | |
827b7087 UD |
537 | |
538 | /* Pointer mangling support. */ | |
539 | #if defined NOT_IN_libc && defined IS_IN_rtld | |
540 | /* We cannot use the thread descriptor because in ld.so we use setjmp | |
541 | earlier than the descriptor is initialized. Using a global variable | |
542 | is too complicated here since we have no PC-relative addressing mode. */ | |
543 | #else | |
3467f5c3 | 544 | # ifdef __ASSEMBLER__ |
4a44ce79 UD |
545 | # define PTR_MANGLE(reg) xorl %gs:POINTER_GUARD, reg; \ |
546 | roll $9, reg | |
547 | # define PTR_DEMANGLE(reg) rorl $9, reg; \ | |
548 | xorl %gs:POINTER_GUARD, reg | |
3467f5c3 | 549 | # else |
4a44ce79 UD |
550 | # define PTR_MANGLE(var) asm ("xorl %%gs:%c2, %0\n" \ |
551 | "roll $9, %0" \ | |
552 | : "=r" (var) \ | |
553 | : "0" (var), \ | |
554 | "i" (offsetof (tcbhead_t, \ | |
555 | pointer_guard))) | |
556 | # define PTR_DEMANGLE(var) asm ("rorl $9, %0\n" \ | |
557 | "xorl %%gs:%c2, %0" \ | |
3467f5c3 UD |
558 | : "=r" (var) \ |
559 | : "0" (var), \ | |
560 | "i" (offsetof (tcbhead_t, \ | |
561 | pointer_guard))) | |
3467f5c3 | 562 | # endif |
827b7087 UD |
563 | #endif |
564 | ||
ec4b0518 | 565 | #endif /* linux/i386/sysdep.h */ |