Back to index

glibc  2.9
sysdep.h
Go to the documentation of this file.
00001 /* Copyright (C) 1996, 1997, 1998, 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Written by Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>,
00004    December 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_M68K_SYSDEP_H
00022 #define _LINUX_M68K_SYSDEP_H 1
00023 
00024 #include <sysdeps/unix/sysdep.h>
00025 #include <sysdeps/m68k/sysdep.h>
00026 
00027 /* Defines RTLD_PRIVATE_ERRNO.  */
00028 #include <dl-sysdep.h>
00029 
00030 /* For Linux we can use the system call table in the header file
00031        /usr/include/asm/unistd.h
00032    of the kernel.  But these symbols do not follow the SYS_* syntax
00033    so we have to redefine the `SYS_ify' macro here.  */
00034 #undef SYS_ify
00035 #ifdef __STDC__
00036 # define SYS_ify(syscall_name)     __NR_##syscall_name
00037 #else
00038 # define SYS_ify(syscall_name)     __NR_syscall_name
00039 #endif
00040 
00041 #ifdef __ASSEMBLER__
00042 
00043 /* Linux uses a negative return value to indicate syscall errors, unlike
00044    most Unices, which use the condition codes' carry flag.
00045 
00046    Since version 2.1 the return value of a system call might be negative
00047    even if the call succeeded.  E.g., the `lseek' system call might return
00048    a large offset.  Therefore we must not anymore test for < 0, but test
00049    for a real error by making sure the value in %d0 is a real error
00050    number.  Linus said he will make sure the no syscall returns a value
00051    in -1 .. -4095 as a valid result so we can savely test with -4095.  */
00052 
00053 /* We don't want the label for the error handler to be visible in the symbol
00054    table when we define it here.  */
00055 #ifdef PIC
00056 #define SYSCALL_ERROR_LABEL .Lsyscall_error
00057 #else
00058 #define SYSCALL_ERROR_LABEL __syscall_error
00059 #endif
00060 
00061 #undef PSEUDO
00062 #define       PSEUDO(name, syscall_name, args)                              \
00063   .text;                                                             \
00064   ENTRY (name)                                                              \
00065     DO_CALL (syscall_name, args);                                    \
00066     cmp.l &-4095, %d0;                                                      \
00067     jcc SYSCALL_ERROR_LABEL
00068 
00069 #undef PSEUDO_END
00070 #define PSEUDO_END(name)                                             \
00071   SYSCALL_ERROR_HANDLER;                                             \
00072   END (name)
00073 
00074 #undef PSEUDO_NOERRNO
00075 #define       PSEUDO_NOERRNO(name, syscall_name, args)                      \
00076   .text;                                                             \
00077   ENTRY (name)                                                              \
00078     DO_CALL (syscall_name, args)
00079 
00080 #undef PSEUDO_END_NOERRNO
00081 #define PSEUDO_END_NOERRNO(name)                                     \
00082   END (name)
00083 
00084 #define ret_NOERRNO rts
00085 
00086 /* The function has to return the error code.  */
00087 #undef PSEUDO_ERRVAL
00088 #define       PSEUDO_ERRVAL(name, syscall_name, args) \
00089   .text;                                                             \
00090   ENTRY (name)                                                              \
00091     DO_CALL (syscall_name, args);                                    \
00092     negl %d0
00093 
00094 #undef PSEUDO_END_ERRVAL
00095 #define       PSEUDO_END_ERRVAL(name) \
00096   END (name)
00097 
00098 #define ret_ERRVAL rts
00099 
00100 #ifdef PIC
00101 # if RTLD_PRIVATE_ERRNO
00102 #  define SYSCALL_ERROR_HANDLER                                             \
00103 SYSCALL_ERROR_LABEL:                                                 \
00104     PCREL_OP (lea, rtld_errno, %a0, %a0);                            \
00105     neg.l %d0;                                                              \
00106     move.l %d0, (%a0);                                                      \
00107     move.l &-1, %d0;                                                 \
00108     /* Copy return value to %a0 for syscalls that are declared to return      \
00109        a pointer (e.g., mmap).  */                                   \
00110     move.l %d0, %a0;                                                 \
00111     rts;
00112 # else /* !RTLD_PRIVATE_ERRNO */
00113 /* Store (- %d0) into errno through the GOT.  */
00114 #  if defined _LIBC_REENTRANT
00115 #   define SYSCALL_ERROR_HANDLER                                     \
00116 SYSCALL_ERROR_LABEL:                                                 \
00117     neg.l %d0;                                                              \
00118     move.l %d0, -(%sp);                                                     \
00119     jbsr __errno_location@PLTPC;                                     \
00120     move.l (%sp)+, (%a0);                                            \
00121     move.l &-1, %d0;                                                 \
00122     /* Copy return value to %a0 for syscalls that are declared to return      \
00123        a pointer (e.g., mmap).  */                                   \
00124     move.l %d0, %a0;                                                 \
00125     rts;
00126 #  else /* !_LIBC_REENTRANT */
00127 #   define SYSCALL_ERROR_HANDLER                                     \
00128 SYSCALL_ERROR_LABEL:                                                 \
00129     move.l (errno@GOTPC, %pc), %a0;                                         \
00130     neg.l %d0;                                                              \
00131     move.l %d0, (%a0);                                                      \
00132     move.l &-1, %d0;                                                 \
00133     /* Copy return value to %a0 for syscalls that are declared to return      \
00134        a pointer (e.g., mmap).  */                                   \
00135     move.l %d0, %a0;                                                 \
00136     rts;
00137 #  endif /* _LIBC_REENTRANT */
00138 # endif /* RTLD_PRIVATE_ERRNO */
00139 #else
00140 # define SYSCALL_ERROR_HANDLER     /* Nothing here; code in sysdep.S is used.  */
00141 #endif /* PIC */
00142 
00143 /* Linux takes system call arguments in registers:
00144 
00145        syscall number       %d0         call-clobbered
00146        arg 1         %d1         call-clobbered
00147        arg 2         %d2         call-saved
00148        arg 3         %d3         call-saved
00149        arg 4         %d4         call-saved
00150        arg 5         %d5         call-saved
00151 
00152    The stack layout upon entering the function is:
00153 
00154        20(%sp)              Arg# 5
00155        16(%sp)              Arg# 4
00156        12(%sp)              Arg# 3
00157         8(%sp)              Arg# 2
00158         4(%sp)              Arg# 1
00159          (%sp)              Return address
00160 
00161    (Of course a function with say 3 arguments does not have entries for
00162    arguments 4 and 5.)
00163 
00164    Separate move's are faster than movem, but need more space.  Since
00165    speed is more important, we don't use movem.  Since %a0 and %a1 are
00166    scratch registers, we can use them for saving as well.  */
00167 
00168 #define DO_CALL(syscall_name, args)                                         \
00169     move.l &SYS_ify(syscall_name), %d0;                                     \
00170     DOARGS_##args                                                    \
00171     trap &0;                                                         \
00172     UNDOARGS_##args
00173 
00174 #define       DOARGS_0      /* No arguments to frob.  */
00175 #define       UNDOARGS_0    /* No arguments to unfrob.  */
00176 #define       _DOARGS_0(n)  /* No arguments to frob.  */
00177 
00178 #define       DOARGS_1      _DOARGS_1 (4)
00179 #define       _DOARGS_1(n)  move.l n(%sp), %d1; _DOARGS_0 (n)
00180 #define       UNDOARGS_1    UNDOARGS_0
00181 
00182 #define       DOARGS_2      _DOARGS_2 (8)
00183 #define       _DOARGS_2(n)  move.l %d2, %a0; move.l n(%sp), %d2; _DOARGS_1 (n-4)
00184 #define       UNDOARGS_2    UNDOARGS_1; move.l %a0, %d2
00185 
00186 #define DOARGS_3     _DOARGS_3 (12)
00187 #define _DOARGS_3(n) move.l %d3, %a1; move.l n(%sp), %d3; _DOARGS_2 (n-4)
00188 #define UNDOARGS_3   UNDOARGS_2; move.l %a1, %d3
00189 
00190 #define DOARGS_4     _DOARGS_4 (16)
00191 #define _DOARGS_4(n) move.l %d4, -(%sp); move.l n+4(%sp), %d4; _DOARGS_3 (n)
00192 #define UNDOARGS_4   UNDOARGS_3; move.l (%sp)+, %d4
00193 
00194 #define DOARGS_5     _DOARGS_5 (20)
00195 #define _DOARGS_5(n) move.l %d5, -(%sp); move.l n+4(%sp), %d5; _DOARGS_4 (n)
00196 #define UNDOARGS_5   UNDOARGS_4; move.l (%sp)+, %d5
00197 
00198 #define DOARGS_6     _DOARGS_6 (24)
00199 #define _DOARGS_6(n) _DOARGS_5 (n-4); move.l %a0, -(%sp); move.l n+12(%sp), %a0;
00200 #define UNDOARGS_6   move.l (%sp)+, %a0; UNDOARGS_5
00201 
00202 
00203 #define       ret    rts
00204 #if 0 /* Not used by Linux */
00205 #define       r0     %d0
00206 #define       r1     %d1
00207 #define       MOVE(x,y)     movel x , y
00208 #endif
00209 
00210 #else /* not __ASSEMBLER__ */
00211 
00212 /* Define a macro which expands into the inline wrapper code for a system
00213    call.  */
00214 #undef INLINE_SYSCALL
00215 #define INLINE_SYSCALL(name, nr, args...)                      \
00216   ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args);  \
00217      if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))\
00218        {                                                       \
00219         __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, ));         \
00220         _sys_result = (unsigned int) -1;                       \
00221        }                                                       \
00222      (int) _sys_result; })
00223 
00224 #undef INTERNAL_SYSCALL_DECL
00225 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
00226 
00227 /* Define a macro which expands inline into the wrapper code for a system
00228    call.  This use is for internal calls that do not need to handle errors
00229    normally.  It will never touch errno.  This returns just what the kernel
00230    gave back.  */
00231 #undef INTERNAL_SYSCALL
00232 #define INTERNAL_SYSCALL(name, err, nr, args...) \
00233   ({ unsigned int _sys_result;                          \
00234      {                                           \
00235        /* Load argument values in temporary variables
00236          to perform side effects like function calls
00237          before the call used registers are set.  */    \
00238        LOAD_ARGS_##nr (args)                            \
00239        LOAD_REGS_##nr                                   \
00240        register int _d0 asm ("%d0") = __NR_##name;      \
00241        asm volatile ("trap #0"                          \
00242                    : "=d" (_d0)                  \
00243                    : "0" (_d0) ASM_ARGS_##nr            \
00244                    : "memory");                  \
00245        _sys_result = _d0;                        \
00246      }                                           \
00247      (int) _sys_result; })
00248 
00249 #undef INTERNAL_SYSCALL_ERROR_P
00250 #define INTERNAL_SYSCALL_ERROR_P(val, err)              \
00251   ((unsigned int) (val) >= -4095U)
00252 
00253 #undef INTERNAL_SYSCALL_ERRNO
00254 #define INTERNAL_SYSCALL_ERRNO(val, err)  (-(val))
00255 
00256 #define LOAD_ARGS_0()
00257 #define LOAD_REGS_0
00258 #define ASM_ARGS_0
00259 #define LOAD_ARGS_1(a1)                          \
00260   LOAD_ARGS_0 ()                          \
00261   int __arg1 = (int) (a1);
00262 #define LOAD_REGS_1                       \
00263   register int _d1 asm ("d1") = __arg1;          \
00264   LOAD_REGS_0
00265 #define ASM_ARGS_1   ASM_ARGS_0, "d" (_d1)
00266 #define LOAD_ARGS_2(a1, a2)               \
00267   LOAD_ARGS_1 (a1)                        \
00268   int __arg2 = (int) (a2);
00269 #define LOAD_REGS_2                       \
00270   register int _d2 asm ("d2") = __arg2;          \
00271   LOAD_REGS_1
00272 #define ASM_ARGS_2   ASM_ARGS_1, "d" (_d2)
00273 #define LOAD_ARGS_3(a1, a2, a3)                  \
00274   LOAD_ARGS_2 (a1, a2)                           \
00275   int __arg3 = (int) (a3);
00276 #define LOAD_REGS_3                       \
00277   register int _d3 asm ("d3") = __arg3;          \
00278   LOAD_REGS_2
00279 #define ASM_ARGS_3   ASM_ARGS_2, "d" (_d3)
00280 #define LOAD_ARGS_4(a1, a2, a3, a4)              \
00281   LOAD_ARGS_3 (a1, a2, a3)                \
00282   int __arg4 = (int) (a4);
00283 #define LOAD_REGS_4                       \
00284   register int _d4 asm ("d4") = __arg4;          \
00285   LOAD_REGS_3
00286 #define ASM_ARGS_4   ASM_ARGS_3, "d" (_d4)
00287 #define LOAD_ARGS_5(a1, a2, a3, a4, a5)          \
00288   LOAD_ARGS_4 (a1, a2, a3, a4)                   \
00289   int __arg5 = (int) (a5);
00290 #define LOAD_REGS_5                       \
00291   register int _d5 asm ("d5") = __arg5;          \
00292   LOAD_REGS_4
00293 #define ASM_ARGS_5   ASM_ARGS_4, "d" (_d5)
00294 #define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)      \
00295   LOAD_ARGS_5 (a1, a2, a3, a4, a5)        \
00296   int __arg6 = (int) (a6);
00297 #define LOAD_REGS_6                       \
00298   register int _a0 asm ("a0") = __arg6;          \
00299   LOAD_REGS_5
00300 #define ASM_ARGS_6   ASM_ARGS_5, "a" (_a0)
00301 
00302 #endif /* not __ASSEMBLER__ */
00303 #endif