(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
microblaze/
sysdep.h
       1  /* Copyright (C) 2000-2023 Free Software Foundation, Inc.
       2  
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _LINUX_MICROBLAZE_SYSDEP_H
      20  #define _LINUX_MICROBLAZE_SYSDEP_H 1
      21  
      22  #include <sysdeps/unix/sysdep.h>
      23  #include <sysdeps/unix/sysv/linux/sysdep.h>
      24  #include <sysdeps/microblaze/sysdep.h>
      25  
      26  /* Defines RTLD_PRIVATE_ERRNO.  */
      27  #include <dl-sysdep.h>
      28  
      29  #include <tls.h>
      30  
      31  /* In order to get __set_errno() definition in INLINE_SYSCALL.  */
      32  #ifndef __ASSEMBLER__
      33  # include <errno.h>
      34  #endif
      35  
      36  /* For Linux we can use the system call table in the header file
      37      /usr/include/asm/unistd.h
      38     of the kernel.  But these symbols do not follow the SYS_* syntax
      39     so we have to redefine the `SYS_ify' macro here.  */
      40  #undef SYS_ify
      41  #define SYS_ify(syscall_name)   __NR_##syscall_name
      42  
      43  #ifdef __ASSEMBLER__
      44  
      45  /* In microblaze ABI function call arguments are passed in registers
      46     r5...r10. The return value is stored in r3 (or r3:r4 register pair).
      47     Linux syscall uses the same convention with the addition that the
      48     syscall number is passed in r12. To enter the kernel "brki r14,8"
      49     instruction is used.
      50     None of the abovementioned registers are presumed across function call
      51     or syscall.
      52  */
      53  /* Linux uses a negative return value to indicate syscall errors, unlike
      54     most Unices, which use the condition codes' carry flag.
      55  
      56     Since version 2.1 the return value of a system call might be negative
      57     even if the call succeeded.  E.g., the `lseek' system call might return
      58     a large offset.  Therefore we must not anymore test for < 0, but test
      59     for a real error by making sure the value in %d0 is a real error
      60     number.  Linus said he will make sure the no syscall returns a value
      61     in -1 .. -4095 as a valid result so we can safely test with -4095.  */
      62  
      63  /* We don't want the label for the error handler to be visible in the symbol
      64     table when we define it here.  */
      65  # undef SYSCALL_ERROR_LABEL
      66  # ifdef PIC
      67  #  define SYSCALL_ERROR_LABEL 0f
      68  # else
      69  #  define SYSCALL_ERROR_LABEL __syscall_error
      70  # endif
      71  
      72  # undef PSEUDO
      73  # define PSEUDO(name, syscall_name, args)           \
      74    .text;                                            \
      75    ENTRY (name)                                      \
      76      DO_CALL (syscall_name, args);                   \
      77      addik r12,r0,-4095;                             \
      78      cmpu  r12,r12,r3;                               \
      79      bgei  r12,SYSCALL_ERROR_LABEL;
      80  
      81  # undef PSEUDO_END
      82  # define PSEUDO_END(name)                           \
      83    SYSCALL_ERROR_HANDLER;                            \
      84    END (name)
      85  
      86  # undef PSEUDO_NOERRNO
      87  # define PSEUDO_NOERRNO(name, syscall_name, args)   \
      88    .text;                                            \
      89    ENTRY (name)                                      \
      90      DO_CALL (syscall_name, args);
      91  
      92  # undef PSEUDO_END_NOERRNO
      93  # define PSEUDO_END_NOERRNO(name)                   \
      94    END (name)
      95  
      96  /* The function has to return the error code.  */
      97  # undef  PSEUDO_ERRVAL
      98  # define PSEUDO_ERRVAL(name, syscall_name, args)    \
      99    .text;                                            \
     100    ENTRY (name)                                      \
     101      DO_CALL (syscall_name, args);                   \
     102  
     103  # undef  PSEUDO_END_ERRVAL
     104  # define PSEUDO_END_ERRVAL(name)                    \
     105    END (name)
     106  
     107  # define ret_NOERRNO                                \
     108    rtsd r15,8; addk r0,r0,r0;
     109  
     110  # define ret_ERRVAL                                 \
     111    rtsd r15,8; rsubk r3,r3,r0;
     112  
     113  # ifdef PIC
     114  #  define SYSCALL_ERROR_LABEL_DCL 0
     115  #  if RTLD_PRIVATE_ERRNO
     116  #   define SYSCALL_ERROR_HANDLER                    \
     117  SYSCALL_ERROR_LABEL_DCL:                            \
     118      mfs   r12,rpc;                                  \
     119      addik r12,r12,_GLOBAL_OFFSET_TABLE_+8;          \
     120      lwi   r12,r12,rtld_errno@GOT;                   \
     121      rsubk r3,r3,r0;                                 \
     122      swi   r3,r12,0;                                 \
     123      rtsd  r15,8;                                    \
     124      addik r3,r0,-1;
     125  #  else /* !RTLD_PRIVATE_ERRNO.  */
     126  /* Store (-r3) into errno through the GOT.  */
     127  #   if defined _LIBC_REENTRANT
     128  #    define SYSCALL_ERROR_HANDLER                   \
     129  SYSCALL_ERROR_LABEL_DCL:                            \
     130      addik r1,r1,-16;                                \
     131      swi   r15,r1,0;                                 \
     132      swi   r20,r1,8;                                 \
     133      rsubk r3,r3,r0;                                 \
     134      swi   r3,r1,12;                                 \
     135      mfs   r20,rpc;                                  \
     136      addik r20,r20,_GLOBAL_OFFSET_TABLE_+8;          \
     137      brlid r15,__errno_location@PLT;                 \
     138      nop;                                            \
     139      lwi   r4,r1,12;                                 \
     140      swi   r4,r3,0;                                  \
     141      lwi   r20,r1,8;                                 \
     142      lwi   r15,r1,0;                                 \
     143      addik r1,r1,16;                                 \
     144      rtsd  r15,8;                                    \
     145      addik r3,r0,-1;
     146  #   else /* !_LIBC_REENTRANT.  */
     147  #    define SYSCALL_ERROR_HANDLER                   \
     148  SYSCALL_ERROR_LABEL_DCL:                            \
     149      mfs   r12,rpc;                                  \
     150      addik r12,r12,_GLOBAL_OFFSET_TABLE_+8;          \
     151      lwi   r12,r12,errno@GOT;                        \
     152      rsubk r3,r3,r0;                                 \
     153      swi   r3,r12,0;                                 \
     154      rtsd  r15,8;                                    \
     155      addik r3,r0,-1;
     156  #    endif /* _LIBC_REENTRANT.  */
     157  # endif /* RTLD_PRIVATE_ERRNO.  */
     158  # else
     159  #  define SYSCALL_ERROR_HANDLER  /* Nothing here; code in sysdep.S is used.  */
     160  # endif /* PIC.  */
     161  
     162  # define DO_CALL(syscall_name, args)                \
     163      addik r12,r0,SYS_ify (syscall_name);            \
     164      brki  r14,8;                                    \
     165      addk  r0,r0,r0;
     166  
     167  #else /* not __ASSEMBLER__ */
     168  
     169  /* Define a macro which expands inline into the wrapper code for a system
     170     call.  This use is for internal calls that do not need to handle errors
     171     normally.  It will never touch errno.  This returns just what the kernel
     172     gave back.  */
     173  # undef INTERNAL_SYSCALL
     174  # define INTERNAL_SYSCALL(name, nr, args...)                    \
     175    inline_syscall##nr(SYS_ify(name), args)
     176  
     177  # undef INTERNAL_SYSCALL_NCS
     178  # define INTERNAL_SYSCALL_NCS(name, nr, args...)                \
     179    inline_syscall##nr(name, args)
     180  
     181  # define SYSCALL_CLOBBERS_6 "r11", "r4", "memory"
     182  # define SYSCALL_CLOBBERS_5 "r10", SYSCALL_CLOBBERS_6
     183  # define SYSCALL_CLOBBERS_4 "r9", SYSCALL_CLOBBERS_5
     184  # define SYSCALL_CLOBBERS_3 "r8", SYSCALL_CLOBBERS_4
     185  # define SYSCALL_CLOBBERS_2 "r7", SYSCALL_CLOBBERS_3
     186  # define SYSCALL_CLOBBERS_1 "r6", SYSCALL_CLOBBERS_2
     187  # define SYSCALL_CLOBBERS_0 "r5", SYSCALL_CLOBBERS_1
     188  
     189  # define inline_syscall0(name,dummy)                                          \
     190    ({                                                                          \
     191      register long int __ret __asm__("r3");                                    \
     192      register long int __r12 __asm__("r12") = name;                            \
     193      __asm__ __volatile__( "brki r14,8; nop;"                                  \
     194        : "=r"(__ret)                                                           \
     195        : "r"(__r12)                                                            \
     196        : SYSCALL_CLOBBERS_0 ); __ret;                                          \
     197    })
     198  
     199  # define inline_syscall1(name,arg1)                                           \
     200    ({                                                                          \
     201      long int __arg1 = (long int) (arg1);                                      \
     202      register long int __ret __asm__("r3");                                    \
     203      register long int __r12 __asm__("r12") = name;                            \
     204      register long int __r5 __asm__("r5") = __arg1;                            \
     205      __asm__ __volatile__( "brki r14,8; nop;"                                  \
     206        : "=r"(__ret)                                                           \
     207        : "r"(__r5), "r"(__r12)                                                 \
     208        : SYSCALL_CLOBBERS_1 ); __ret;                                          \
     209    })
     210  
     211  # define inline_syscall2(name,arg1,arg2)                                      \
     212    ({                                                                          \
     213      long int __arg1 = (long int) (arg1);                                      \
     214      long int __arg2 = (long int) (arg2);                                      \
     215      register long int __ret __asm__("r3");                                    \
     216      register long int __r12 __asm__("r12") = name;                            \
     217      register long int __r5 __asm__("r5") = __arg1;                            \
     218      register long int __r6 __asm__("r6") = __arg2;                            \
     219      __asm__ __volatile__( "brki r14,8; nop;"                                  \
     220        : "=r"(__ret)                                                           \
     221        : "r"(__r5), "r"(__r6), "r"(__r12)                                      \
     222        : SYSCALL_CLOBBERS_2 ); __ret;                                          \
     223    })
     224  
     225  
     226  # define inline_syscall3(name,arg1,arg2,arg3)                                 \
     227    ({                                                                          \
     228      long int __arg1 = (long int) (arg1);                                      \
     229      long int __arg2 = (long int) (arg2);                                      \
     230      long int __arg3 = (long int) (arg3);                                      \
     231      register long int __ret __asm__("r3");                                    \
     232      register long int __r12 __asm__("r12") = name;                            \
     233      register long int __r5 __asm__("r5") = __arg1;                            \
     234      register long int __r6 __asm__("r6") = __arg2;                            \
     235      register long int __r7 __asm__("r7") = __arg3;                            \
     236      __asm__ __volatile__( "brki r14,8; nop;"                                  \
     237        : "=r"(__ret)                                                           \
     238        : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r12)                           \
     239        : SYSCALL_CLOBBERS_3 ); __ret;                                          \
     240    })
     241  
     242  
     243  # define inline_syscall4(name,arg1,arg2,arg3,arg4)                            \
     244    ({                                                                          \
     245      long int __arg1 = (long int) (arg1);                                      \
     246      long int __arg2 = (long int) (arg2);                                      \
     247      long int __arg3 = (long int) (arg3);                                      \
     248      long int __arg4 = (long int) (arg4);                                      \
     249      register long int __ret __asm__("r3");                                    \
     250      register long int __r12 __asm__("r12") = name;                            \
     251      register long int __r5 __asm__("r5") = __arg1;                            \
     252      register long int __r6 __asm__("r6") = __arg2;                            \
     253      register long int __r7 __asm__("r7") = __arg3;                            \
     254      register long int __r8 __asm__("r8") = __arg4;                            \
     255      __asm__ __volatile__( "brki r14,8; nop;"                                  \
     256        : "=r"(__ret)                                                           \
     257        : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r12)                 \
     258        : SYSCALL_CLOBBERS_4 ); __ret;                                          \
     259    })
     260  
     261  
     262  # define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5)                       \
     263    ({                                                                          \
     264      long int __arg1 = (long int) (arg1);                                      \
     265      long int __arg2 = (long int) (arg2);                                      \
     266      long int __arg3 = (long int) (arg3);                                      \
     267      long int __arg4 = (long int) (arg4);                                      \
     268      long int __arg5 = (long int) (arg5);                                      \
     269      register long int __ret __asm__("r3");                                    \
     270      register long int __r12 __asm__("r12") = name;                            \
     271      register long int __r5 __asm__("r5") = __arg1;                            \
     272      register long int __r6 __asm__("r6") = __arg2;                            \
     273      register long int __r7 __asm__("r7") = __arg3;                            \
     274      register long int __r8 __asm__("r8") = __arg4;                            \
     275      register long int __r9 __asm__("r9") = __arg5;                            \
     276      __asm__ __volatile__( "brki r14,8; nop;"                                  \
     277        : "=r"(__ret)                                                           \
     278        : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r9), "r"(__r12)      \
     279        : SYSCALL_CLOBBERS_5 ); __ret;                                          \
     280    })
     281  
     282  
     283  # define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6)                  \
     284    ({                                                                          \
     285      long int __arg1 = (long int) (arg1);                                      \
     286      long int __arg2 = (long int) (arg2);                                      \
     287      long int __arg3 = (long int) (arg3);                                      \
     288      long int __arg4 = (long int) (arg4);                                      \
     289      long int __arg5 = (long int) (arg5);                                      \
     290      long int __arg6 = (long int) (arg6);                                      \
     291      register long int __ret __asm__("r3");                                    \
     292      register long int __r12 __asm__("r12") = name;                            \
     293      register long int __r5 __asm__("r5") = __arg1;                            \
     294      register long int __r6 __asm__("r6") = __arg2;                            \
     295      register long int __r7 __asm__("r7") = __arg3;                            \
     296      register long int __r8 __asm__("r8") = __arg4;                            \
     297      register long int __r9 __asm__("r9") = __arg5;                            \
     298      register long int __r10 __asm__("r10") = __arg6;                          \
     299      __asm__ __volatile__( "brki r14,8; nop;"                                  \
     300        : "=r"(__ret)                                                           \
     301        : "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r9), "r"(__r10),     \
     302        "r"(__r12)                                                              \
     303        : SYSCALL_CLOBBERS_6 ); __ret;                                          \
     304    })
     305  
     306  
     307  #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
     308  #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
     309  
     310  #endif /* not __ASSEMBLER__ */
     311  
     312  #endif /* _LINUX_MICROBLAZE_SYSDEP_H */