(INTERNAL_SYSCALL, INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO):
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / linux / i386 / sysdep.h
1 /* Copyright (C) 1992,1993,1995-2000,2002,2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper, <drepper@gnu.org>, 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 Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the 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    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #ifndef _LINUX_I386_SYSDEP_H
21 #define _LINUX_I386_SYSDEP_H 1
22
23 /* There is some commonality.  */
24 #include <sysdeps/unix/i386/sysdep.h>
25 #include <bp-sym.h>
26 #include <bp-asm.h>
27 /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO.  */
28 #include <dl-sysdep.h>
29 #include <tls.h>
30
31
32 /* For Linux we can use the system call table in the header file
33         /usr/include/asm/unistd.h
34    of the kernel.  But these symbols do not follow the SYS_* syntax
35    so we have to redefine the `SYS_ify' macro here.  */
36 #undef SYS_ify
37 #define SYS_ify(syscall_name)   __NR_##syscall_name
38
39 #if defined USE_DL_SYSINFO \
40     && (!defined NOT_IN_libc || defined IS_IN_libpthread)
41 # define I386_USE_SYSENTER      1
42 #else
43 # undef I386_USE_SYSENTER
44 #endif
45
46 #ifdef __ASSEMBLER__
47
48 /* Linux uses a negative return value to indicate syscall errors,
49    unlike most Unices, which use the condition codes' carry flag.
50
51    Since version 2.1 the return value of a system call might be
52    negative even if the call succeeded.  E.g., the `lseek' system call
53    might return a large offset.  Therefore we must not anymore test
54    for < 0, but test for a real error by making sure the value in %eax
55    is a real error number.  Linus said he will make sure the no syscall
56    returns a value in -1 .. -4095 as a valid result so we can savely
57    test with -4095.  */
58
59 /* We don't want the label for the error handle to be global when we define
60    it here.  */
61 #ifdef PIC
62 # define SYSCALL_ERROR_LABEL 0f
63 #else
64 # define SYSCALL_ERROR_LABEL syscall_error
65 #endif
66
67 #undef  PSEUDO
68 #define PSEUDO(name, syscall_name, args)                                      \
69   .text;                                                                      \
70   ENTRY (name)                                                                \
71     DO_CALL (syscall_name, args);                                             \
72     cmpl $-4095, %eax;                                                        \
73     jae SYSCALL_ERROR_LABEL;                                                  \
74   L(pseudo_end):
75
76 #undef  PSEUDO_END
77 #define PSEUDO_END(name)                                                      \
78   SYSCALL_ERROR_HANDLER                                                       \
79   END (name)
80
81 #ifndef PIC
82 # define SYSCALL_ERROR_HANDLER  /* Nothing here; code in sysdep.S is used.  */
83 #else
84
85 # ifndef HAVE_HIDDEN
86 #  define SETUP_PIC_REG(reg) \
87   call 1f;                                                                    \
88   .subsection 1;                                                              \
89 1:movl (%esp), %e##reg;                                                       \
90   ret;                                                                        \
91   .previous
92 # else
93 #  define SETUP_PIC_REG(reg) \
94   .section .gnu.linkonce.t.__i686.get_pc_thunk.reg,"ax",@progbits;            \
95   .globl __i686.get_pc_thunk.reg;                                             \
96   .hidden __i686.get_pc_thunk.reg;                                            \
97   .type __i686.get_pc_thunk.reg,@function;                                    \
98 __i686.get_pc_thunk.reg:                                                      \
99   movl (%esp), %e##reg;                                                       \
100   ret;                                                                        \
101   .size __i686.get_pc_thunk.reg, . - __i686.get_pc_thunk.reg;                 \
102   .previous;                                                                  \
103   call __i686.get_pc_thunk.reg
104 # endif
105
106 # if RTLD_PRIVATE_ERRNO
107 #  define SYSCALL_ERROR_HANDLER                                               \
108 0:SETUP_PIC_REG(cx);                                                          \
109   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                          \
110   xorl %edx, %edx;                                                            \
111   subl %eax, %edx;                                                            \
112   movl %edx, errno@GOTOFF(%ecx);                                              \
113   orl $-1, %eax;                                                              \
114   jmp L(pseudo_end);
115
116 # elif defined _LIBC_REENTRANT
117
118 #  if USE___THREAD
119 #   ifndef NOT_IN_libc
120 #    define SYSCALL_ERROR_ERRNO __libc_errno
121 #   else
122 #    define SYSCALL_ERROR_ERRNO errno
123 #   endif
124 #   define SYSCALL_ERROR_HANDLER                                              \
125 0:SETUP_PIC_REG (cx);                                                         \
126   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                          \
127   movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx;                             \
128   xorl %edx, %edx;                                                            \
129   subl %eax, %edx;                                                            \
130   movl %edx, %gs:0(%ecx);                                                     \
131   orl $-1, %eax;                                                              \
132   jmp L(pseudo_end);
133 #  else
134 #   define SYSCALL_ERROR_HANDLER                                              \
135 0:pushl %ebx;                                                                 \
136   SETUP_PIC_REG (bx);                                                         \
137   addl $_GLOBAL_OFFSET_TABLE_, %ebx;                                          \
138   xorl %edx, %edx;                                                            \
139   subl %eax, %edx;                                                            \
140   pushl %edx;                                                                 \
141   PUSH_ERRNO_LOCATION_RETURN;                                                 \
142   call BP_SYM (__errno_location)@PLT;                                         \
143   POP_ERRNO_LOCATION_RETURN;                                                  \
144   popl %ecx;                                                                  \
145   popl %ebx;                                                                  \
146   movl %ecx, (%eax);                                                          \
147   orl $-1, %eax;                                                              \
148   jmp L(pseudo_end);
149 /* A quick note: it is assumed that the call to `__errno_location' does
150    not modify the stack!  */
151 #  endif
152 # else
153 /* Store (- %eax) into errno through the GOT.  */
154 #  define SYSCALL_ERROR_HANDLER                                               \
155 0:SETUP_PIC_REG(cx);                                                  \
156   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                          \
157   xorl %edx, %edx;                                                            \
158   subl %eax, %edx;                                                            \
159   movl errno@GOT(%ecx), %ecx;                                                 \
160   movl %edx, (%ecx);                                                          \
161   orl $-1, %eax;                                                              \
162   jmp L(pseudo_end);
163 # endif /* _LIBC_REENTRANT */
164 #endif  /* PIC */
165
166
167 /* The original calling convention for system calls on Linux/i386 is
168    to use int $0x80.  */
169 #ifdef I386_USE_SYSENTER
170 # ifdef SHARED
171 #  define ENTER_KERNEL call *%gs:SYSINFO_OFFSET
172 # else
173 #  define ENTER_KERNEL call *_dl_sysinfo
174 # endif
175 #else
176 # define ENTER_KERNEL int $0x80
177 #endif
178
179 /* Linux takes system call arguments in registers:
180
181         syscall number  %eax         call-clobbered
182         arg 1           %ebx         call-saved
183         arg 2           %ecx         call-clobbered
184         arg 3           %edx         call-clobbered
185         arg 4           %esi         call-saved
186         arg 5           %edi         call-saved
187
188    The stack layout upon entering the function is:
189
190         20(%esp)        Arg# 5
191         16(%esp)        Arg# 4
192         12(%esp)        Arg# 3
193          8(%esp)        Arg# 2
194          4(%esp)        Arg# 1
195           (%esp)        Return address
196
197    (Of course a function with say 3 arguments does not have entries for
198    arguments 4 and 5.)
199
200    The following code tries hard to be optimal.  A general assumption
201    (which is true according to the data books I have) is that
202
203         2 * xchg        is more expensive than  pushl + movl + popl
204
205    Beside this a neat trick is used.  The calling conventions for Linux
206    tell that among the registers used for parameters %ecx and %edx need
207    not be saved.  Beside this we may clobber this registers even when
208    they are not used for parameter passing.
209
210    As a result one can see below that we save the content of the %ebx
211    register in the %edx register when we have less than 3 arguments
212    (2 * movl is less expensive than pushl + popl).
213
214    Second unlike for the other registers we don't save the content of
215    %ecx and %edx when we have more than 1 and 2 registers resp.
216
217    The code below might look a bit long but we have to take care for
218    the pipelined processors (i586).  Here the `pushl' and `popl'
219    instructions are marked as NP (not pairable) but the exception is
220    two consecutive of these instruction.  This gives no penalty on
221    other processors though.  */
222
223 #undef  DO_CALL
224 #define DO_CALL(syscall_name, args)                                           \
225     PUSHARGS_##args                                                           \
226     DOARGS_##args                                                             \
227     movl $SYS_ify (syscall_name), %eax;                                       \
228     ENTER_KERNEL                                                              \
229     POPARGS_##args
230
231 #define PUSHARGS_0      /* No arguments to push.  */
232 #define DOARGS_0        /* No arguments to frob.  */
233 #define POPARGS_0       /* No arguments to pop.  */
234 #define _PUSHARGS_0     /* No arguments to push.  */
235 #define _DOARGS_0(n)    /* No arguments to frob.  */
236 #define _POPARGS_0      /* No arguments to pop.  */
237
238 #define PUSHARGS_1      movl %ebx, %edx; PUSHARGS_0
239 #define DOARGS_1        _DOARGS_1 (4)
240 #define POPARGS_1       POPARGS_0; movl %edx, %ebx
241 #define _PUSHARGS_1     pushl %ebx; _PUSHARGS_0
242 #define _DOARGS_1(n)    movl n(%esp), %ebx; _DOARGS_0(n-4)
243 #define _POPARGS_1      _POPARGS_0; popl %ebx
244
245 #define PUSHARGS_2      PUSHARGS_1
246 #define DOARGS_2        _DOARGS_2 (8)
247 #define POPARGS_2       POPARGS_1
248 #define _PUSHARGS_2     _PUSHARGS_1
249 #define _DOARGS_2(n)    movl n(%esp), %ecx; _DOARGS_1 (n-4)
250 #define _POPARGS_2      _POPARGS_1
251
252 #define PUSHARGS_3      _PUSHARGS_2
253 #define DOARGS_3        _DOARGS_3 (16)
254 #define POPARGS_3       _POPARGS_3
255 #define _PUSHARGS_3     _PUSHARGS_2
256 #define _DOARGS_3(n)    movl n(%esp), %edx; _DOARGS_2 (n-4)
257 #define _POPARGS_3      _POPARGS_2
258
259 #define PUSHARGS_4      _PUSHARGS_4
260 #define DOARGS_4        _DOARGS_4 (24)
261 #define POPARGS_4       _POPARGS_4
262 #define _PUSHARGS_4     pushl %esi; _PUSHARGS_3
263 #define _DOARGS_4(n)    movl n(%esp), %esi; _DOARGS_3 (n-4)
264 #define _POPARGS_4      _POPARGS_3; popl %esi
265
266 #define PUSHARGS_5      _PUSHARGS_5
267 #define DOARGS_5        _DOARGS_5 (32)
268 #define POPARGS_5       _POPARGS_5
269 #define _PUSHARGS_5     pushl %edi; _PUSHARGS_4
270 #define _DOARGS_5(n)    movl n(%esp), %edi; _DOARGS_4 (n-4)
271 #define _POPARGS_5      _POPARGS_4; popl %edi
272
273 #else   /* !__ASSEMBLER__ */
274
275 /* We need some help from the assembler to generate optimal code.  We
276    define some macros here which later will be used.  */
277 asm (".L__X'%ebx = 1\n\t"
278      ".L__X'%ecx = 2\n\t"
279      ".L__X'%edx = 2\n\t"
280      ".L__X'%eax = 3\n\t"
281      ".L__X'%esi = 3\n\t"
282      ".L__X'%edi = 3\n\t"
283      ".L__X'%ebp = 3\n\t"
284      ".L__X'%esp = 3\n\t"
285      ".macro bpushl name reg\n\t"
286      ".if 1 - \\name\n\t"
287      ".if 2 - \\name\n\t"
288      "pushl %ebx\n\t"
289      ".else\n\t"
290      "xchgl \\reg, %ebx\n\t"
291      ".endif\n\t"
292      ".endif\n\t"
293      ".endm\n\t"
294      ".macro bpopl name reg\n\t"
295      ".if 1 - \\name\n\t"
296      ".if 2 - \\name\n\t"
297      "popl %ebx\n\t"
298      ".else\n\t"
299      "xchgl \\reg, %ebx\n\t"
300      ".endif\n\t"
301      ".endif\n\t"
302      ".endm\n\t"
303      ".macro bmovl name reg\n\t"
304      ".if 1 - \\name\n\t"
305      ".if 2 - \\name\n\t"
306      "movl \\reg, %ebx\n\t"
307      ".endif\n\t"
308      ".endif\n\t"
309      ".endm\n\t");
310
311 /* Define a macro which expands inline into the wrapper code for a system
312    call.  */
313 #undef INLINE_SYSCALL
314 #define INLINE_SYSCALL(name, nr, args...) \
315   ({                                                                          \
316     unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);             \
317     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))         \
318       {                                                                       \
319         __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));                   \
320         resultvar = 0xffffffff;                                               \
321       }                                                                       \
322     (int) resultvar; })
323
324 /* Define a macro which expands inline into the wrapper code for a system
325    call.  This use is for internal calls that do not need to handle errors
326    normally.  It will never touch errno.  This returns just what the kernel
327    gave back.  */
328 #undef INTERNAL_SYSCALL
329 #ifdef I386_USE_SYSENTER
330 # ifdef SHARED
331 #  define INTERNAL_SYSCALL(name, err, nr, args...) \
332   ({                                                                          \
333     unsigned int resultvar;                                                   \
334     asm volatile (                                                            \
335     LOADARGS_##nr                                                             \
336     "movl %1, %%eax\n\t"                                                      \
337     "call *%%gs:%P2\n\t"                                                      \
338     RESTOREARGS_##nr                                                          \
339     : "=a" (resultvar)                                                        \
340     : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))                  \
341       ASMFMT_##nr(args) : "memory", "cc");                                    \
342     (int) resultvar; })
343 # else
344 #  define INTERNAL_SYSCALL(name, err, nr, args...) \
345   ({                                                                          \
346     unsigned int resultvar;                                                   \
347     asm volatile (                                                            \
348     LOADARGS_##nr                                                             \
349     "movl %1, %%eax\n\t"                                                      \
350     "call *_dl_sysinfo\n\t"                                                   \
351     RESTOREARGS_##nr                                                          \
352     : "=a" (resultvar)                                                        \
353     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                  \
354     (int) resultvar; })
355 # endif
356 #else
357 # define INTERNAL_SYSCALL(name, err, nr, args...) \
358   ({                                                                          \
359     unsigned int resultvar;                                                   \
360     asm volatile (                                                            \
361     LOADARGS_##nr                                                             \
362     "movl %1, %%eax\n\t"                                                      \
363     "int $0x80\n\t"                                                   \
364     RESTOREARGS_##nr                                                          \
365     : "=a" (resultvar)                                                        \
366     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                  \
367     (int) resultvar; })
368 #endif
369
370 #undef INTERNAL_SYSCALL_DECL
371 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
372
373 #undef INTERNAL_SYSCALL_ERROR_P
374 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
375   ((unsigned int) (val) >= 0xfffff001u)
376
377 #undef INTERNAL_SYSCALL_ERRNO
378 #define INTERNAL_SYSCALL_ERRNO(val, err)        (-(val))
379
380 #define LOADARGS_0
381 #if defined I386_USE_SYSENTER && defined SHARED
382 # define LOADARGS_1 \
383     "bpushl .L__X'%k3, %k3\n\t"                                               \
384     "bmovl .L__X'%k3, %k3\n\t"
385 #else
386 # define LOADARGS_1 \
387     "bpushl .L__X'%k2, %k2\n\t"                                               \
388     "bmovl .L__X'%k2, %k2\n\t"
389 #endif
390 #define LOADARGS_2      LOADARGS_1
391 #define LOADARGS_3      LOADARGS_1
392 #define LOADARGS_4      LOADARGS_1
393 #define LOADARGS_5      LOADARGS_1
394
395 #define RESTOREARGS_0
396 #if defined I386_USE_SYSENTER && defined SHARED
397 # define RESTOREARGS_1 \
398     "bpopl .L__X'%k3, %k3\n\t"
399 #else
400 # define RESTOREARGS_1 \
401     "bpopl .L__X'%k2, %k2\n\t"
402 #endif
403 #define RESTOREARGS_2   RESTOREARGS_1
404 #define RESTOREARGS_3   RESTOREARGS_1
405 #define RESTOREARGS_4   RESTOREARGS_1
406 #define RESTOREARGS_5   RESTOREARGS_1
407
408 #define ASMFMT_0()
409 #define ASMFMT_1(arg1) \
410         , "acdSD" (arg1)
411 #define ASMFMT_2(arg1, arg2) \
412         , "adSD" (arg1), "c" (arg2)
413 #define ASMFMT_3(arg1, arg2, arg3) \
414         , "aSD" (arg1), "c" (arg2), "d" (arg3)
415 #define ASMFMT_4(arg1, arg2, arg3, arg4) \
416         , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
417 #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
418         , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
419
420 #endif  /* __ASSEMBLER__ */
421
422 #endif /* linux/i386/sysdep.h */