Blame sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h

Packit 6c4009
/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* Alan Modra <amodra@bigpond.net.au> rewrote the INLINE_SYSCALL macro */
Packit 6c4009
Packit 6c4009
#ifndef _LINUX_POWERPC_SYSDEP_H
Packit 6c4009
#define _LINUX_POWERPC_SYSDEP_H 1
Packit 6c4009
Packit 6c4009
#include <sysdeps/unix/sysv/linux/sysdep.h>
Packit 6c4009
#include <sysdeps/unix/powerpc/sysdep.h>
Packit 6c4009
#include <tls.h>
Packit 6c4009
Packit 6c4009
/* Define __set_errno() for INLINE_SYSCALL macro below.  */
Packit 6c4009
#ifndef __ASSEMBLER__
Packit 6c4009
#include <errno.h>
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* For Linux we can use the system call table in the header file
Packit 6c4009
	/usr/include/asm/unistd.h
Packit 6c4009
   of the kernel.  But these symbols do not follow the SYS_* syntax
Packit 6c4009
   so we have to redefine the `SYS_ify' macro here.  */
Packit 6c4009
#undef SYS_ify
Packit 6c4009
#define SYS_ify(syscall_name)	__NR_##syscall_name
Packit 6c4009
Packit 6c4009
#ifdef __ASSEMBLER__
Packit 6c4009
Packit 6c4009
/* This seems to always be the case on PPC.  */
Packit 6c4009
# define ALIGNARG(log2) log2
Packit 6c4009
# define ASM_SIZE_DIRECTIVE(name) .size name,.-name
Packit 6c4009
Packit 6c4009
#endif /* __ASSEMBLER__ */
Packit 6c4009
Packit 6c4009
/* This version is for internal uses when there is no desire
Packit 6c4009
   to set errno */
Packit 6c4009
#define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, type, nr, args...)   \
Packit 6c4009
  ({									      \
Packit 6c4009
    type sc_ret = ENOSYS;						      \
Packit 6c4009
									      \
Packit 6c4009
    __typeof (__vdso_##name) vdsop = __vdso_##name;			      \
Packit 6c4009
    PTR_DEMANGLE (vdsop);						      \
Packit 6c4009
    if (vdsop != NULL)							      \
Packit 6c4009
      sc_ret =								      \
Packit 6c4009
        INTERNAL_VSYSCALL_CALL_TYPE (vdsop, err, type, nr, ##args);	      \
Packit 6c4009
    else								      \
Packit 6c4009
      err = 1 << 28;							      \
Packit 6c4009
    sc_ret;								      \
Packit 6c4009
  })
Packit 6c4009
Packit 6c4009
/* List of system calls which are supported as vsyscalls.  */
Packit 6c4009
#define HAVE_CLOCK_GETRES_VSYSCALL	1
Packit 6c4009
#define HAVE_CLOCK_GETTIME_VSYSCALL	1
Packit 6c4009
#define HAVE_GETCPU_VSYSCALL		1
Packit 6c4009
Packit 6c4009
/* Define a macro which expands inline into the wrapper code for a system
Packit 6c4009
   call. This use is for internal calls that do not need to handle errors
Packit 6c4009
   normally. It will never touch errno. This returns just what the kernel
Packit 6c4009
   gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
Packit 6c4009
   the negation of the return value in the kernel gets reverted.  */
Packit 6c4009
Packit 6c4009
#define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, type, nr, args...)    \
Packit 6c4009
  ({									\
Packit 6c4009
    register void *r0  __asm__ ("r0");					\
Packit 6c4009
    register long int r3  __asm__ ("r3");				\
Packit 6c4009
    register long int r4  __asm__ ("r4");				\
Packit 6c4009
    register long int r5  __asm__ ("r5");				\
Packit 6c4009
    register long int r6  __asm__ ("r6");				\
Packit 6c4009
    register long int r7  __asm__ ("r7");				\
Packit 6c4009
    register long int r8  __asm__ ("r8");				\
Packit 6c4009
    register type rval  __asm__ ("r3");				        \
Packit 6c4009
    LOADARGS_##nr (funcptr, args);					\
Packit 6c4009
    __asm__ __volatile__						\
Packit 6c4009
      ("mtctr %0\n\t"							\
Packit 6c4009
       "bctrl\n\t"							\
Packit 6c4009
       "mfcr  %0\n\t"							\
Packit 6c4009
       "0:"								\
Packit 6c4009
       : "+r" (r0), "+r" (r3), "+r" (r4), "+r" (r5),  "+r" (r6),        \
Packit 6c4009
         "+r" (r7), "+r" (r8)						\
Packit 6c4009
       : : "r9", "r10", "r11", "r12", "cr0", "ctr", "lr", "memory");	\
Packit 6c4009
    err = (long int) r0;						\
Packit 6c4009
    __asm__ __volatile__ ("" : "=r" (rval) : "r" (r3));		        \
Packit 6c4009
    rval;								\
Packit 6c4009
  })
Packit 6c4009
Packit 6c4009
#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)		\
Packit 6c4009
  INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, long int, nr, args)
Packit 6c4009
Packit 6c4009
#undef INLINE_SYSCALL
Packit 6c4009
Packit 6c4009
/* This version is for kernels that implement system calls that
Packit 6c4009
   behave like function calls as far as register saving.  */
Packit 6c4009
#define INLINE_SYSCALL(name, nr, args...)				\
Packit 6c4009
  ({									\
Packit 6c4009
    INTERNAL_SYSCALL_DECL (sc_err);					\
Packit 6c4009
    long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args);	\
Packit 6c4009
    if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err))			\
Packit 6c4009
      {									\
Packit 6c4009
        __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));		\
Packit 6c4009
        sc_ret = -1L;							\
Packit 6c4009
      }									\
Packit 6c4009
    sc_ret;								\
Packit 6c4009
  })
Packit 6c4009
Packit 6c4009
/* Define a macro which expands inline into the wrapper code for a system
Packit 6c4009
   call. This use is for internal calls that do not need to handle errors
Packit 6c4009
   normally. It will never touch errno. This returns just what the kernel
Packit 6c4009
   gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
Packit 6c4009
   the negation of the return value in the kernel gets reverted.  */
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL
Packit 6c4009
#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
Packit 6c4009
  ({									\
Packit 6c4009
    register long int r0  __asm__ ("r0");				\
Packit 6c4009
    register long int r3  __asm__ ("r3");				\
Packit 6c4009
    register long int r4  __asm__ ("r4");				\
Packit 6c4009
    register long int r5  __asm__ ("r5");				\
Packit 6c4009
    register long int r6  __asm__ ("r6");				\
Packit 6c4009
    register long int r7  __asm__ ("r7");				\
Packit 6c4009
    register long int r8  __asm__ ("r8");				\
Packit 6c4009
    LOADARGS_##nr (name, ##args);					\
Packit 6c4009
    __asm__ __volatile__						\
Packit 6c4009
      ("sc\n\t"								\
Packit 6c4009
       "mfcr  %0\n\t"							\
Packit 6c4009
       "0:"								\
Packit 6c4009
       : "=&r" (r0),							\
Packit 6c4009
         "=&r" (r3), "=&r" (r4), "=&r" (r5),				\
Packit 6c4009
         "=&r" (r6), "=&r" (r7), "=&r" (r8)				\
Packit 6c4009
       : ASM_INPUT_##nr							\
Packit 6c4009
       : "r9", "r10", "r11", "r12",					\
Packit 6c4009
         "cr0", "ctr", "memory");					\
Packit 6c4009
	  err = r0;  \
Packit 6c4009
    r3;  \
Packit 6c4009
  })
Packit 6c4009
#define INTERNAL_SYSCALL(name, err, nr, args...)			\
Packit 6c4009
  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, args)
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_DECL
Packit 6c4009
#define INTERNAL_SYSCALL_DECL(err) long int err __attribute__ ((unused))
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_ERROR_P
Packit 6c4009
#define INTERNAL_SYSCALL_ERROR_P(val, err) \
Packit 6c4009
  ((void) (val), __builtin_expect ((err) & (1 << 28), 0))
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_ERRNO
Packit 6c4009
#define INTERNAL_SYSCALL_ERRNO(val, err)     (val)
Packit 6c4009
Packit 6c4009
#define LOADARGS_0(name, dummy) \
Packit 6c4009
	r0 = name
Packit 6c4009
#define LOADARGS_1(name, __arg1) \
Packit 6c4009
	long int arg1 = (long int) (__arg1); \
Packit 6c4009
	LOADARGS_0(name, 0); \
Packit 6c4009
	extern void __illegally_sized_syscall_arg1 (void); \
Packit 6c4009
	if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 8) \
Packit 6c4009
	  __illegally_sized_syscall_arg1 (); \
Packit 6c4009
	r3 = arg1
Packit 6c4009
#define LOADARGS_2(name, __arg1, __arg2) \
Packit 6c4009
	long int arg2 = (long int) (__arg2); \
Packit 6c4009
	LOADARGS_1(name, __arg1); \
Packit 6c4009
	extern void __illegally_sized_syscall_arg2 (void); \
Packit 6c4009
	if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 8) \
Packit 6c4009
	  __illegally_sized_syscall_arg2 (); \
Packit 6c4009
	r4 = arg2
Packit 6c4009
#define LOADARGS_3(name, __arg1, __arg2, __arg3) \
Packit 6c4009
	long int arg3 = (long int) (__arg3); \
Packit 6c4009
	LOADARGS_2(name, __arg1, __arg2); \
Packit 6c4009
	extern void __illegally_sized_syscall_arg3 (void); \
Packit 6c4009
	if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 8) \
Packit 6c4009
	  __illegally_sized_syscall_arg3 (); \
Packit 6c4009
	r5 = arg3
Packit 6c4009
#define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \
Packit 6c4009
	long int arg4 = (long int) (__arg4); \
Packit 6c4009
	LOADARGS_3(name, __arg1, __arg2, __arg3); \
Packit 6c4009
	extern void __illegally_sized_syscall_arg4 (void); \
Packit 6c4009
	if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 8) \
Packit 6c4009
	  __illegally_sized_syscall_arg4 (); \
Packit 6c4009
	r6 = arg4
Packit 6c4009
#define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \
Packit 6c4009
	long int arg5 = (long int) (__arg5); \
Packit 6c4009
	LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \
Packit 6c4009
	extern void __illegally_sized_syscall_arg5 (void); \
Packit 6c4009
	if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 8) \
Packit 6c4009
	  __illegally_sized_syscall_arg5 (); \
Packit 6c4009
	r7 = arg5
Packit 6c4009
#define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \
Packit 6c4009
	long int arg6 = (long int) (__arg6); \
Packit 6c4009
	LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \
Packit 6c4009
	extern void __illegally_sized_syscall_arg6 (void); \
Packit 6c4009
	if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 8) \
Packit 6c4009
	  __illegally_sized_syscall_arg6 (); \
Packit 6c4009
	r8 = arg6
Packit 6c4009
Packit 6c4009
#define ASM_INPUT_0 "0" (r0)
Packit 6c4009
#define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)
Packit 6c4009
#define ASM_INPUT_2 ASM_INPUT_1, "2" (r4)
Packit 6c4009
#define ASM_INPUT_3 ASM_INPUT_2, "3" (r5)
Packit 6c4009
#define ASM_INPUT_4 ASM_INPUT_3, "4" (r6)
Packit 6c4009
#define ASM_INPUT_5 ASM_INPUT_4, "5" (r7)
Packit 6c4009
#define ASM_INPUT_6 ASM_INPUT_5, "6" (r8)
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Pointer mangling support.  */
Packit 6c4009
#if IS_IN (rtld)
Packit 6c4009
/* We cannot use the thread descriptor because in ld.so we use setjmp
Packit 6c4009
   earlier than the descriptor is initialized.  */
Packit 6c4009
#else
Packit 6c4009
# ifdef __ASSEMBLER__
Packit 6c4009
#  define PTR_MANGLE(reg, tmpreg) \
Packit 6c4009
	ld	tmpreg,POINTER_GUARD(r13); \
Packit 6c4009
	xor	reg,tmpreg,reg
Packit 6c4009
#  define PTR_MANGLE2(reg, tmpreg) \
Packit 6c4009
	xor	reg,tmpreg,reg
Packit 6c4009
#  define PTR_MANGLE3(destreg, reg, tmpreg) \
Packit 6c4009
	ld	tmpreg,POINTER_GUARD(r13); \
Packit 6c4009
	xor	destreg,tmpreg,reg
Packit 6c4009
#  define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
Packit 6c4009
#  define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg)
Packit 6c4009
#  define PTR_DEMANGLE3(destreg, reg, tmpreg) PTR_MANGLE3 (destreg, reg, tmpreg)
Packit 6c4009
# else
Packit 6c4009
#  define PTR_MANGLE(var) \
Packit 6c4009
  (var) = (__typeof (var)) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
Packit 6c4009
#  define PTR_DEMANGLE(var)	PTR_MANGLE (var)
Packit 6c4009
# endif
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* In the PowerPC64 ABI, the unadorned F_GETLK* opcodes should be used
Packit 6c4009
   even by largefile64 code.  */
Packit 6c4009
#define FCNTL_ADJUST_CMD(__cmd)				\
Packit 6c4009
  ({ int cmd_ = (__cmd);				\
Packit 6c4009
     if (cmd_ >= F_GETLK64 && cmd_ <= F_SETLKW64)	\
Packit 6c4009
       cmd_ -= F_GETLK64 - F_GETLK;			\
Packit 6c4009
     cmd_; })
Packit 6c4009
Packit 6c4009
Packit 6c4009
#endif /* linux/powerpc/powerpc64/sysdep.h */