(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
ia64/
sysdep.h
       1  /* Copyright (C) 1999-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #ifndef _LINUX_IA64_SYSDEP_H
      19  #define _LINUX_IA64_SYSDEP_H 1
      20  
      21  #include <sysdeps/unix/sysdep.h>
      22  #include <sysdeps/unix/sysv/linux/sysdep.h>
      23  #include <sysdeps/ia64/sysdep.h>
      24  #include <dl-sysdep.h>
      25  #include <tls.h>
      26  #include <asm/break.h>
      27  
      28  /* In order to get __set_errno() definition in INLINE_SYSCALL.  */
      29  #ifndef __ASSEMBLER__
      30  #include <errno.h>
      31  #endif
      32  
      33  /* As of GAS v2.4.90.0.7, including a ".align" directive inside a
      34     function will cause bad unwind info to be emitted (GAS doesn't know
      35     how to account for the padding introduced by the .align directive).
      36     Turning on this macro will work around this bug by introducing the
      37     necessary padding explicitly. */
      38  #define GAS_ALIGN_BREAKS_UNWIND_INFO
      39  
      40  /* For Linux we can use the system call table in the header file
      41  	/usr/include/asm/unistd.h
      42     of the kernel.  But these symbols do not follow the SYS_* syntax
      43     so we have to redefine the `SYS_ify' macro here.  */
      44  #undef SYS_ify
      45  #define SYS_ify(syscall_name)	__NR_##syscall_name
      46  
      47  #ifndef IA64_USE_NEW_STUB
      48  # if defined USE_DL_SYSINFO && IS_IN (libc)
      49  #  define IA64_USE_NEW_STUB 1
      50  # else
      51  #  define IA64_USE_NEW_STUB 0
      52  # endif
      53  #endif
      54  #if IA64_USE_NEW_STUB && !USE_DL_SYSINFO
      55  # error IA64_USE_NEW_STUB needs USE_DL_SYSINFO
      56  #endif
      57  
      58  #ifdef __ASSEMBLER__
      59  
      60  #undef CALL_MCOUNT
      61  #ifdef PROF
      62  # define CALL_MCOUNT							\
      63  	.data;								\
      64  1:	data8 0;	/* XXX fixme: use .xdata8 once labels work */	\
      65  	.previous;							\
      66  	.prologue;							\
      67  	.save ar.pfs, r40;						\
      68  	alloc out0 = ar.pfs, 8, 0, 4, 0;				\
      69  	mov out1 = gp;							\
      70  	.save rp, out2;							\
      71  	mov out2 = rp;							\
      72  	.body;								\
      73  	;;								\
      74  	addl out3 = @ltoff(1b), gp;					\
      75  	br.call.sptk.many rp = _mcount					\
      76  	;;
      77  #else
      78  # define CALL_MCOUNT	/* Do nothing. */
      79  #endif
      80  
      81  /* Linux uses a negative return value to indicate syscall errors, unlike
      82     most Unices, which use the condition codes' carry flag.
      83  
      84     Since version 2.1 the return value of a system call might be negative
      85     even if the call succeeded.  E.g., the `lseek' system call might return
      86     a large offset.  Therefore we must not anymore test for < 0, but test
      87     for a real error by making sure the value in %d0 is a real error
      88     number.  Linus said he will make sure the no syscall returns a value
      89     in -1 .. -4095 as a valid result so we can safely test with -4095.  */
      90  
      91  /* We don't want the label for the error handler to be visible in the symbol
      92     table when we define it here.  */
      93  #undef SYSCALL_ERROR_LABEL
      94  #define SYSCALL_ERROR_LABEL __syscall_error
      95  
      96  #undef PSEUDO
      97  #define	PSEUDO(name, syscall_name, args)	\
      98    ENTRY(name)					\
      99      DO_CALL (SYS_ify(syscall_name));		\
     100  	cmp.eq p6,p0=-1,r10;			\
     101  (p6)	br.cond.spnt.few __syscall_error;
     102  
     103  #define DO_CALL_VIA_BREAK(num)			\
     104  	mov r15=num;				\
     105  	break __IA64_BREAK_SYSCALL
     106  
     107  #if IA64_USE_NEW_STUB
     108  # ifdef SHARED
     109  #  define DO_CALL(num)				\
     110  	.prologue;				\
     111  	adds r2 = SYSINFO_OFFSET, r13;;		\
     112  	ld8 r2 = [r2];				\
     113  	.save ar.pfs, r11;			\
     114  	mov r11 = ar.pfs;;			\
     115  	.body;					\
     116  	mov r15 = num;				\
     117  	mov b7 = r2;				\
     118  	br.call.sptk.many b6 = b7;;		\
     119  	.restore sp;				\
     120  	mov ar.pfs = r11;			\
     121  	.prologue;				\
     122  	.body
     123  # else /* !SHARED */
     124  #  define DO_CALL(num)				\
     125  	.prologue;				\
     126  	mov r15 = num;				\
     127  	movl r2 = _dl_sysinfo;;			\
     128  	ld8 r2 = [r2];				\
     129  	.save ar.pfs, r11;			\
     130  	mov r11 = ar.pfs;;			\
     131  	.body;					\
     132  	mov b7 = r2;				\
     133  	br.call.sptk.many b6 = b7;;		\
     134  	.restore sp;				\
     135  	mov ar.pfs = r11;			\
     136  	.prologue;				\
     137  	.body
     138  # endif
     139  #else
     140  # define DO_CALL(num)				DO_CALL_VIA_BREAK(num)
     141  #endif
     142  
     143  #undef PSEUDO_END
     144  #define PSEUDO_END(name)	.endp C_SYMBOL_NAME(name);
     145  
     146  #undef PSEUDO_NOERRNO
     147  #define	PSEUDO_NOERRNO(name, syscall_name, args)	\
     148    ENTRY(name)						\
     149      DO_CALL (SYS_ify(syscall_name));
     150  
     151  #undef PSEUDO_END_NOERRNO
     152  #define PSEUDO_END_NOERRNO(name)	.endp C_SYMBOL_NAME(name);
     153  
     154  #undef PSEUDO_ERRVAL
     155  #define	PSEUDO_ERRVAL(name, syscall_name, args)	\
     156    ENTRY(name)					\
     157      DO_CALL (SYS_ify(syscall_name));		\
     158  	cmp.eq p6,p0=-1,r10;			\
     159  (p6)	mov r10=r8;
     160  
     161  
     162  #undef PSEUDO_END_ERRVAL
     163  #define PSEUDO_END_ERRVAL(name)	.endp C_SYMBOL_NAME(name);
     164  
     165  #undef END
     166  #define END(name)						\
     167  	.size	C_SYMBOL_NAME(name), . - C_SYMBOL_NAME(name) ;	\
     168  	.endp	C_SYMBOL_NAME(name)
     169  
     170  #define ret			br.ret.sptk.few b0
     171  #define ret_NOERRNO		ret
     172  #define ret_ERRVAL		ret
     173  
     174  #else /* not __ASSEMBLER__ */
     175  
     176  #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
     177  #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
     178  
     179  #define BREAK_INSN_1(num) "break " #num ";;\n\t"
     180  #define BREAK_INSN(num) BREAK_INSN_1(num)
     181  
     182  /* On IA-64 we have stacked registers for passing arguments.  The
     183     "out" registers end up being the called function's "in"
     184     registers.
     185  
     186     Also, since we have plenty of registers we have two return values
     187     from a syscall.  r10 is set to -1 on error, whilst r8 contains the
     188     (non-negative) errno on error or the return value on success.
     189   */
     190  
     191  #if IA64_USE_NEW_STUB
     192  
     193  # define INTERNAL_SYSCALL_NCS(name, nr, args...)			      \
     194  ({									      \
     195      LOAD_ARGS_##nr (args)						      \
     196      register long _r8 __asm ("r8");					      \
     197      register long _r10 __asm ("r10");					      \
     198      register long _r15 __asm ("r15") = name;				      \
     199      register void *_b7 __asm ("b7") = ((tcbhead_t *)__thread_self)->__private;\
     200      LOAD_REGS_##nr							      \
     201      /*									      \
     202       * Don't specify any unwind info here.  We mark ar.pfs as		      \
     203       * clobbered.  This will force the compiler to save ar.pfs		      \
     204       * somewhere and emit appropriate unwind info for that save.	      \
     205       */									      \
     206      __asm __volatile ("br.call.sptk.many b6=%0;;\n"			      \
     207  		      : "=b"(_b7), "=r" (_r8), "=r" (_r10), "=r" (_r15)	      \
     208  			ASM_OUTARGS_##nr				      \
     209  		      : "0" (_b7), "3" (_r15) ASM_ARGS_##nr		      \
     210  		      : "memory", "ar.pfs" ASM_CLOBBERS_##nr);		      \
     211      _r10 == -1 ? -_r8 : _r8;						      \
     212  })
     213  
     214  #else /* !IA64_USE_NEW_STUB */
     215  
     216  # define INTERNAL_SYSCALL_NCS(name, nr, args...)		\
     217  ({								\
     218      LOAD_ARGS_##nr (args)					\
     219      register long _r8 asm ("r8");				\
     220      register long _r10 asm ("r10");				\
     221      register long _r15 asm ("r15") = name;			\
     222      LOAD_REGS_##nr						\
     223      __asm __volatile (BREAK_INSN (__IA64_BREAK_SYSCALL)		\
     224  		      : "=r" (_r8), "=r" (_r10), "=r" (_r15)	\
     225  			ASM_OUTARGS_##nr			\
     226  		      : "2" (_r15) ASM_ARGS_##nr		\
     227  		      : "memory" ASM_CLOBBERS_##nr);		\
     228      _r10 == -1 ? -_r8 : _r8;					\
     229  })
     230  
     231  #endif /* !IA64_USE_NEW_STUB */
     232  
     233  #define INTERNAL_SYSCALL(name, nr, args...)	\
     234    INTERNAL_SYSCALL_NCS (__NR_##name, nr, ##args)
     235  
     236  #define LOAD_ARGS_0()
     237  #define LOAD_REGS_0
     238  #define LOAD_ARGS_1(a1)					\
     239    long _arg1 = (long) (a1);				\
     240    LOAD_ARGS_0 ()
     241  #define LOAD_REGS_1					\
     242    register long _out0 asm ("out0") = _arg1;		\
     243    LOAD_REGS_0
     244  #define LOAD_ARGS_2(a1, a2)				\
     245    long _arg2 = (long) (a2);				\
     246    LOAD_ARGS_1 (a1)
     247  #define LOAD_REGS_2					\
     248    register long _out1 asm ("out1") = _arg2;		\
     249    LOAD_REGS_1
     250  #define LOAD_ARGS_3(a1, a2, a3)				\
     251    long _arg3 = (long) (a3);				\
     252    LOAD_ARGS_2 (a1, a2)
     253  #define LOAD_REGS_3					\
     254    register long _out2 asm ("out2") = _arg3;		\
     255    LOAD_REGS_2
     256  #define LOAD_ARGS_4(a1, a2, a3, a4)			\
     257    long _arg4 = (long) (a4);				\
     258    LOAD_ARGS_3 (a1, a2, a3)
     259  #define LOAD_REGS_4					\
     260    register long _out3 asm ("out3") = _arg4;		\
     261    LOAD_REGS_3
     262  #define LOAD_ARGS_5(a1, a2, a3, a4, a5)			\
     263    long _arg5 = (long) (a5);				\
     264    LOAD_ARGS_4 (a1, a2, a3, a4)
     265  #define LOAD_REGS_5					\
     266    register long _out4 asm ("out4") = _arg5;		\
     267    LOAD_REGS_4
     268  #define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)		\
     269    long _arg6 = (long) (a6);	    			\
     270    LOAD_ARGS_5 (a1, a2, a3, a4, a5)
     271  #define LOAD_REGS_6					\
     272    register long _out5 asm ("out5") = _arg6;		\
     273    LOAD_REGS_5
     274  
     275  #define ASM_OUTARGS_0
     276  #define ASM_OUTARGS_1	ASM_OUTARGS_0, "=r" (_out0)
     277  #define ASM_OUTARGS_2	ASM_OUTARGS_1, "=r" (_out1)
     278  #define ASM_OUTARGS_3	ASM_OUTARGS_2, "=r" (_out2)
     279  #define ASM_OUTARGS_4	ASM_OUTARGS_3, "=r" (_out3)
     280  #define ASM_OUTARGS_5	ASM_OUTARGS_4, "=r" (_out4)
     281  #define ASM_OUTARGS_6	ASM_OUTARGS_5, "=r" (_out5)
     282  
     283  #if IA64_USE_NEW_STUB
     284  #define ASM_ARGS_0
     285  #define ASM_ARGS_1	ASM_ARGS_0, "4" (_out0)
     286  #define ASM_ARGS_2	ASM_ARGS_1, "5" (_out1)
     287  #define ASM_ARGS_3	ASM_ARGS_2, "6" (_out2)
     288  #define ASM_ARGS_4	ASM_ARGS_3, "7" (_out3)
     289  #define ASM_ARGS_5	ASM_ARGS_4, "8" (_out4)
     290  #define ASM_ARGS_6	ASM_ARGS_5, "9" (_out5)
     291  #else
     292  #define ASM_ARGS_0
     293  #define ASM_ARGS_1	ASM_ARGS_0, "3" (_out0)
     294  #define ASM_ARGS_2	ASM_ARGS_1, "4" (_out1)
     295  #define ASM_ARGS_3	ASM_ARGS_2, "5" (_out2)
     296  #define ASM_ARGS_4	ASM_ARGS_3, "6" (_out3)
     297  #define ASM_ARGS_5	ASM_ARGS_4, "7" (_out4)
     298  #define ASM_ARGS_6	ASM_ARGS_5, "8" (_out5)
     299  #endif
     300  
     301  #define ASM_CLOBBERS_0	ASM_CLOBBERS_1, "out0"
     302  #define ASM_CLOBBERS_1	ASM_CLOBBERS_2, "out1"
     303  #define ASM_CLOBBERS_2	ASM_CLOBBERS_3, "out2"
     304  #define ASM_CLOBBERS_3	ASM_CLOBBERS_4, "out3"
     305  #define ASM_CLOBBERS_4	ASM_CLOBBERS_5, "out4"
     306  #define ASM_CLOBBERS_5	ASM_CLOBBERS_6, "out5"
     307  #define ASM_CLOBBERS_6_COMMON	, "out6", "out7",			\
     308    /* Non-stacked integer registers, minus r8, r10, r15.  */		\
     309    "r2", "r3", "r9", "r11", "r13", "r14", "r16", "r17", "r18",		\
     310    "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",	\
     311    "r28", "r29", "r30", "r31",						\
     312    /* Predicate registers.  */						\
     313    "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",	\
     314    /* Non-rotating fp registers.  */					\
     315    "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",	\
     316    /* Branch registers.  */						\
     317    "b6"
     318  
     319  #if IA64_USE_NEW_STUB
     320  # define ASM_CLOBBERS_6	ASM_CLOBBERS_6_COMMON
     321  #else
     322  # define ASM_CLOBBERS_6	ASM_CLOBBERS_6_COMMON , "b7"
     323  #endif
     324  
     325  #endif /* not __ASSEMBLER__ */
     326  
     327  #endif /* linux/ia64/sysdep.h */