Back to index

glibc  2.9
sysdep.h
Go to the documentation of this file.
00001 /* Copyright (C) 1992,1993,1995-2000,2002-2006,2007
00002        Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #ifndef _LINUX_I386_SYSDEP_H
00022 #define _LINUX_I386_SYSDEP_H 1
00023 
00024 /* There is some commonality.  */
00025 #include <sysdeps/unix/i386/sysdep.h>
00026 #include <bp-sym.h>
00027 #include <bp-asm.h>
00028 /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO.  */
00029 #include <dl-sysdep.h>
00030 #include <tls.h>
00031 
00032 
00033 /* For Linux we can use the system call table in the header file
00034        /usr/include/asm/unistd.h
00035    of the kernel.  But these symbols do not follow the SYS_* syntax
00036    so we have to redefine the `SYS_ify' macro here.  */
00037 #undef SYS_ify
00038 #define SYS_ify(syscall_name)      __NR_##syscall_name
00039 
00040 #if defined USE_DL_SYSINFO \
00041     && (!defined NOT_IN_libc || defined IS_IN_libpthread)
00042 # define I386_USE_SYSENTER  1
00043 #else
00044 # undef I386_USE_SYSENTER
00045 #endif
00046 
00047 #ifdef __ASSEMBLER__
00048 
00049 /* Linux uses a negative return value to indicate syscall errors,
00050    unlike most Unices, which use the condition codes' carry flag.
00051 
00052    Since version 2.1 the return value of a system call might be
00053    negative even if the call succeeded.  E.g., the `lseek' system call
00054    might return a large offset.  Therefore we must not anymore test
00055    for < 0, but test for a real error by making sure the value in %eax
00056    is a real error number.  Linus said he will make sure the no syscall
00057    returns a value in -1 .. -4095 as a valid result so we can savely
00058    test with -4095.  */
00059 
00060 /* We don't want the label for the error handle to be global when we define
00061    it here.  */
00062 #ifdef PIC
00063 # define SYSCALL_ERROR_LABEL 0f
00064 #else
00065 # define SYSCALL_ERROR_LABEL syscall_error
00066 #endif
00067 
00068 #undef PSEUDO
00069 #define       PSEUDO(name, syscall_name, args)                              \
00070   .text;                                                             \
00071   ENTRY (name)                                                              \
00072     DO_CALL (syscall_name, args);                                    \
00073     cmpl $-4095, %eax;                                                      \
00074     jae SYSCALL_ERROR_LABEL;                                                \
00075   L(pseudo_end):
00076 
00077 #undef PSEUDO_END
00078 #define       PSEUDO_END(name)                                              \
00079   SYSCALL_ERROR_HANDLER                                                     \
00080   END (name)
00081 
00082 #undef PSEUDO_NOERRNO
00083 #define       PSEUDO_NOERRNO(name, syscall_name, args)                      \
00084   .text;                                                             \
00085   ENTRY (name)                                                              \
00086     DO_CALL (syscall_name, args)
00087 
00088 #undef PSEUDO_END_NOERRNO
00089 #define       PSEUDO_END_NOERRNO(name)                                      \
00090   END (name)
00091 
00092 #define ret_NOERRNO ret
00093 
00094 /* The function has to return the error code.  */
00095 #undef PSEUDO_ERRVAL
00096 #define       PSEUDO_ERRVAL(name, syscall_name, args) \
00097   .text;                                                             \
00098   ENTRY (name)                                                              \
00099     DO_CALL (syscall_name, args);                                    \
00100     negl %eax
00101 
00102 #undef PSEUDO_END_ERRVAL
00103 #define       PSEUDO_END_ERRVAL(name) \
00104   END (name)
00105 
00106 #define ret_ERRVAL ret
00107 
00108 #ifndef PIC
00109 # define SYSCALL_ERROR_HANDLER     /* Nothing here; code in sysdep.S is used.  */
00110 #else
00111 
00112 # if RTLD_PRIVATE_ERRNO
00113 #  define SYSCALL_ERROR_HANDLER                                             \
00114 0:SETUP_PIC_REG(cx);                                                 \
00115   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                        \
00116   xorl %edx, %edx;                                                   \
00117   subl %eax, %edx;                                                   \
00118   movl %edx, rtld_errno@GOTOFF(%ecx);                                       \
00119   orl $-1, %eax;                                                     \
00120   jmp L(pseudo_end);
00121 
00122 # elif defined _LIBC_REENTRANT
00123 
00124 #  if USE___THREAD
00125 #   ifndef NOT_IN_libc
00126 #    define SYSCALL_ERROR_ERRNO __libc_errno
00127 #   else
00128 #    define SYSCALL_ERROR_ERRNO errno
00129 #   endif
00130 #   define SYSCALL_ERROR_HANDLER                                     \
00131 0:SETUP_PIC_REG (cx);                                                       \
00132   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                        \
00133   movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx;                           \
00134   xorl %edx, %edx;                                                   \
00135   subl %eax, %edx;                                                   \
00136   SYSCALL_ERROR_HANDLER_TLS_STORE (%edx, %ecx);                             \
00137   orl $-1, %eax;                                                     \
00138   jmp L(pseudo_end);
00139 #   ifndef NO_TLS_DIRECT_SEG_REFS
00140 #    define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)                   \
00141   movl src, %gs:(destoff)
00142 #   else
00143 #    define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)                   \
00144   addl %gs:0, destoff;                                                      \
00145   movl src, (destoff)
00146 #   endif
00147 #  else
00148 #   define SYSCALL_ERROR_HANDLER                                     \
00149 0:pushl %ebx;                                                        \
00150   cfi_adjust_cfa_offset (4);                                                \
00151   cfi_rel_offset (ebx, 0);                                           \
00152   SETUP_PIC_REG (bx);                                                       \
00153   addl $_GLOBAL_OFFSET_TABLE_, %ebx;                                        \
00154   xorl %edx, %edx;                                                   \
00155   subl %eax, %edx;                                                   \
00156   pushl %edx;                                                        \
00157   cfi_adjust_cfa_offset (4);                                                \
00158   PUSH_ERRNO_LOCATION_RETURN;                                               \
00159   call BP_SYM (__errno_location)@PLT;                                       \
00160   POP_ERRNO_LOCATION_RETURN;                                                \
00161   popl %ecx;                                                         \
00162   cfi_adjust_cfa_offset (-4);                                               \
00163   popl %ebx;                                                         \
00164   cfi_adjust_cfa_offset (-4);                                               \
00165   cfi_restore (ebx);                                                 \
00166   movl %ecx, (%eax);                                                 \
00167   orl $-1, %eax;                                                     \
00168   jmp L(pseudo_end);
00169 /* A quick note: it is assumed that the call to `__errno_location' does
00170    not modify the stack!  */
00171 #  endif
00172 # else
00173 /* Store (- %eax) into errno through the GOT.  */
00174 #  define SYSCALL_ERROR_HANDLER                                             \
00175 0:SETUP_PIC_REG(cx);                                                 \
00176   addl $_GLOBAL_OFFSET_TABLE_, %ecx;                                        \
00177   xorl %edx, %edx;                                                   \
00178   subl %eax, %edx;                                                   \
00179   movl errno@GOT(%ecx), %ecx;                                               \
00180   movl %edx, (%ecx);                                                 \
00181   orl $-1, %eax;                                                     \
00182   jmp L(pseudo_end);
00183 # endif       /* _LIBC_REENTRANT */
00184 #endif /* PIC */
00185 
00186 
00187 /* The original calling convention for system calls on Linux/i386 is
00188    to use int $0x80.  */
00189 #ifdef I386_USE_SYSENTER
00190 # ifdef SHARED
00191 #  define ENTER_KERNEL call *%gs:SYSINFO_OFFSET
00192 # else
00193 #  define ENTER_KERNEL call *_dl_sysinfo
00194 # endif
00195 #else
00196 # define ENTER_KERNEL int $0x80
00197 #endif
00198 
00199 /* Linux takes system call arguments in registers:
00200 
00201        syscall number       %eax        call-clobbered
00202        arg 1         %ebx        call-saved
00203        arg 2         %ecx        call-clobbered
00204        arg 3         %edx        call-clobbered
00205        arg 4         %esi        call-saved
00206        arg 5         %edi        call-saved
00207 
00208    The stack layout upon entering the function is:
00209 
00210        20(%esp)      Arg# 5
00211        16(%esp)      Arg# 4
00212        12(%esp)      Arg# 3
00213         8(%esp)      Arg# 2
00214         4(%esp)      Arg# 1
00215          (%esp)      Return address
00216 
00217    (Of course a function with say 3 arguments does not have entries for
00218    arguments 4 and 5.)
00219 
00220    The following code tries hard to be optimal.  A general assumption
00221    (which is true according to the data books I have) is that
00222 
00223        2 * xchg      is more expensive than      pushl + movl + popl
00224 
00225    Beside this a neat trick is used.  The calling conventions for Linux
00226    tell that among the registers used for parameters %ecx and %edx need
00227    not be saved.  Beside this we may clobber this registers even when
00228    they are not used for parameter passing.
00229 
00230    As a result one can see below that we save the content of the %ebx
00231    register in the %edx register when we have less than 3 arguments
00232    (2 * movl is less expensive than pushl + popl).
00233 
00234    Second unlike for the other registers we don't save the content of
00235    %ecx and %edx when we have more than 1 and 2 registers resp.
00236 
00237    The code below might look a bit long but we have to take care for
00238    the pipelined processors (i586).  Here the `pushl' and `popl'
00239    instructions are marked as NP (not pairable) but the exception is
00240    two consecutive of these instruction.  This gives no penalty on
00241    other processors though.  */
00242 
00243 #undef DO_CALL
00244 #define DO_CALL(syscall_name, args)                                         \
00245     PUSHARGS_##args                                                  \
00246     DOARGS_##args                                                    \
00247     movl $SYS_ify (syscall_name), %eax;                                     \
00248     ENTER_KERNEL                                                     \
00249     POPARGS_##args
00250 
00251 #define PUSHARGS_0   /* No arguments to push.  */
00252 #define       DOARGS_0      /* No arguments to frob.  */
00253 #define       POPARGS_0     /* No arguments to pop.  */
00254 #define       _PUSHARGS_0   /* No arguments to push.  */
00255 #define _DOARGS_0(n) /* No arguments to frob.  */
00256 #define       _POPARGS_0    /* No arguments to pop.  */
00257 
00258 #define PUSHARGS_1   movl %ebx, %edx; L(SAVEBX1): PUSHARGS_0
00259 #define       DOARGS_1      _DOARGS_1 (4)
00260 #define       POPARGS_1     POPARGS_0; movl %edx, %ebx; L(RESTBX1):
00261 #define       _PUSHARGS_1   pushl %ebx; cfi_adjust_cfa_offset (4); \
00262                      cfi_rel_offset (ebx, 0); L(PUSHBX1): _PUSHARGS_0
00263 #define _DOARGS_1(n) movl n(%esp), %ebx; _DOARGS_0(n-4)
00264 #define       _POPARGS_1    _POPARGS_0; popl %ebx; cfi_adjust_cfa_offset (-4); \
00265                      cfi_restore (ebx); L(POPBX1):
00266 
00267 #define PUSHARGS_2   PUSHARGS_1
00268 #define       DOARGS_2      _DOARGS_2 (8)
00269 #define       POPARGS_2     POPARGS_1
00270 #define _PUSHARGS_2  _PUSHARGS_1
00271 #define       _DOARGS_2(n)  movl n(%esp), %ecx; _DOARGS_1 (n-4)
00272 #define       _POPARGS_2    _POPARGS_1
00273 
00274 #define PUSHARGS_3   _PUSHARGS_2
00275 #define DOARGS_3     _DOARGS_3 (16)
00276 #define POPARGS_3    _POPARGS_3
00277 #define _PUSHARGS_3  _PUSHARGS_2
00278 #define _DOARGS_3(n) movl n(%esp), %edx; _DOARGS_2 (n-4)
00279 #define _POPARGS_3   _POPARGS_2
00280 
00281 #define PUSHARGS_4   _PUSHARGS_4
00282 #define DOARGS_4     _DOARGS_4 (24)
00283 #define POPARGS_4    _POPARGS_4
00284 #define _PUSHARGS_4  pushl %esi; cfi_adjust_cfa_offset (4); \
00285                      cfi_rel_offset (esi, 0); L(PUSHSI1): _PUSHARGS_3
00286 #define _DOARGS_4(n) movl n(%esp), %esi; _DOARGS_3 (n-4)
00287 #define _POPARGS_4   _POPARGS_3; popl %esi; cfi_adjust_cfa_offset (-4); \
00288                      cfi_restore (esi); L(POPSI1):
00289 
00290 #define PUSHARGS_5   _PUSHARGS_5
00291 #define DOARGS_5     _DOARGS_5 (32)
00292 #define POPARGS_5    _POPARGS_5
00293 #define _PUSHARGS_5  pushl %edi; cfi_adjust_cfa_offset (4); \
00294                      cfi_rel_offset (edi, 0); L(PUSHDI1): _PUSHARGS_4
00295 #define _DOARGS_5(n) movl n(%esp), %edi; _DOARGS_4 (n-4)
00296 #define _POPARGS_5   _POPARGS_4; popl %edi; cfi_adjust_cfa_offset (-4); \
00297                      cfi_restore (edi); L(POPDI1):
00298 
00299 #define PUSHARGS_6   _PUSHARGS_6
00300 #define DOARGS_6     _DOARGS_6 (40)
00301 #define POPARGS_6    _POPARGS_6
00302 #define _PUSHARGS_6  pushl %ebp; cfi_adjust_cfa_offset (4); \
00303                      cfi_rel_offset (ebp, 0); L(PUSHBP1): _PUSHARGS_5
00304 #define _DOARGS_6(n) movl n(%esp), %ebp; _DOARGS_5 (n-4)
00305 #define _POPARGS_6   _POPARGS_5; popl %ebp; cfi_adjust_cfa_offset (-4); \
00306                      cfi_restore (ebp); L(POPBP1):
00307 
00308 #else  /* !__ASSEMBLER__ */
00309 
00310 /* We need some help from the assembler to generate optimal code.  We
00311    define some macros here which later will be used.  */
00312 asm (".L__X'%ebx = 1\n\t"
00313      ".L__X'%ecx = 2\n\t"
00314      ".L__X'%edx = 2\n\t"
00315      ".L__X'%eax = 3\n\t"
00316      ".L__X'%esi = 3\n\t"
00317      ".L__X'%edi = 3\n\t"
00318      ".L__X'%ebp = 3\n\t"
00319      ".L__X'%esp = 3\n\t"
00320      ".macro bpushl name reg\n\t"
00321      ".if 1 - \\name\n\t"
00322      ".if 2 - \\name\n\t"
00323      "error\n\t"
00324      ".else\n\t"
00325      "xchgl \\reg, %ebx\n\t"
00326      ".endif\n\t"
00327      ".endif\n\t"
00328      ".endm\n\t"
00329      ".macro bpopl name reg\n\t"
00330      ".if 1 - \\name\n\t"
00331      ".if 2 - \\name\n\t"
00332      "error\n\t"
00333      ".else\n\t"
00334      "xchgl \\reg, %ebx\n\t"
00335      ".endif\n\t"
00336      ".endif\n\t"
00337      ".endm\n\t");
00338 
00339 /* Define a macro which expands inline into the wrapper code for a system
00340    call.  */
00341 #undef INLINE_SYSCALL
00342 #define INLINE_SYSCALL(name, nr, args...) \
00343   ({                                                                 \
00344     unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);           \
00345     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))       \
00346       {                                                                     \
00347        __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));                  \
00348        resultvar = 0xffffffff;                                              \
00349       }                                                                     \
00350     (int) resultvar; })
00351 
00352 /* Define a macro which expands inline into the wrapper code for a system
00353    call.  This use is for internal calls that do not need to handle errors
00354    normally.  It will never touch errno.  This returns just what the kernel
00355    gave back.
00356 
00357    The _NCS variant allows non-constant syscall numbers but it is not
00358    possible to use more than four parameters.  */
00359 #undef INTERNAL_SYSCALL
00360 #ifdef I386_USE_SYSENTER
00361 # ifdef SHARED
00362 #  define INTERNAL_SYSCALL(name, err, nr, args...) \
00363   ({                                                                 \
00364     register unsigned int resultvar;                                        \
00365     EXTRAVAR_##nr                                                    \
00366     asm volatile (                                                   \
00367     LOADARGS_##nr                                                    \
00368     "movl %1, %%eax\n\t"                                             \
00369     "call *%%gs:%P2\n\t"                                             \
00370     RESTOREARGS_##nr                                                 \
00371     : "=a" (resultvar)                                                      \
00372     : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))                \
00373       ASMFMT_##nr(args) : "memory", "cc");                                  \
00374     (int) resultvar; })
00375 #  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
00376   ({                                                                 \
00377     register unsigned int resultvar;                                        \
00378     EXTRAVAR_##nr                                                    \
00379     asm volatile (                                                   \
00380     LOADARGS_##nr                                                    \
00381     "call *%%gs:%P2\n\t"                                             \
00382     RESTOREARGS_##nr                                                 \
00383     : "=a" (resultvar)                                                      \
00384     : "0" (name), "i" (offsetof (tcbhead_t, sysinfo))                       \
00385       ASMFMT_##nr(args) : "memory", "cc");                                  \
00386     (int) resultvar; })
00387 # else
00388 #  define INTERNAL_SYSCALL(name, err, nr, args...) \
00389   ({                                                                 \
00390     register unsigned int resultvar;                                        \
00391     EXTRAVAR_##nr                                                    \
00392     asm volatile (                                                   \
00393     LOADARGS_##nr                                                    \
00394     "movl %1, %%eax\n\t"                                             \
00395     "call *_dl_sysinfo\n\t"                                          \
00396     RESTOREARGS_##nr                                                 \
00397     : "=a" (resultvar)                                                      \
00398     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                \
00399     (int) resultvar; })
00400 #  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
00401   ({                                                                 \
00402     register unsigned int resultvar;                                        \
00403     EXTRAVAR_##nr                                                    \
00404     asm volatile (                                                   \
00405     LOADARGS_##nr                                                    \
00406     "call *_dl_sysinfo\n\t"                                          \
00407     RESTOREARGS_##nr                                                 \
00408     : "=a" (resultvar)                                                      \
00409     : "0" (name) ASMFMT_##nr(args) : "memory", "cc");                       \
00410     (int) resultvar; })
00411 # endif
00412 #else
00413 # define INTERNAL_SYSCALL(name, err, nr, args...) \
00414   ({                                                                 \
00415     register unsigned int resultvar;                                        \
00416     EXTRAVAR_##nr                                                    \
00417     asm volatile (                                                   \
00418     LOADARGS_##nr                                                    \
00419     "movl %1, %%eax\n\t"                                             \
00420     "int $0x80\n\t"                                                  \
00421     RESTOREARGS_##nr                                                 \
00422     : "=a" (resultvar)                                                      \
00423     : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                \
00424     (int) resultvar; })
00425 # define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
00426   ({                                                                 \
00427     register unsigned int resultvar;                                        \
00428     EXTRAVAR_##nr                                                    \
00429     asm volatile (                                                   \
00430     LOADARGS_##nr                                                    \
00431     "int $0x80\n\t"                                                  \
00432     RESTOREARGS_##nr                                                 \
00433     : "=a" (resultvar)                                                      \
00434     : "0" (name) ASMFMT_##nr(args) : "memory", "cc");                       \
00435     (int) resultvar; })
00436 #endif
00437 
00438 #undef INTERNAL_SYSCALL_DECL
00439 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
00440 
00441 #undef INTERNAL_SYSCALL_ERROR_P
00442 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
00443   ((unsigned int) (val) >= 0xfffff001u)
00444 
00445 #undef INTERNAL_SYSCALL_ERRNO
00446 #define INTERNAL_SYSCALL_ERRNO(val, err)  (-(val))
00447 
00448 #define LOADARGS_0
00449 #ifdef __PIC__
00450 # if defined I386_USE_SYSENTER && defined SHARED
00451 #  define LOADARGS_1 \
00452     "bpushl .L__X'%k3, %k3\n\t"
00453 #  define LOADARGS_5 \
00454     "movl %%ebx, %4\n\t"                                             \
00455     "movl %3, %%ebx\n\t"
00456 # else
00457 #  define LOADARGS_1 \
00458     "bpushl .L__X'%k2, %k2\n\t"
00459 #  define LOADARGS_5 \
00460     "movl %%ebx, %3\n\t"                                             \
00461     "movl %2, %%ebx\n\t"
00462 # endif
00463 # define LOADARGS_2  LOADARGS_1
00464 # define LOADARGS_3 \
00465     "xchgl %%ebx, %%edi\n\t"
00466 # define LOADARGS_4  LOADARGS_3
00467 #else
00468 # define LOADARGS_1
00469 # define LOADARGS_2
00470 # define LOADARGS_3
00471 # define LOADARGS_4
00472 # define LOADARGS_5
00473 #endif
00474 
00475 #define RESTOREARGS_0
00476 #ifdef __PIC__
00477 # if defined I386_USE_SYSENTER && defined SHARED
00478 #  define RESTOREARGS_1 \
00479     "bpopl .L__X'%k3, %k3\n\t"
00480 #  define RESTOREARGS_5 \
00481     "movl %4, %%ebx"
00482 # else
00483 #  define RESTOREARGS_1 \
00484     "bpopl .L__X'%k2, %k2\n\t"
00485 #  define RESTOREARGS_5 \
00486     "movl %3, %%ebx"
00487 # endif
00488 # define RESTOREARGS_2      RESTOREARGS_1
00489 # define RESTOREARGS_3 \
00490     "xchgl %%edi, %%ebx\n\t"
00491 # define RESTOREARGS_4      RESTOREARGS_3
00492 #else
00493 # define RESTOREARGS_1
00494 # define RESTOREARGS_2
00495 # define RESTOREARGS_3
00496 # define RESTOREARGS_4
00497 # define RESTOREARGS_5
00498 #endif
00499 
00500 #define ASMFMT_0()
00501 #ifdef __PIC__
00502 # define ASMFMT_1(arg1) \
00503        , "cd" (arg1)
00504 # define ASMFMT_2(arg1, arg2) \
00505        , "d" (arg1), "c" (arg2)
00506 # define ASMFMT_3(arg1, arg2, arg3) \
00507        , "D" (arg1), "c" (arg2), "d" (arg3)
00508 # define ASMFMT_4(arg1, arg2, arg3, arg4) \
00509        , "D" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
00510 # define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
00511        , "0" (arg1), "m" (_xv), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
00512 #else
00513 # define ASMFMT_1(arg1) \
00514        , "b" (arg1)
00515 # define ASMFMT_2(arg1, arg2) \
00516        , "b" (arg1), "c" (arg2)
00517 # define ASMFMT_3(arg1, arg2, arg3) \
00518        , "b" (arg1), "c" (arg2), "d" (arg3)
00519 # define ASMFMT_4(arg1, arg2, arg3, arg4) \
00520        , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
00521 # define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
00522        , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
00523 #endif
00524 
00525 #define EXTRAVAR_0
00526 #define EXTRAVAR_1
00527 #define EXTRAVAR_2
00528 #define EXTRAVAR_3
00529 #define EXTRAVAR_4
00530 #ifdef __PIC__
00531 # define EXTRAVAR_5 int _xv;
00532 #else
00533 # define EXTRAVAR_5
00534 #endif
00535 
00536 /* Consistency check for position-independent code.  */
00537 #ifdef __PIC__
00538 # define check_consistency()                                                \
00539   ({ int __res;                                                             \
00540      __asm__ __volatile__                                            \
00541        ("call __i686.get_pc_thunk.cx;"                                      \
00542        "addl $_GLOBAL_OFFSET_TABLE_, %%ecx;"                                \
00543        "subl %%ebx, %%ecx;"                                          \
00544        "je 1f;"                                                      \
00545        "ud2;"                                                        \
00546        "1:\n"                                                        \
00547        ".section .gnu.linkonce.t.__i686.get_pc_thunk.cx,\"ax\",@progbits;"   \
00548        ".globl __i686.get_pc_thunk.cx;"                              \
00549        ".hidden __i686.get_pc_thunk.cx;"                             \
00550        ".type __i686.get_pc_thunk.cx,@function;"                     \
00551        "__i686.get_pc_thunk.cx:"                                     \
00552        "movl (%%esp), %%ecx;"                                               \
00553        "ret;"                                                        \
00554        ".previous"                                                   \
00555        : "=c" (__res));                                              \
00556      __res; })
00557 #endif
00558 
00559 #endif /* __ASSEMBLER__ */
00560 
00561 
00562 /* Pointer mangling support.  */
00563 #if defined NOT_IN_libc && defined IS_IN_rtld
00564 /* We cannot use the thread descriptor because in ld.so we use setjmp
00565    earlier than the descriptor is initialized.  Using a global variable
00566    is too complicated here since we have no PC-relative addressing mode.  */
00567 #else
00568 # ifdef __ASSEMBLER__
00569 #  define PTR_MANGLE(reg)   xorl %gs:POINTER_GUARD, reg;                    \
00570                             roll $9, reg
00571 #  define PTR_DEMANGLE(reg) rorl $9, reg;                            \
00572                             xorl %gs:POINTER_GUARD, reg
00573 # else
00574 #  define PTR_MANGLE(var)   asm ("xorl %%gs:%c2, %0\n"               \
00575                                  "roll $9, %0"                       \
00576                                  : "=r" (var)                        \
00577                                  : "0" (var),                        \
00578                                    "i" (offsetof (tcbhead_t,         \
00579                                                 pointer_guard)))
00580 #  define PTR_DEMANGLE(var) asm ("rorl $9, %0\n"                     \
00581                                  "xorl %%gs:%c2, %0"                 \
00582                                  : "=r" (var)                        \
00583                                  : "0" (var),                        \
00584                                    "i" (offsetof (tcbhead_t,         \
00585                                                 pointer_guard)))
00586 # endif
00587 #endif
00588 
00589 #endif /* linux/i386/sysdep.h */