diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/powerpc/powerpc64')
9 files changed, 584 insertions, 80 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c new file mode 100644 index 0000000000..f733001abe --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c @@ -0,0 +1,75 @@ +/* Copyright (C) 1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#include "kernel-features.h" + +#ifdef __NR_ftruncate64 +#ifndef __ASSUME_TRUNCATE64_SYSCALL +/* The variable is shared between all wrappers around *truncate64 calls. */ +extern int have_no_truncate64; +#endif + + +/* Truncate the file FD refers to to LENGTH bytes. */ +int +__ftruncate64 (fd, length) + int fd; + off64_t length; +{ +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (! have_no_truncate64) +#endif + { +#ifndef __ASSUME_TRUNCATE64_SYSCALL + int saved_errno = errno; +#endif + int result = INLINE_SYSCALL (ftruncate64, 2, fd, length); + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (result != -1 || errno != ENOSYS) +#endif + return result; + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + __set_errno (saved_errno); + have_no_truncate64 = 1; +#endif + } + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if ((off_t) length != length) + { + __set_errno (EINVAL); + return -1; + } + return __ftruncate (fd, (off_t) length); +#endif +} +weak_alias (__ftruncate64, ftruncate64) + +#else +/* Use the generic implementation. */ +# include <sysdeps/generic/ftruncate64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c new file mode 100644 index 0000000000..d5b77e0b57 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <unistd.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 + +# if __ASSUME_PREAD_SYSCALL == 0 +static ssize_t __emulate_pread (int fd, void *buf, size_t count, + off_t offset) internal_function; +# endif + + +ssize_t +__libc_pread (fd, buf, count, offset) + int fd; + void *buf; + size_t count; + off_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +strong_alias (__libc_pread, __pread) +weak_alias (__libc_pread, pread) + +# define __libc_pread(fd, buf, count, offset) \ + static internal_function __emulate_pread (fd, buf, count, offset) +#endif + +#if __ASSUME_PREAD_SYSCALL == 0 +# include <sysdeps/posix/pread.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c new file mode 100644 index 0000000000..9bbe389420 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <unistd.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#if defined __NR_pread || __ASSUME_PREAD_SYSCALL > 0 + +# if __ASSUME_PREAD_SYSCALL == 0 +static ssize_t __emulate_pread64 (int fd, void *buf, size_t count, + off64_t offset) internal_function; +# endif + + +ssize_t +__libc_pread64 (fd, buf, count, offset) + int fd; + void *buf; + size_t count; + off64_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread64 (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PREAD_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pread64 (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +weak_alias (__libc_pread64, __pread64) +weak_alias (__libc_pread64, pread64) + +# define __libc_pread64(fd, buf, count, offset) \ + static internal_function __emulate_pread64 (fd, buf, count, offset) +#endif + +# if __ASSUME_PREAD_SYSCALL == 0 +# include <sysdeps/posix/pread64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c new file mode 100644 index 0000000000..96b72e18a5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <unistd.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 + +# if __ASSUME_PWRITE_SYSCALL == 0 +static ssize_t __emulate_pwrite (int fd, const void *buf, size_t count, + off_t offset) internal_function; +# endif + + +ssize_t +__libc_pwrite (fd, buf, count, offset) + int fd; + const void *buf; + size_t count; + off_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +strong_alias (__libc_pwrite, __pwrite) +weak_alias (__libc_pwrite, pwrite) + +# define __libc_pwrite(fd, buf, count, offset) \ + static internal_function __emulate_pwrite (fd, buf, count, offset) +#endif + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include <sysdeps/posix/pwrite.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c new file mode 100644 index 0000000000..9e68acdf08 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <unistd.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#if defined __NR_pwrite || __ASSUME_PWRITE_SYSCALL > 0 + +# if __ASSUME_PWRITE_SYSCALL == 0 +static ssize_t __emulate_pwrite64 (int fd, const void *buf, size_t count, + off64_t offset) internal_function; +# endif + + +ssize_t +__libc_pwrite64 (fd, buf, count, offset) + int fd; + const void *buf; + size_t count; + off64_t offset; +{ + ssize_t result; + + if (SINGLE_THREAD_P) + { + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite64 (fd, buf, count, offset); +# endif + + return result; + } + + int oldtype = LIBC_CANCEL_ASYNC (); + + result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, + offset); +# if __ASSUME_PWRITE_SYSCALL == 0 + if (result == -1 && errno == ENOSYS) + /* No system call available. Use the emulation. */ + result = __emulate_pwrite64 (fd, buf, count, offset); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +weak_alias (__libc_pwrite64, __pwrite64) +libc_hidden_weak (__pwrite64) +weak_alias (__libc_pwrite64, pwrite64) + +# define __libc_pwrite64(fd, buf, count, offset) \ + static internal_function __emulate_pwrite64 (fd, buf, count, offset) +#endif + +#if __ASSUME_PWRITE_SYSCALL == 0 +# include <sysdeps/posix/pwrite64.c> +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S index 08696c3cf3..a4e27c3611 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1999, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -39,7 +39,7 @@ #define NARGS 3 #endif -#define stackblock 48 /* offset to parm save area */ +#define stackblock 80 /* offset to socket parm area. */ #ifndef socket /* If this is just socket.S leave it alone! */ @@ -51,7 +51,7 @@ .text ENTRY(__socket) - stdu r1,-112(r1) + stdu r1,-144(r1) #if NARGS >= 1 std r3,stackblock(r1) #endif @@ -79,11 +79,40 @@ ENTRY(__socket) #if NARGS >= 9 #error too many arguments! #endif - li r3,P(SOCKOP_,socket) + +#if defined NEED_CANCELLATION && defined CENABLE + SINGLE_THREAD_P + bne- .Lsocket_cancel +#endif + + li r3,P(SOCKOP_,socket) + addi r4,r1,stackblock + DO_CALL(SYS_ify(socketcall)) + addi r1,r1,144 + PSEUDO_RET + +#if defined NEED_CANCELLATION && defined CENABLE +.Lsocket_cancel: + mflr r9 + std r9,144+16(r1) + CENABLE + std r3,72(r1) + li r3,P(SOCKOP_,socket) addi r4,r1,stackblock DO_CALL(SYS_ify(socketcall)) - addi r1,r1,112 + mfcr r0 + std r3,64(r1) + std r0,8(r1) + ld r3,72(r1) + CDISABLE + ld r4,144+16(r1) + ld r0,8(r1) + ld r3,64(r1) + mtlr r4 + mtcr r0 + addi r1,r1,144 PSEUDO_RET +#endif PSEUDO_END (__socket) weak_alias (__socket, socket) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list index d8303a60f6..5266c4f59f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list @@ -16,7 +16,6 @@ rt_sigtimedwait - rt_sigtimedwait i:pppi __syscall_rt_sigtimedwait s_fcntl fcntl fcntl i:iiF __syscall_fcntl s_fcntl64 fcntl64 fcntl64 i:iiF __syscall_fcntl64 s_fstat64 fxstat64 fstat64 i:ip __syscall_fstat64 -s_ftruncate64 ftruncate64 ftruncate64 i:iii __syscall_ftruncate64 s_getcwd getcwd getcwd i:pi __syscall_getcwd s_getdents getdents getdents i:ipi __syscall_getdents s_getdents64 getdents getdents64 i:ipi __syscall_getdents64 @@ -26,10 +25,8 @@ s_getrlimit getrlimit getrlimit i:ip __syscall_getrlimit s_lstat64 lxstat64 lstat64 i:sp __syscall_lstat64 s_mmap2 mmap64 mmap2 b:aniiii __syscall_mmap2 s_poll poll poll i:pii __syscall_poll -s_pread64 pread64 pread i:ibnii __syscall_pread s_ptrace ptrace ptrace i:iipp __syscall_ptrace s_putpmsg putpmsg putpmsg i:ippii __syscall_putpmsg -s_pwrite64 pwrite64 pwrite i:ibnii __syscall_pwrite s_reboot reboot reboot i:iii __syscall_reboot s_setrlimit setrlimit setrlimit i:ip __syscall_setrlimit s_sigaction sigaction sigaction i:ipp __syscall_sigaction @@ -38,7 +35,6 @@ s_sigprocmask sigprocmask sigprocmask i:ipp __syscall_sigprocmask s_sigsuspend sigsuspend sigsuspend i:iii __syscall_sigsuspend s_stat64 xstat64 stat64 i:sp __syscall_stat64 s_sysctl sysctl _sysctl i:p __syscall__sysctl -s_truncate64 truncate64 truncate64 i:sii __syscall_truncate64 s_ugetrlimit getrlimit ugetrlimit i:ip __syscall_ugetrlimit s_ustat ustat ustat i:ip __syscall_ustat s_vfork vfork vfork i: __syscall_vfork diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h index d56ff877ac..d37be2ef4f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h @@ -69,65 +69,7 @@ #endif /* __ASSEMBLER__ */ #undef INLINE_SYSCALL -#if 1 -#define INLINE_SYSCALL(name, nr, args...) \ - ({ \ - DECLARGS_##nr; \ - long ret, err; \ - LOADARGS_##nr(name, args); \ - __asm __volatile ("sc\n\t" \ - "mfcr %1\n\t" \ - : "=r" (r3), "=r" (err) \ - : ASM_INPUT_##nr \ - : "cc", "memory"); \ - ret = r3; \ - if (err & 1 << 28) \ - { \ - __set_errno (ret); \ - ret = -1L; \ - } \ - ret; \ - }) - -#define DECLARGS_0 register long r0 __asm__ ("r0"); \ - register long r3 __asm__ ("r3") -#define DECLARGS_1 DECLARGS_0 -#define DECLARGS_2 DECLARGS_1; register long r4 __asm__ ("r4") -#define DECLARGS_3 DECLARGS_2; register long r5 __asm__ ("r5") -#define DECLARGS_4 DECLARGS_3; register long r6 __asm__ ("r6") -#define DECLARGS_5 DECLARGS_4; register long r7 __asm__ ("r7") -#define DECLARGS_6 DECLARGS_5; register long r8 __asm__ ("r8") - -#define LOADARGS_0(name) \ - r0 = __NR_##name -#define LOADARGS_1(name, arg1) \ - LOADARGS_0(name); \ - r3 = (long) (arg1) -#define LOADARGS_2(name, arg1, arg2) \ - LOADARGS_1(name, arg1); \ - r4 = (long) (arg2) -#define LOADARGS_3(name, arg1, arg2, arg3) \ - LOADARGS_2(name, arg1, arg2); \ - r5 = (long) (arg3) -#define LOADARGS_4(name, arg1, arg2, arg3, arg4) \ - LOADARGS_3(name, arg1, arg2, arg3); \ - r6 = (long) (arg4) -#define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ - LOADARGS_4(name, arg1, arg2, arg3, arg4); \ - r7 = (long) (arg5) -#define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ - LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ - r8 = (long) (arg6) - -#define ASM_INPUT_0 "r" (r0) -#define ASM_INPUT_1 ASM_INPUT_0, "0" (r3) -#define ASM_INPUT_2 ASM_INPUT_1, "r" (r4) -#define ASM_INPUT_3 ASM_INPUT_2, "r" (r5) -#define ASM_INPUT_4 ASM_INPUT_3, "r" (r6) -#define ASM_INPUT_5 ASM_INPUT_4, "r" (r7) -#define ASM_INPUT_6 ASM_INPUT_5, "r" (r8) -#else /* This version is for kernels that implement system calls that behave like function calls as far as register saving. */ #define INLINE_SYSCALL(name, nr, args...) \ @@ -149,40 +91,89 @@ : ASM_INPUT_##nr \ : "r9", "r10", "r11", "r12", \ "fr0", "fr1", "fr2", "fr3", \ - "fr4", "fr5", "fr6", "fr7", \ - "fr8", "fr9", "fr10", "fr11", \ - "fr12", "fr13", \ - "ctr", "lr", \ - "cr0", "cr1", "cr5", "cr6", "cr7", \ - "memory"); \ + "fr4", "fr5", "fr6", "fr7", \ + "fr8", "fr9", "fr10", "fr11", \ + "fr12", "fr13", \ + "ctr", "lr", \ + "cr0", "cr1", "cr5", "cr6", "cr7", \ + "memory"); \ ret = r3; \ - if (err & 1 << 28) \ + if (__builtin_expect ((err & (1 << 28)), 0)) \ { \ - __set_errno (ret); \ - ret = -1L; \ + __set_errno (ret); \ + ret = -1L; \ } \ ret; \ }) -#define LOADARGS_0(name) \ +/* Define a macro which expands inline into the wrapper code for a system + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. This returns just what the kernel + gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set) + the negation of the return value in the kernel gets reverted. */ + +# undef INTERNAL_SYSCALL +# define INTERNAL_SYSCALL(name, nr, args...) \ + ({ \ + register long r0 __asm__ ("r0"); \ + register long r3 __asm__ ("r3"); \ + register long r4 __asm__ ("r4"); \ + register long r5 __asm__ ("r5"); \ + register long r6 __asm__ ("r6"); \ + register long r7 __asm__ ("r7"); \ + register long r8 __asm__ ("r8"); \ + LOADARGS_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc\n\t" \ + "bns+ 0f\n\t" \ + "neg %1,%1\n" \ + "0:" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), \ + "=&r" (r6), "=&r" (r7), "=&r" (r8) \ + : ASM_INPUT_##nr \ + : "r9", "r10", "r11", "r12", \ + "cr0", "ctr", "memory"); \ + (int) r3; \ + }) + +# undef INTERNAL_SYSCALL_ERROR_P +# define INTERNAL_SYSCALL_ERROR_P(val) ((unsigned long) (val) >= 0xfffffffffffff001u) + +# undef INTERNAL_SYSCALL_ERRNO +# define INTERNAL_SYSCALL_ERRNO(val) (-(val)) + +#define LOADARGS_0(name, dummy) \ r0 = __NR_##name #define LOADARGS_1(name, arg1) \ - LOADARGS_0(name); \ + LOADARGS_0(name, 0); \ + extern void __illegally_sized_syscall_##name##_arg1 (void); \ + if (sizeof (arg1) > 8) __illegally_sized_syscall_##name##_arg1 (); \ r3 = (long) (arg1) #define LOADARGS_2(name, arg1, arg2) \ LOADARGS_1(name, arg1); \ + extern void __illegally_sized_syscall_##name##_arg2 (void); \ + if (sizeof (arg2) > 8) __illegally_sized_syscall_##name##_arg2 (); \ r4 = (long) (arg2) #define LOADARGS_3(name, arg1, arg2, arg3) \ LOADARGS_2(name, arg1, arg2); \ + extern void __illegally_sized_syscall_##name##_arg3 (void); \ + if (sizeof (arg3) > 8) __illegally_sized_syscall_##name##_arg3 (); \ r5 = (long) (arg3) #define LOADARGS_4(name, arg1, arg2, arg3, arg4) \ LOADARGS_3(name, arg1, arg2, arg3); \ + extern void __illegally_sized_syscall_##name##_arg4 (void); \ + if (sizeof (arg4) > 8) __illegally_sized_syscall_##name##_arg4 (); \ r6 = (long) (arg4) #define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ LOADARGS_4(name, arg1, arg2, arg3, arg4); \ + extern void __illegally_sized_syscall_##name##_arg5 (void); \ + if (sizeof (arg5) > 8) __illegally_sized_syscall_##name##_arg5 (); \ r7 = (long) (arg5) #define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ + extern void __illegally_sized_syscall_##name##_arg6 (void); \ + if (sizeof (arg6) > 8) __illegally_sized_syscall_##name##_arg6 (); \ r8 = (long) (arg6) #define ASM_INPUT_0 "0" (r0) @@ -193,6 +184,4 @@ #define ASM_INPUT_5 ASM_INPUT_4, "5" (r7) #define ASM_INPUT_6 ASM_INPUT_5, "6" (r8) -#endif - #endif /* linux/powerpc/powerpc64/sysdep.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c new file mode 100644 index 0000000000..cbf0669082 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> + +#include <sysdep.h> +#include <sys/syscall.h> +#include <bp-checks.h> + +#include "kernel-features.h" + +#ifdef __NR_truncate64 +#ifndef __ASSUME_TRUNCATE64_SYSCALL +/* The variable is shared between all wrappers around *truncate64 calls. */ +int have_no_truncate64; +#endif + + +/* Truncate the file FD refers to to LENGTH bytes. */ +int +truncate64 (path, length) + const char *path; + off64_t length; +{ +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (! have_no_truncate64) +#endif + { +#ifndef __ASSUME_TRUNCATE64_SYSCALL + int saved_errno = errno; +#endif + int result = INLINE_SYSCALL (truncate64, 2, CHECK_STRING (path), + length); + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if (result != -1 || errno != ENOSYS) +#endif + return result; + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + __set_errno (saved_errno); + have_no_truncate64 = 1; +#endif + } + +#ifndef __ASSUME_TRUNCATE64_SYSCALL + if ((off_t) length != length) + { + __set_errno (EINVAL); + return -1; + } + return truncate (path, (off_t) length); +#endif +} + +#else +/* Use the generic implementation. */ +# include <sysdeps/generic/truncate64.c> +#endif |