Back to index

glibc  2.9
sysdep.h
Go to the documentation of this file.
00001 /* Copyright (C) 1992,1993,1995,1996,1997,1998,1999,2000,2002,2003,2004,
00002    2005,2006  Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995.
00005    Changed by Kaz Kojima, <kkojima@rr.iij4u.or.jp>.
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_SH_SYSDEP_H
00023 #define _LINUX_SH_SYSDEP_H 1
00024 
00025 /* There is some commonality.  */
00026 #include <sysdeps/unix/sh/sysdep.h>
00027 #include <tls.h>
00028 
00029 /* For Linux we can use the system call table in the header file
00030        /usr/include/asm/unistd.h
00031    of the kernel.  But these symbols do not follow the SYS_* syntax
00032    so we have to redefine the `SYS_ify' macro here.  */
00033 #undef SYS_ify
00034 #define SYS_ify(syscall_name)      (__NR_##syscall_name)
00035 
00036 
00037 #ifdef __ASSEMBLER__
00038 
00039 /* Linux uses a negative return value to indicate syscall errors,
00040    unlike most Unices, which use the condition codes' carry flag.
00041 
00042    Since version 2.1 the return value of a system call might be
00043    negative even if the call succeeded.  E.g., the `lseek' system call
00044    might return a large offset.  Therefore we must not anymore test
00045    for < 0, but test for a real error by making sure the value in R0
00046    is a real error number.  Linus said he will make sure the no syscall
00047    returns a value in -1 .. -4095 as a valid result so we can savely
00048    test with -4095.  */
00049 
00050 #define _IMM1 #-1
00051 #define _IMM12 #-12
00052 #undef PSEUDO
00053 #define       PSEUDO(name, syscall_name, args) \
00054  .text; \
00055  ENTRY (name); \
00056     DO_CALL (syscall_name, args); \
00057     mov r0,r1; \
00058     mov _IMM12,r2; \
00059     shad r2,r1; \
00060     not r1,r1; \
00061     tst r1,r1; \
00062     bf .Lpseudo_end; \
00063     SYSCALL_ERROR_HANDLER; \
00064  .Lpseudo_end:
00065 
00066 #undef PSEUDO_END
00067 #define       PSEUDO_END(name) \
00068   END (name)
00069 
00070 #undef PSEUDO_NOERRNO
00071 #define       PSEUDO_NOERRNO(name, syscall_name, args) \
00072  .text; \
00073  ENTRY (name); \
00074     DO_CALL (syscall_name, args)
00075 
00076 #undef PSEUDO_END_NOERRNO
00077 #define       PSEUDO_END_NOERRNO(name) \
00078   END (name)
00079 
00080 #define ret_NOERRNO ret
00081 
00082 #define       PSEUDO_ERRVAL(name, syscall_name, args) \
00083  .text; \
00084  ENTRY (name); \
00085     DO_CALL (syscall_name, args);
00086 
00087 #undef PSEUDO_END_ERRVAL
00088 #define       PSEUDO_END_ERRVAL(name) \
00089   END (name)
00090 
00091 #define ret_ERRVAL ret
00092 
00093 #ifndef PIC
00094 # define SYSCALL_ERROR_HANDLER     \
00095        mov.l 0f,r1; \
00096        jmp @r1; \
00097         mov r0,r4; \
00098        .align 2; \
00099      0: .long __syscall_error
00100 #else
00101 # if RTLD_PRIVATE_ERRNO
00102 #  define SYSCALL_ERROR_HANDLER    \
00103        neg r0,r1; \
00104        mov.l 0f,r12; \
00105        mova 0f,r0; \
00106        add r0,r12; \
00107        mov.l 1f,r0; \
00108        mov.l r1,@(r0,r12); \
00109        bra .Lpseudo_end; \
00110         mov _IMM1,r0; \
00111        .align 2; \
00112      0: .long _GLOBAL_OFFSET_TABLE_; \
00113      1: .long rtld_errno@GOTOFF
00114 
00115 # elif defined _LIBC_REENTRANT
00116 
00117 #  if USE___THREAD
00118 #   ifndef NOT_IN_libc
00119 #    define SYSCALL_ERROR_ERRNO __libc_errno
00120 #   else
00121 #    define SYSCALL_ERROR_ERRNO errno
00122 #   endif
00123 #   define SYSCALL_ERROR_HANDLER \
00124        neg r0,r1; \
00125        mov r12,r2; \
00126        mov.l 0f,r12; \
00127        mova 0f,r0; \
00128        add r0,r12; \
00129        mov.l 1f,r0; \
00130        stc gbr, r4; \
00131        mov.l @(r0,r12),r0; \
00132        mov r2,r12; \
00133        add r4,r0; \
00134        mov.l r1,@r0; \
00135        bra .Lpseudo_end; \
00136         mov _IMM1,r0; \
00137        .align 2; \
00138      0: .long _GLOBAL_OFFSET_TABLE_; \
00139      1: .long SYSCALL_ERROR_ERRNO@GOTTPOFF
00140 #  else
00141 #   define SYSCALL_ERROR_HANDLER \
00142        neg r0,r1; \
00143        mov.l r14,@-r15; \
00144        cfi_adjust_cfa_offset (4); \
00145        cfi_rel_offset (r14, 0); \
00146        mov.l r12,@-r15; \
00147        cfi_adjust_cfa_offset (4); \
00148        cfi_rel_offset (r12, 0); \
00149        mov.l r1,@-r15; \
00150        cfi_adjust_cfa_offset (4); \
00151        cfi_rel_offset (r1, 0); \
00152        mov.l 0f,r12; \
00153        mova 0f,r0; \
00154        add r0,r12; \
00155        sts.l pr,@-r15; \
00156        cfi_adjust_cfa_offset (4); \
00157        cfi_rel_offset (pr, 0); \
00158        mov r15,r14; \
00159        cfi_def_cfa_register (r14); \
00160        mov.l 1f,r1; \
00161        bsrf r1; \
00162          nop; \
00163      2: mov r14,r15; \
00164        lds.l @r15+,pr; \
00165        mov.l @r15+,r1; \
00166        mov.l r1,@r0; \
00167        mov.l @r15+,r12; \
00168        mov.l @r15+,r14; \
00169        bra .Lpseudo_end; \
00170         mov _IMM1,r0; \
00171        .align 2; \
00172      0: .long _GLOBAL_OFFSET_TABLE_; \
00173      1: .long PLTJMP(C_SYMBOL_NAME(__errno_location))-(2b-.)
00174 /* A quick note: it is assumed that the call to `__errno_location' does
00175    not modify the stack!  */
00176 #  endif
00177 # else
00178 /* Store (-r0) into errno through the GOT.  */
00179 #  define SYSCALL_ERROR_HANDLER                                             \
00180        neg r0,r1; \
00181        mov r12,r2; \
00182        mov.l 0f,r12; \
00183        mova 0f,r0; \
00184        add r0,r12; \
00185        mov.l 1f,r0; \
00186        mov.l @(r0,r12),r0; \
00187        mov r2,r12; \
00188        mov.l r1,@r0; \
00189        bra .Lpseudo_end; \
00190         mov _IMM1,r0; \
00191        .align 2; \
00192      0: .long _GLOBAL_OFFSET_TABLE_; \
00193      1: .long errno@GOT
00194 # endif       /* _LIBC_REENTRANT */
00195 #endif /* PIC */
00196 
00197 # ifdef NEED_SYSCALL_INST_PAD
00198 #  define SYSCALL_INST_PAD \
00199        or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0
00200 # else
00201 #  define SYSCALL_INST_PAD
00202 # endif
00203 
00204 #define SYSCALL_INST0       trapa #0x10
00205 #define SYSCALL_INST1       trapa #0x11
00206 #define SYSCALL_INST2       trapa #0x12
00207 #define SYSCALL_INST3       trapa #0x13
00208 #define SYSCALL_INST4       trapa #0x14
00209 #define SYSCALL_INST5       mov.l @(0,r15),r0; trapa #0x15
00210 #define SYSCALL_INST6       mov.l @(0,r15),r0; mov.l @(4,r15),r1; trapa #0x16
00211 
00212 #undef DO_CALL
00213 #define DO_CALL(syscall_name, args)       \
00214     mov.l 1f,r3;                   \
00215     SYSCALL_INST##args;                   \
00216     SYSCALL_INST_PAD;                     \
00217     bra 2f;                        \
00218      nop;                          \
00219     .align 2;                      \
00220  1: .long SYS_ify (syscall_name);  \
00221  2:
00222 
00223 #else /* not __ASSEMBLER__ */
00224 
00225 #define SYSCALL_INST_STR0   "trapa #0x10\n\t"
00226 #define SYSCALL_INST_STR1   "trapa #0x11\n\t"
00227 #define SYSCALL_INST_STR2   "trapa #0x12\n\t"
00228 #define SYSCALL_INST_STR3   "trapa #0x13\n\t"
00229 #define SYSCALL_INST_STR4   "trapa #0x14\n\t"
00230 #define SYSCALL_INST_STR5   "trapa #0x15\n\t"
00231 #define SYSCALL_INST_STR6   "trapa #0x16\n\t"
00232 
00233 # ifdef NEED_SYSCALL_INST_PAD
00234 #  define SYSCALL_INST_PAD "\
00235        or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0"
00236 # else
00237 #  define SYSCALL_INST_PAD
00238 # endif
00239 
00240 #define ASMFMT_0
00241 #define ASMFMT_1 \
00242        , "r" (r4)
00243 #define ASMFMT_2 \
00244        , "r" (r4), "r" (r5)
00245 #define ASMFMT_3 \
00246        , "r" (r4), "r" (r5), "r" (r6)
00247 #define ASMFMT_4 \
00248        , "r" (r4), "r" (r5), "r" (r6), "r" (r7)
00249 #define ASMFMT_5 \
00250        , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0)
00251 #define ASMFMT_6 \
00252        , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0), "r" (r1)
00253 #define ASMFMT_7 \
00254        , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0), "r" (r1), "r" (r2)
00255 
00256 #define SUBSTITUTE_ARGS_0()
00257 #define SUBSTITUTE_ARGS_1(arg1) \
00258        long int _arg1 = (long int) (arg1);                                  \
00259        register long int r4 asm ("%r4") = (long int) (_arg1)
00260 #define SUBSTITUTE_ARGS_2(arg1, arg2) \
00261        long int _arg1 = (long int) (arg1);                                  \
00262        long int _arg2 = (long int) (arg2);                                  \
00263        register long int r4 asm ("%r4") = (long int) (_arg1);               \
00264        register long int r5 asm ("%r5") = (long int) (_arg2)
00265 #define SUBSTITUTE_ARGS_3(arg1, arg2, arg3) \
00266        long int _arg1 = (long int) (arg1);                                  \
00267        long int _arg2 = (long int) (arg2);                                  \
00268        long int _arg3 = (long int) (arg3);                                  \
00269        register long int r4 asm ("%r4") = (long int) (_arg1);               \
00270        register long int r5 asm ("%r5") = (long int) (_arg2);               \
00271        register long int r6 asm ("%r6") = (long int) (_arg3)
00272 #define SUBSTITUTE_ARGS_4(arg1, arg2, arg3, arg4) \
00273        long int _arg1 = (long int) (arg1);                                  \
00274        long int _arg2 = (long int) (arg2);                                  \
00275        long int _arg3 = (long int) (arg3);                                  \
00276        long int _arg4 = (long int) (arg4);                                  \
00277        register long int r4 asm ("%r4") = (long int) (_arg1);               \
00278        register long int r5 asm ("%r5") = (long int) (_arg2);               \
00279        register long int r6 asm ("%r6") = (long int) (_arg3);               \
00280        register long int r7 asm ("%r7") = (long int) (_arg4)
00281 #define SUBSTITUTE_ARGS_5(arg1, arg2, arg3, arg4, arg5) \
00282        long int _arg1 = (long int) (arg1);                                  \
00283        long int _arg2 = (long int) (arg2);                                  \
00284        long int _arg3 = (long int) (arg3);                                  \
00285        long int _arg4 = (long int) (arg4);                                  \
00286        long int _arg5 = (long int) (arg5);                                  \
00287        register long int r4 asm ("%r4") = (long int) (_arg1);               \
00288        register long int r5 asm ("%r5") = (long int) (_arg2);               \
00289        register long int r6 asm ("%r6") = (long int) (_arg3);               \
00290        register long int r7 asm ("%r7") = (long int) (_arg4);               \
00291        register long int r0 asm ("%r0") = (long int) (_arg5)
00292 #define SUBSTITUTE_ARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
00293        long int _arg1 = (long int) (arg1);                                  \
00294        long int _arg2 = (long int) (arg2);                                  \
00295        long int _arg3 = (long int) (arg3);                                  \
00296        long int _arg4 = (long int) (arg4);                                  \
00297        long int _arg5 = (long int) (arg5);                                  \
00298        long int _arg6 = (long int) (arg6);                                  \
00299        register long int r4 asm ("%r4") = (long int)(_arg1);                \
00300        register long int r5 asm ("%r5") = (long int) (_arg2);               \
00301        register long int r6 asm ("%r6") = (long int) (_arg3);               \
00302        register long int r7 asm ("%r7") = (long int) (_arg4);               \
00303        register long int r0 asm ("%r0") = (long int) (_arg5);               \
00304        register long int r1 asm ("%r1") = (long int) (_arg6)
00305 #define SUBSTITUTE_ARGS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
00306        long int _arg1 = (long int) (arg1);                                  \
00307        long int _arg2 = (long int) (arg2);                                  \
00308        long int _arg3 = (long int) (arg3);                                  \
00309        long int _arg4 = (long int) (arg4);                                  \
00310        long int _arg5 = (long int) (arg5);                                  \
00311        long int _arg6 = (long int) (arg6);                                  \
00312        long int _arg7 = (long int) (arg7);                                  \
00313        register long int r4 asm ("%r4") = (long int) (_arg1);               \
00314        register long int r5 asm ("%r5") = (long int) (_arg2);               \
00315        register long int r6 asm ("%r6") = (long int) (_arg3);               \
00316        register long int r7 asm ("%r7") = (long int) (_arg4);               \
00317        register long int r0 asm ("%r0") = (long int) (_arg5);               \
00318        register long int r1 asm ("%r1") = (long int) (_arg6);               \
00319        register long int r2 asm ("%r2") = (long int) (_arg7)
00320 
00321 #undef INLINE_SYSCALL
00322 #define INLINE_SYSCALL(name, nr, args...) \
00323   ({                                                                          \
00324     unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);             \
00325     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))         \
00326       {                                                                       \
00327         __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));                   \
00328         resultvar = 0xffffffff;                                               \
00329       }                                                                       \
00330     (int) resultvar; })
00331 
00332 #undef INTERNAL_SYSCALL
00333 #define INTERNAL_SYSCALL(name, err, nr, args...) \
00334   ({                                                                 \
00335     unsigned long int resultvar;                                     \
00336     register long int r3 asm ("%r3") = SYS_ify (name);                      \
00337     SUBSTITUTE_ARGS_##nr(args);                                             \
00338                                                                      \
00339     asm volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD                     \
00340                 : "=z" (resultvar)                                   \
00341                 : "r" (r3) ASMFMT_##nr                               \
00342                 : "memory");                                                \
00343                                                                      \
00344     (int) resultvar; })
00345 
00346 /* The _NCS variant allows non-constant syscall numbers.  */
00347 #define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
00348   ({                                                                 \
00349     unsigned long int resultvar;                                     \
00350     register long int r3 asm ("%r3") = (name);                              \
00351     SUBSTITUTE_ARGS_##nr(args);                                             \
00352                                                                      \
00353     asm volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD                     \
00354                 : "=z" (resultvar)                                   \
00355                 : "r" (r3) ASMFMT_##nr                               \
00356                 : "memory");                                                \
00357                                                                      \
00358     (int) resultvar; })
00359 
00360 #undef INTERNAL_SYSCALL_DECL
00361 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
00362 
00363 #undef INTERNAL_SYSCALL_ERROR_P
00364 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
00365   ((unsigned int) (val) >= 0xfffff001u)
00366 
00367 #undef INTERNAL_SYSCALL_ERRNO
00368 #define INTERNAL_SYSCALL_ERRNO(val, err)        (-(val))
00369 
00370 #endif /* __ASSEMBLER__ */
00371 
00372 /* Pointer mangling support.  */
00373 #if defined NOT_IN_libc && defined IS_IN_rtld
00374 /* We cannot use the thread descriptor because in ld.so we use setjmp
00375    earlier than the descriptor is initialized.  Using a global variable
00376    is too complicated here since we have no PC-relative addressing mode.  */
00377 #else
00378 # ifdef __ASSEMBLER__
00379 #  define PTR_MANGLE(reg, tmp) \
00380      stc gbr,tmp; mov.l @(POINTER_GUARD,tmp),tmp; xor tmp,reg
00381 #  define PTR_MANGLE2(reg, tmp)    xor tmp,reg
00382 #  define PTR_DEMANGLE(reg, tmp)   PTR_MANGLE (reg, tmp)
00383 #  define PTR_DEMANGLE2(reg, tmp)  PTR_MANGLE2 (reg, tmp)
00384 # else
00385 #  define PTR_MANGLE(var) \
00386      (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
00387 #  define PTR_DEMANGLE(var) PTR_MANGLE (var)
00388 # endif
00389 #endif
00390 
00391 #endif /* linux/sh/sysdep.h */