Back to index

glibc  2.9
sysdep.h
Go to the documentation of this file.
00001 /* Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Written by Jes Sorensen, <Jes.Sorensen@cern.ch>, April 1999.
00005    Based on code originally written by David Mosberger-Tang
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #ifndef _LINUX_IA64_SYSDEP_H
00023 #define _LINUX_IA64_SYSDEP_H 1
00024 
00025 #include <sysdeps/unix/sysdep.h>
00026 #include <sysdeps/ia64/sysdep.h>
00027 #include <dl-sysdep.h>
00028 #include <tls.h>
00029 
00030 /* As of GAS v2.4.90.0.7, including a ".align" directive inside a
00031    function will cause bad unwind info to be emitted (GAS doesn't know
00032    how to account for the padding introduced by the .align directive).
00033    Turning on this macro will work around this bug by introducing the
00034    necessary padding explicitly. */
00035 #define GAS_ALIGN_BREAKS_UNWIND_INFO
00036 
00037 /* For Linux we can use the system call table in the header file
00038        /usr/include/asm/unistd.h
00039    of the kernel.  But these symbols do not follow the SYS_* syntax
00040    so we have to redefine the `SYS_ify' macro here.  */
00041 #undef SYS_ify
00042 #ifdef __STDC__
00043 # define SYS_ify(syscall_name)     __NR_##syscall_name
00044 #else
00045 # define SYS_ify(syscall_name)     __NR_syscall_name
00046 #endif
00047 
00048 /* This is a kludge to make syscalls.list find these under the names
00049    pread and pwrite, since some kernel headers define those names
00050    and some define the *64 names for the same system calls.  */
00051 #if !defined __NR_pread && defined __NR_pread64
00052 # define __NR_pread __NR_pread64
00053 #endif
00054 #if !defined __NR_pwrite && defined __NR_pwrite64
00055 # define __NR_pwrite __NR_pwrite64
00056 #endif
00057 
00058 /* This is to help the old kernel headers where __NR_semtimedop is not
00059    available.  */
00060 #ifndef __NR_semtimedop
00061 # define __NR_semtimedop 1247
00062 #endif
00063 
00064 #if defined USE_DL_SYSINFO \
00065        && (!defined NOT_IN_libc \
00066            || defined IS_IN_libpthread || defined IS_IN_librt)
00067 # define IA64_USE_NEW_STUB
00068 #else
00069 # undef IA64_USE_NEW_STUB
00070 #endif
00071 
00072 #ifdef __ASSEMBLER__
00073 
00074 #undef CALL_MCOUNT
00075 #ifdef PROF
00076 # define CALL_MCOUNT                                           \
00077        .data;                                                  \
00078 1:     data8 0;      /* XXX fixme: use .xdata8 once labels work */    \
00079        .previous;                                              \
00080        .prologue;                                              \
00081        .save ar.pfs, r40;                                      \
00082        alloc out0 = ar.pfs, 8, 0, 4, 0;                        \
00083        mov out1 = gp;                                                 \
00084        .save rp, out2;                                                \
00085        mov out2 = rp;                                                 \
00086        .body;                                                  \
00087        ;;                                                      \
00088        addl out3 = @ltoff(1b), gp;                             \
00089        br.call.sptk.many rp = _mcount                                 \
00090        ;;
00091 #else
00092 # define CALL_MCOUNT /* Do nothing. */
00093 #endif
00094 
00095 /* Linux uses a negative return value to indicate syscall errors, unlike
00096    most Unices, which use the condition codes' carry flag.
00097 
00098    Since version 2.1 the return value of a system call might be negative
00099    even if the call succeeded.  E.g., the `lseek' system call might return
00100    a large offset.  Therefore we must not anymore test for < 0, but test
00101    for a real error by making sure the value in %d0 is a real error
00102    number.  Linus said he will make sure the no syscall returns a value
00103    in -1 .. -4095 as a valid result so we can savely test with -4095.  */
00104 
00105 /* We don't want the label for the error handler to be visible in the symbol
00106    table when we define it here.  */
00107 #define SYSCALL_ERROR_LABEL __syscall_error
00108 
00109 #undef PSEUDO
00110 #define       PSEUDO(name, syscall_name, args)   \
00111   ENTRY(name)                             \
00112     DO_CALL (SYS_ify(syscall_name));             \
00113        cmp.eq p6,p0=-1,r10;               \
00114 (p6)   br.cond.spnt.few __syscall_error;
00115 
00116 #define DO_CALL_VIA_BREAK(num)                   \
00117        mov r15=num;                       \
00118        break __BREAK_SYSCALL
00119 
00120 #ifdef IA64_USE_NEW_STUB
00121 # ifdef SHARED
00122 #  define DO_CALL(num)                           \
00123        .prologue;                         \
00124        adds r2 = SYSINFO_OFFSET, r13;;           \
00125        ld8 r2 = [r2];                            \
00126        .save ar.pfs, r11;                 \
00127        mov r11 = ar.pfs;;                 \
00128        .body;                             \
00129        mov r15 = num;                            \
00130        mov b7 = r2;                       \
00131        br.call.sptk.many b6 = b7;;        \
00132        .restore sp;                       \
00133        mov ar.pfs = r11;                  \
00134        .prologue;                         \
00135        .body
00136 # else /* !SHARED */
00137 #  define DO_CALL(num)                           \
00138        .prologue;                         \
00139        mov r15 = num;                            \
00140        movl r2 = _dl_sysinfo;;                   \
00141        ld8 r2 = [r2];                            \
00142        .save ar.pfs, r11;                 \
00143        mov r11 = ar.pfs;;                 \
00144        .body;                             \
00145        mov b7 = r2;                       \
00146        br.call.sptk.many b6 = b7;;        \
00147        .restore sp;                       \
00148        mov ar.pfs = r11;                  \
00149        .prologue;                         \
00150        .body
00151 # endif
00152 #else
00153 # define DO_CALL(num)                            DO_CALL_VIA_BREAK(num)
00154 #endif
00155 
00156 #undef PSEUDO_END
00157 #define PSEUDO_END(name)    .endp C_SYMBOL_NAME(name);
00158 
00159 #undef PSEUDO_NOERRNO
00160 #define       PSEUDO_NOERRNO(name, syscall_name, args)  \
00161   ENTRY(name)                                    \
00162     DO_CALL (SYS_ify(syscall_name));
00163 
00164 #undef PSEUDO_END_NOERRNO
00165 #define PSEUDO_END_NOERRNO(name)   .endp C_SYMBOL_NAME(name);
00166 
00167 #undef PSEUDO_ERRVAL
00168 #define       PSEUDO_ERRVAL(name, syscall_name, args)   \
00169   ENTRY(name)                             \
00170     DO_CALL (SYS_ify(syscall_name));             \
00171        cmp.eq p6,p0=-1,r10;               \
00172 (p6)   mov r10=r8;
00173 
00174 
00175 #undef PSEUDO_END_ERRVAL
00176 #define PSEUDO_END_ERRVAL(name)    .endp C_SYMBOL_NAME(name);
00177 
00178 #undef END
00179 #define END(name)                                       \
00180        .size  C_SYMBOL_NAME(name), . - C_SYMBOL_NAME(name) ;   \
00181        .endp  C_SYMBOL_NAME(name)
00182 
00183 #define ret                 br.ret.sptk.few b0
00184 #define ret_NOERRNO         ret
00185 #define ret_ERRVAL          ret
00186 
00187 #else /* not __ASSEMBLER__ */
00188 
00189 #define BREAK_INSN_1(num) "break " #num ";;\n\t"
00190 #define BREAK_INSN(num) BREAK_INSN_1(num)
00191 
00192 /* On IA-64 we have stacked registers for passing arguments.  The
00193    "out" registers end up being the called function's "in"
00194    registers.
00195 
00196    Also, since we have plenty of registers we have two return values
00197    from a syscall.  r10 is set to -1 on error, whilst r8 contains the
00198    (non-negative) errno on error or the return value on success.
00199  */
00200 
00201 #ifdef IA64_USE_NEW_STUB
00202 
00203 # define DO_INLINE_SYSCALL_NCS(name, nr, args...)                           \
00204     LOAD_ARGS_##nr (args)                                            \
00205     register long _r8 __asm ("r8");                                         \
00206     register long _r10 __asm ("r10");                                       \
00207     register long _r15 __asm ("r15") = name;                                \
00208     register void *_b7 __asm ("b7") = ((tcbhead_t *)__thread_self)->__private;\
00209     long _retval;                                                    \
00210     LOAD_REGS_##nr                                                   \
00211     /*                                                               \
00212      * Don't specify any unwind info here.  We mark ar.pfs as               \
00213      * clobbered.  This will force the compiler to save ar.pfs              \
00214      * somewhere and emit appropriate unwind info for that save.            \
00215      */                                                                     \
00216     __asm __volatile ("br.call.sptk.many b6=%0;;\n"                         \
00217                     : "=b"(_b7), "=r" (_r8), "=r" (_r10), "=r" (_r15)       \
00218                      ASM_OUTARGS_##nr                                \
00219                     : "0" (_b7), "3" (_r15) ASM_ARGS_##nr                   \
00220                     : "memory", "ar.pfs" ASM_CLOBBERS_##nr);                \
00221     _retval = _r8;
00222 
00223 #else /* !IA64_USE_NEW_STUB */
00224 
00225 # define DO_INLINE_SYSCALL_NCS(name, nr, args...)              \
00226     LOAD_ARGS_##nr (args)                               \
00227     register long _r8 asm ("r8");                       \
00228     register long _r10 asm ("r10");                            \
00229     register long _r15 asm ("r15") = name;                     \
00230     long _retval;                                       \
00231     LOAD_REGS_##nr                                      \
00232     __asm __volatile (BREAK_INSN (__BREAK_SYSCALL)             \
00233                     : "=r" (_r8), "=r" (_r10), "=r" (_r15)     \
00234                      ASM_OUTARGS_##nr                   \
00235                     : "2" (_r15) ASM_ARGS_##nr          \
00236                     : "memory" ASM_CLOBBERS_##nr);             \
00237     _retval = _r8;
00238 
00239 #endif /* !IA64_USE_NEW_STUB */
00240 
00241 #define DO_INLINE_SYSCALL(name, nr, args...)     \
00242   DO_INLINE_SYSCALL_NCS (__NR_##name, nr, ##args)
00243 
00244 #undef INLINE_SYSCALL
00245 #define INLINE_SYSCALL(name, nr, args...)        \
00246   ({                                             \
00247     DO_INLINE_SYSCALL_NCS (__NR_##name, nr, args)       \
00248     if (_r10 == -1)                              \
00249       {                                                 \
00250        __set_errno (_retval);                           \
00251        _retval = -1;                             \
00252       }                                                 \
00253     _retval; })
00254 
00255 #undef INTERNAL_SYSCALL_DECL
00256 #define INTERNAL_SYSCALL_DECL(err) long int err
00257 
00258 #undef INTERNAL_SYSCALL
00259 #define INTERNAL_SYSCALL_NCS(name, err, nr, args...)    \
00260   ({                                             \
00261     DO_INLINE_SYSCALL_NCS (name, nr, args)              \
00262     err = _r10;                                         \
00263     _retval; })
00264 #define INTERNAL_SYSCALL(name, err, nr, args...) \
00265   INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
00266 
00267 #undef INTERNAL_SYSCALL_ERROR_P
00268 #define INTERNAL_SYSCALL_ERROR_P(val, err)       (err == -1)
00269 
00270 #undef INTERNAL_SYSCALL_ERRNO
00271 #define INTERNAL_SYSCALL_ERRNO(val, err)  (val)
00272 
00273 #define LOAD_ARGS_0()
00274 #define LOAD_REGS_0
00275 #define LOAD_ARGS_1(a1)                                 \
00276   long _arg1 = (long) (a1);                      \
00277   LOAD_ARGS_0 ()
00278 #define LOAD_REGS_1                              \
00279   register long _out0 asm ("out0") = _arg1;             \
00280   LOAD_REGS_0
00281 #define LOAD_ARGS_2(a1, a2)                      \
00282   long _arg2 = (long) (a2);                      \
00283   LOAD_ARGS_1 (a1)
00284 #define LOAD_REGS_2                              \
00285   register long _out1 asm ("out1") = _arg2;             \
00286   LOAD_REGS_1
00287 #define LOAD_ARGS_3(a1, a2, a3)                         \
00288   long _arg3 = (long) (a3);                      \
00289   LOAD_ARGS_2 (a1, a2)
00290 #define LOAD_REGS_3                              \
00291   register long _out2 asm ("out2") = _arg3;             \
00292   LOAD_REGS_2
00293 #define LOAD_ARGS_4(a1, a2, a3, a4)                     \
00294   long _arg4 = (long) (a4);                      \
00295   LOAD_ARGS_3 (a1, a2, a3)
00296 #define LOAD_REGS_4                              \
00297   register long _out3 asm ("out3") = _arg4;             \
00298   LOAD_REGS_3
00299 #define LOAD_ARGS_5(a1, a2, a3, a4, a5)                 \
00300   long _arg5 = (long) (a5);                      \
00301   LOAD_ARGS_4 (a1, a2, a3, a4)
00302 #define LOAD_REGS_5                              \
00303   register long _out4 asm ("out4") = _arg5;             \
00304   LOAD_REGS_4
00305 #define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)             \
00306   long _arg6 = (long) (a6);                      \
00307   LOAD_ARGS_5 (a1, a2, a3, a4, a5)
00308 #define LOAD_REGS_6                              \
00309   register long _out5 asm ("out5") = _arg6;             \
00310   LOAD_REGS_5
00311 
00312 #define ASM_OUTARGS_0
00313 #define ASM_OUTARGS_1       ASM_OUTARGS_0, "=r" (_out0)
00314 #define ASM_OUTARGS_2       ASM_OUTARGS_1, "=r" (_out1)
00315 #define ASM_OUTARGS_3       ASM_OUTARGS_2, "=r" (_out2)
00316 #define ASM_OUTARGS_4       ASM_OUTARGS_3, "=r" (_out3)
00317 #define ASM_OUTARGS_5       ASM_OUTARGS_4, "=r" (_out4)
00318 #define ASM_OUTARGS_6       ASM_OUTARGS_5, "=r" (_out5)
00319 
00320 #ifdef IA64_USE_NEW_STUB
00321 #define ASM_ARGS_0
00322 #define ASM_ARGS_1   ASM_ARGS_0, "4" (_out0)
00323 #define ASM_ARGS_2   ASM_ARGS_1, "5" (_out1)
00324 #define ASM_ARGS_3   ASM_ARGS_2, "6" (_out2)
00325 #define ASM_ARGS_4   ASM_ARGS_3, "7" (_out3)
00326 #define ASM_ARGS_5   ASM_ARGS_4, "8" (_out4)
00327 #define ASM_ARGS_6   ASM_ARGS_5, "9" (_out5)
00328 #else
00329 #define ASM_ARGS_0
00330 #define ASM_ARGS_1   ASM_ARGS_0, "3" (_out0)
00331 #define ASM_ARGS_2   ASM_ARGS_1, "4" (_out1)
00332 #define ASM_ARGS_3   ASM_ARGS_2, "5" (_out2)
00333 #define ASM_ARGS_4   ASM_ARGS_3, "6" (_out3)
00334 #define ASM_ARGS_5   ASM_ARGS_4, "7" (_out4)
00335 #define ASM_ARGS_6   ASM_ARGS_5, "8" (_out5)
00336 #endif
00337 
00338 #define ASM_CLOBBERS_0      ASM_CLOBBERS_1, "out0"
00339 #define ASM_CLOBBERS_1      ASM_CLOBBERS_2, "out1"
00340 #define ASM_CLOBBERS_2      ASM_CLOBBERS_3, "out2"
00341 #define ASM_CLOBBERS_3      ASM_CLOBBERS_4, "out3"
00342 #define ASM_CLOBBERS_4      ASM_CLOBBERS_5, "out4"
00343 #define ASM_CLOBBERS_5      ASM_CLOBBERS_6, "out5"
00344 #define ASM_CLOBBERS_6_COMMON      , "out6", "out7",                  \
00345   /* Non-stacked integer registers, minus r8, r10, r15.  */           \
00346   "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",  \
00347   "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",      \
00348   "r28", "r29", "r30", "r31",                                         \
00349   /* Predicate registers.  */                                         \
00350   "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",   \
00351   /* Non-rotating fp registers.  */                                   \
00352   "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",   \
00353   /* Branch registers.  */                                     \
00354   "b6"
00355 
00356 #ifdef IA64_USE_NEW_STUB
00357 # define ASM_CLOBBERS_6     ASM_CLOBBERS_6_COMMON
00358 #else
00359 # define ASM_CLOBBERS_6     ASM_CLOBBERS_6_COMMON , "b7"
00360 #endif
00361 
00362 #endif /* not __ASSEMBLER__ */
00363 
00364 /* Pointer mangling support.  */
00365 #if defined NOT_IN_libc && defined IS_IN_rtld
00366 /* We cannot use the thread descriptor because in ld.so we use setjmp
00367    earlier than the descriptor is initialized.  */
00368 #else
00369 # ifdef __ASSEMBLER__
00370 #  define PTR_MANGLE(reg, tmpreg) \
00371         add   tmpreg=-16,r13              \
00372         ;;                         \
00373         ld8   tmpreg=[tmpreg]             \
00374         ;;                         \
00375         xor   reg=reg, tmpreg
00376 #  define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
00377 # else
00378 #  define PTR_MANGLE(var) \
00379   (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
00380 #  define PTR_DEMANGLE(var) PTR_MANGLE (var)
00381 # endif
00382 #endif
00383 
00384 #endif /* linux/ia64/sysdep.h */