Back to index

glibc  2.9
sysdep.h
Go to the documentation of this file.
00001 /* Assembler macros for CRIS.
00002    Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <asm/unistd.h>
00021 #include <sysdeps/cris/sysdep.h>
00022 #include <sys/syscall.h>
00023 #include "config.h"
00024 
00025 #undef SYS_ify
00026 #define SYS_ify(syscall_name)      (__NR_##syscall_name)
00027 
00028 
00029 #ifdef __ASSEMBLER__
00030 
00031 /* For Linux we can use the system call table in the header file
00032        /usr/include/asm/unistd.h
00033    of the kernel.  But these symbols do not follow the SYS_* syntax
00034    so we have to redefine the `SYS_ify' macro here.  */
00035 #undef SYS_ify
00036 #define SYS_ify(syscall_name)      __NR_##syscall_name
00037 
00038 /* ELF-like local names start with `.L'.  */
00039 #undef L
00040 #define L(name)      .L##name
00041 
00042 /* Linux uses a negative return value to indicate syscall errors,
00043    unlike most Unices, which use the condition codes' carry flag.
00044 
00045    Since version 2.1 the return value of a system call might be
00046    negative even if the call succeeded.  E.g., the `lseek' system call
00047    might return a large offset.  Therefore we must not anymore test
00048    for < 0, but test for a real error by making sure the value in %eax
00049    is a real error number.  Linus said he will make sure the no syscall
00050    returns a value in -1 .. -4095 as a valid result so we can safely
00051    test with -4095.  */
00052 
00053 /* Syscall wrappers consist of
00054        #include <sysdep.h>
00055        PSEUDO (...)
00056         ret
00057        PSEUDO_END (...)
00058 
00059    which expand to the following.  */
00060 
00061 /* Linux takes system call arguments in registers:
00062        syscall number       R9
00063        arg 1         R10
00064        arg 2         R11
00065        arg 3         R12
00066        arg 4         R13
00067        arg 5         MOF
00068        arg 6         SRP
00069 
00070    The compiler calls us by the C convention:
00071        syscall number       in the DO_CALL macro
00072        arg 1         R10
00073        arg 2         R11
00074        arg 3         R12
00075        arg 4         R13
00076        arg 5         [SP]
00077        arg 6         [SP + 4]
00078    */
00079 
00080 /* Note that we use "bhs", since we want to match
00081    (unsigned) -4096 .. 0xffffffff.  Using "ble" would match
00082    -4096 .. -2**31.  */
00083 #define       PSEUDO(name, syscall_name, args) \
00084   ENTRY       (name)                                    @ \
00085   DOARGS_##args                                         @ \
00086   movu.w SYS_ify (syscall_name),$r9                     @ \
00087   break       13                                        @ \
00088   cmps.w -4096,$r10                              @ \
00089   bhs  0f                                        @ \
00090   nop                                            @ \
00091   UNDOARGS_return_##args
00092 
00093 /* Ouch!  We have to remember not to use "ret" in assembly-code.
00094    ("Luckily", mnemonics are case-insensitive.)
00095    Note that we assume usage is exactly:
00096        PSEUDO (...)
00097        ret
00098        PSEUDO_END (...)
00099    so we can put all payload into PSEUDO (except for error handling).  */
00100 
00101 #define ret
00102 
00103 #define       PSEUDO_END(name) \
00104 0:                                               @ \
00105   SETUP_PIC                                      @ \
00106   PLTJUMP (syscall_error)                        @ \
00107   END (name)
00108 
00109 #define       PSEUDO_NOERRNO(name, syscall_name, args) \
00110   ENTRY       (name)                                    @ \
00111   DOARGS_##args                                         @ \
00112   movu.w SYS_ify (syscall_name),$r9                     @ \
00113   break       13                                        @ \
00114   UNDOARGS_return_##args
00115 
00116 #define ret_NOERRNO
00117 
00118 #define       PSEUDO_END_NOERRNO(name) \
00119   END (name)
00120 
00121 #define DOARGS_0
00122 #define DOARGS_1
00123 #define DOARGS_2
00124 #define DOARGS_3
00125 #define DOARGS_4
00126 #define DOARGS_5 \
00127   move [$sp],$mof
00128 
00129 /* To avoid allocating stack-space, we re-use the arg 5 (MOF) entry by
00130    storing SRP into it.  If called with too-few arguments, we will crash,
00131    but that will happen in the general case too.  */
00132 #define DOARGS_6 \
00133   DOARGS_5                                       @ \
00134   move $srp,[$sp]                                @ \
00135   move [$sp+4],$srp
00136 
00137 #define UNDOARGS_return_0 \
00138   Ret                                            @ \
00139   nop
00140 
00141 #define UNDOARGS_return_1 UNDOARGS_return_0
00142 #define UNDOARGS_return_2 UNDOARGS_return_0
00143 #define UNDOARGS_return_3 UNDOARGS_return_0
00144 #define UNDOARGS_return_4 UNDOARGS_return_0
00145 #define UNDOARGS_return_5 UNDOARGS_return_0
00146 
00147 /* We assume the following code will be "ret" and "PSEUDO_END".  */
00148 #define UNDOARGS_return_return_6 \
00149   jump [$sp]
00150 
00151 #else  /* not __ASSEMBLER__ */
00152 
00153 #undef INLINE_SYSCALL
00154 #define INLINE_SYSCALL(name, nr, args...) \
00155   ({                                      \
00156      unsigned long __sys_res;                    \
00157      register unsigned long __res asm ("r10");   \
00158      LOAD_ARGS_c_##nr (args)                     \
00159      register unsigned long __callno asm ("r9")  \
00160        = SYS_ify (name);                  \
00161      asm volatile (LOAD_ARGS_asm_##nr (args)     \
00162                  "break 13"               \
00163                  : "=r" (__res)           \
00164                  : ASM_ARGS_##nr (args)   \
00165                  : ASM_CLOBBER_##nr);            \
00166      __sys_res = __res;                          \
00167                                           \
00168      if (__sys_res >= (unsigned long) -4096)     \
00169        {                                  \
00170         __set_errno (- __sys_res);        \
00171         __sys_res = (unsigned long) -1;   \
00172        }                                  \
00173      (long int) __sys_res;                \
00174    })
00175 
00176 #define LOAD_ARGS_c_0()
00177 #define LOAD_ARGS_asm_0()
00178 #define ASM_CLOBBER_0 "memory"
00179 #define ASM_ARGS_0() "r" (__callno)
00180 
00181 #define LOAD_ARGS_c_1(r10) \
00182        LOAD_ARGS_c_0()                                         \
00183        register unsigned long __r10 __asm__ ("r10") = (unsigned long) (r10);
00184 #define LOAD_ARGS_asm_1(r10) LOAD_ARGS_asm_0 ()
00185 #define ASM_CLOBBER_1 ASM_CLOBBER_0
00186 #define ASM_ARGS_1(r10) ASM_ARGS_0 (), "0" (__r10)
00187 
00188 #define LOAD_ARGS_c_2(r10, r11) \
00189        LOAD_ARGS_c_1(r10)                               \
00190        register unsigned long __r11 __asm__ ("r11") = (unsigned long) (r11);
00191 #define LOAD_ARGS_asm_2(r10, r11) LOAD_ARGS_asm_1 (r10)
00192 #define ASM_CLOBBER_2 ASM_CLOBBER_1
00193 #define ASM_ARGS_2(r10, r11) ASM_ARGS_1 (r10), "r" (__r11)
00194 
00195 #define LOAD_ARGS_c_3(r10, r11, r12) \
00196        LOAD_ARGS_c_2(r10, r11)                                 \
00197        register unsigned long __r12 __asm__ ("r12") = (unsigned long) (r12);
00198 #define LOAD_ARGS_asm_3(r10, r11, r12) LOAD_ARGS_asm_2 (r10, r11)
00199 #define ASM_CLOBBER_3 ASM_CLOBBER_2
00200 #define ASM_ARGS_3(r10, r11, r12) ASM_ARGS_2 (r10, r11), "r" (__r12)
00201 
00202 #define LOAD_ARGS_c_4(r10, r11, r12, r13) \
00203        LOAD_ARGS_c_3(r10, r11, r12)                            \
00204        register unsigned long __r13 __asm__ ("r13") = (unsigned long) (r13);
00205 #define LOAD_ARGS_asm_4(r10, r11, r12, r13) LOAD_ARGS_asm_3 (r10, r11, r12)
00206 #define ASM_CLOBBER_4 ASM_CLOBBER_3
00207 #define ASM_ARGS_4(r10, r11, r12, r13) ASM_ARGS_3 (r10, r11, r12), "r" (__r13)
00208 
00209 #define LOAD_ARGS_c_5(r10, r11, r12, r13, mof) \
00210        LOAD_ARGS_c_4(r10, r11, r12, r13)
00211 #define LOAD_ARGS_asm_5(r10, r11, r12, r13, mof) \
00212        LOAD_ARGS_asm_4 (r10, r11, r12, r13) "move %6,$mof\n\t"
00213 #define ASM_CLOBBER_5 ASM_CLOBBER_4
00214 #define ASM_ARGS_5(r10, r11, r12, r13, mof) \
00215        ASM_ARGS_4 (r10, r11, r12, r13), "g" (mof)
00216 
00217 #define LOAD_ARGS_c_6(r10, r11, r12, r13, mof, srp)            \
00218        LOAD_ARGS_c_5(r10, r11, r12, r13, mof)
00219 #define LOAD_ARGS_asm_6(r10, r11, r12, r13, mof, srp)          \
00220        LOAD_ARGS_asm_5(r10, r11, r12, r13, mof)         \
00221        "move %7,$srp\n\t"
00222 #define ASM_CLOBBER_6 ASM_CLOBBER_5, "srp"
00223 #define ASM_ARGS_6(r10, r11, r12, r13, mof, srp) \
00224        ASM_ARGS_5 (r10, r11, r12, r13, mof), "g" (srp)
00225 
00226 #endif /* not __ASSEMBLER__ */