about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/alpha/dl-machine.h4
-rw-r--r--sysdeps/generic/dl-tls.c27
-rw-r--r--sysdeps/generic/libc-tls.c18
-rw-r--r--sysdeps/i386/dl-machine.h10
-rw-r--r--sysdeps/ia64/dl-machine.h41
-rw-r--r--sysdeps/ia64/dl-tls.h4
-rw-r--r--sysdeps/ia64/libc-tls.c37
-rw-r--r--sysdeps/powerpc/powerpc64/sysdep.h2
-rw-r--r--sysdeps/sh/dl-machine.h4
-rw-r--r--sysdeps/unix/sysv/linux/arm/socket.S41
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/bits/stat.h6
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/ftruncate64.c75
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/pread.c85
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/pread64.c84
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite.c85
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/pwrite64.c85
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S39
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list4
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h131
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/truncate64.c76
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/sys/procfs.h5
-rw-r--r--sysdeps/unix/sysv/linux/sh/sysdep.h7
22 files changed, 756 insertions, 114 deletions
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index 711bf10fdd..3a182ca99f 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  Alpha version.
-   Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1996-2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
@@ -610,8 +610,8 @@ elf_machine_rela (struct link_map *map,
 #else
 	  if (sym_map)
 	    {
-	      *reloc_addr = sym_value - sym_map->l_tls_offset;
 	      CHECK_STATIC_TLS (map, sym_map);
+	      *reloc_addr = sym_value - sym_map->l_tls_offset;
 	    }
 #endif
 	}
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c
index 6791d765ee..0afe379ae6 100644
--- a/sysdeps/generic/dl-tls.c
+++ b/sysdeps/generic/dl-tls.c
@@ -282,9 +282,18 @@ internal_function
 _dl_allocate_tls_storage (void)
 {
   void *result;
+  size_t size = GL(dl_tls_static_size);
+
+# if TLS_DTV_AT_TP
+  /* Memory layout is:
+     [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ]
+			  ^ This should be returned.  */
+  size += (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1)
+	  & ~(GL(dl_tls_static_align) - 1);
+# endif
 
   /* Allocate a correctly aligned chunk of memory.  */
-  result = __libc_memalign (GL(dl_tls_static_align), GL(dl_tls_static_size));
+  result = __libc_memalign (GL(dl_tls_static_align), size);
   if (__builtin_expect (result != NULL, 0))
     {
       /* Allocate the DTV.  */
@@ -292,12 +301,20 @@ _dl_allocate_tls_storage (void)
 
 # if TLS_TCB_AT_TP
       /* The TCB follows the TLS blocks.  */
-      result = (char *) result + GL(dl_tls_static_size) - TLS_TCB_SIZE;
-# endif
+      result = (char *) result + size - TLS_TCB_SIZE;
 
       /* Clear the TCB data structure.  We can't ask the caller (i.e.
 	 libpthread) to do it, because we will initialize the DTV et al.  */
       memset (result, 0, TLS_TCB_SIZE);
+# elif TLS_DTV_AT_TP
+      result = (char *) result + size - GL(dl_tls_static_size);
+
+      /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it.
+	 We can't ask the caller (i.e. libpthread) to do it, because we will
+	 initialize the DTV et al.  */
+      memset ((char *) result - TLS_PRE_TCB_SIZE, 0,
+	      TLS_PRE_TCB_SIZE + TLS_TCB_SIZE);
+# endif
 
       result = allocate_dtv (result);
       if (result == NULL)
@@ -405,6 +422,10 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
 # if TLS_TCB_AT_TP
       /* The TCB follows the TLS blocks.  Back up to free the whole block.  */
       tcb -= GL(dl_tls_static_size) - TLS_TCB_SIZE;
+# elif TLS_DTV_AT_TP
+      /* Back up the TLS_PRE_TCB_SIZE bytes.  */
+      tcb -= (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1)
+	     & ~(GL(dl_tls_static_align) - 1);
 # endif
       free (tcb);
     }
diff --git a/sysdeps/generic/libc-tls.c b/sysdeps/generic/libc-tls.c
index 1461bf8543..b5ecc36436 100644
--- a/sysdeps/generic/libc-tls.c
+++ b/sysdeps/generic/libc-tls.c
@@ -1,5 +1,5 @@
 /* Initialization code for TLS in statically linked application.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 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
@@ -134,15 +134,16 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
 	  break;
 	}
 
+#ifdef TLS_INIT_TP_EXPENSIVE
   if (memsz == 0 && tcbsize <= TLS_INIT_TCB_SIZE)
     {
       /* We do not need a TLS block and no thread descriptor.  */
-#ifdef NONTLS_INIT_TP
+# ifdef NONTLS_INIT_TP
       NONTLS_INIT_TP;
-#endif
+# endif
       return;
     }
-
+#endif
 
   /* We have to set up the TCB block which also (possibly) contains
      'errno'.  Therefore we avoid 'malloc' which might touch 'errno'.
@@ -157,8 +158,10 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
   tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
   tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
 # elif TLS_DTV_AT_TP
-  tlsblock = __sbrk (roundup (tcbsize, align) + memsz + max_align
-		     + GL(dl_tls_static_size));
+  tcb_offset = roundup (tcbsize, align ?: 1);
+  tlsblock = __sbrk (tcb_offset + memsz + max_align
+		     + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
+  tlsblock += TLS_PRE_TCB_SIZE;
 # else
   /* In case a model with a different layout for the TCB and DTV
      is defined add another #elif here and in the following #ifs.  */
@@ -179,7 +182,6 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
 			   - roundup (memsz, align ?: 1));
   static_map.l_tls_offset = roundup (memsz, align ?: 1);
 # elif TLS_DTV_AT_TP
-  tcb_offset = roundup (tcbsize, align);
   static_dtv[2].pointer = (char *) tlsblock + tcb_offset;
   static_map.l_tls_offset = tcb_offset;
 # else
@@ -222,6 +224,8 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
 
 # if TLS_TCB_AT_TP
   memsz += tcbsize;
+# elif TLS_DTV_AT_TP
+  memsz += tcb_offset;
 # endif
 
   init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index add6f8e01b..fa5076e3e5 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  i386 version.
-   Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc.
+   Copyright (C) 1995-2002, 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
@@ -445,8 +445,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	     block we subtract the offset from that of the TLS block.  */
 	  if (sym != NULL)
 	    {
-	      *reloc_addr += sym_map->l_tls_offset - sym->st_value;
 	      CHECK_STATIC_TLS (map, sym_map);
+	      *reloc_addr += sym_map->l_tls_offset - sym->st_value;
 	    }
 # endif
 	  break;
@@ -460,8 +460,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	     thread pointer.  */
 	  if (sym != NULL)
 	    {
-	      *reloc_addr += sym->st_value - sym_map->l_tls_offset;
 	      CHECK_STATIC_TLS (map, sym_map);
+	      *reloc_addr += sym->st_value - sym_map->l_tls_offset;
 	    }
 # endif
 	  break;
@@ -555,20 +555,20 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 	     It is a positive value which will be subtracted from the
 	     thread pointer.  To get the variable position in the TLS
 	     block we subtract the offset from that of the TLS block.  */
+	  CHECK_STATIC_TLS (map, sym_map);
 	  *reloc_addr
 	    = (sym == NULL ? 0 : sym_map->l_tls_offset - sym->st_value)
 	      + reloc->r_addend;
-	  CHECK_STATIC_TLS (map, sym_map);
 	  break;
 	case R_386_TLS_TPOFF:
 	  /* The offset is negative, forward from the thread pointer.  */
 	  /* We know the offset of object the symbol is contained in.
 	     It is a negative value which will be added to the
 	     thread pointer.  */
+	  CHECK_STATIC_TLS (map, sym_map);
 	  *reloc_addr
 	    = (sym == NULL ? 0 : sym->st_value - sym_map->l_tls_offset)
 	      + reloc->r_addend;
-	  CHECK_STATIC_TLS (map, sym_map);
 	  break;
 # endif	/* use TLS */
 # ifndef RESOLVE_CONFLICT_FIND_MAP
diff --git a/sysdeps/ia64/dl-machine.h b/sysdeps/ia64/dl-machine.h
index 16a1ff3000..f5eeef67db 100644
--- a/sysdeps/ia64/dl-machine.h
+++ b/sysdeps/ia64/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  IA-64 version.
-   Copyright (C) 1995,1996,1997,2000,2001,2002 Free Software Foundation, Inc.
+   Copyright (C) 1995-1997, 2000-2002, 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
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <link.h>
 #include <errno.h>
-
+#include <tls.h>
 
 /* Translate a processor specific dynamic tag to the index
    in l_info array.  */
@@ -448,14 +448,22 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 #define RTLD_START_SPECIAL_INIT /* nothing */
 #endif
 
-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
-   PLT entries should not be allowed to define the value.
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or TLS
+   variable, so undefined references should not be allowed to define the
+   value.
    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
    of the main executable's symbols, as for a COPY reloc, which we don't
    use.  */
-/* ??? Ignore IPLTMSB for now.  */
+/* ??? Ignore *MSB for now.  */
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+#define elf_machine_type_class(type) \
+  (((type) == R_IA64_IPLTLSB || (type) == R_IA64_DTPMOD64LSB		      \
+    || (type) == R_IA64_DTPREL64LSB || (type) == R_IA64_TPREL64LSB)	      \
+   * ELF_RTYPE_CLASS_PLT)
+#else
 #define elf_machine_type_class(type) \
   (((type) == R_IA64_IPLTLSB) * ELF_RTYPE_CLASS_PLT)
+#endif
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT	 R_IA64_IPLTLSB
@@ -557,8 +565,7 @@ elf_machine_rela (struct link_map *map,
       /* RESOLVE_MAP() will return NULL if it fail to locate the symbol.  */
       if ((sym_map = RESOLVE_MAP (&sym, version, r_type)))
         {
-	  value = sym ? sym_map->l_addr + sym->st_value : 0;
-	  value += reloc->r_addend;
+	  value = sym_map->l_addr + sym->st_value + reloc->r_addend;
 
 	  if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DIR64LSB))
 	    ;/* No adjustment.  */
@@ -571,6 +578,26 @@ elf_machine_rela (struct link_map *map,
 	    value = __ia64_make_fptr (sym_map, sym, value);
 	  else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_PCREL64LSB))
 	    value -= (Elf64_Addr) reloc_addr & -16;
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || defined USE___THREAD)
+	  else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DTPMOD64LSB))
+# ifdef RTLD_BOOTSTRAP
+	    /* During startup the dynamic linker is always index 1.  */
+	    value = 1;
+# else	      
+	    /* Get the information from the link map returned by the
+	       resolv function.  */
+	    value = sym_map->l_tls_modid;
+	  else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_DTPREL64LSB))
+	    value -= sym_map->l_addr;
+# endif
+	  else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_TPREL64LSB))
+	    {
+# ifndef RTLD_BOOTSTRAP
+	      CHECK_STATIC_TLS (map, sym_map);
+# endif
+	      value += sym_map->l_tls_offset - sym_map->l_addr;
+	    }
+#endif
 	  else
 	    assert (! "unexpected dynamic reloc type");
 	}
diff --git a/sysdeps/ia64/dl-tls.h b/sysdeps/ia64/dl-tls.h
index 738c820a44..26f3d2adf1 100644
--- a/sysdeps/ia64/dl-tls.h
+++ b/sysdeps/ia64/dl-tls.h
@@ -1,5 +1,5 @@
 /* Thread-local storage handling in the ELF dynamic linker.  IA-64 version.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 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
@@ -26,3 +26,5 @@
 
 /* We have no tls_index type.  */
 #define DONT_USE_TLS_INDEX	1
+
+extern void *__tls_get_addr (size_t m, size_t offset);
diff --git a/sysdeps/ia64/libc-tls.c b/sysdeps/ia64/libc-tls.c
new file mode 100644
index 0000000000..f1df4cd12e
--- /dev/null
+++ b/sysdeps/ia64/libc-tls.c
@@ -0,0 +1,37 @@
+/* Thread-local storage handling in the ELF dynamic linker.  IA-64 version.
+   Copyright (C) 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
+   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 <sysdeps/generic/libc-tls.c>
+
+#if USE_TLS
+
+/* On IA-64, as it lacks linker optimizations, __tls_get_addr can be
+   called even in statically linked binaries.
+   In this case module must be always 1 and PT_TLS segment
+   exist in the binary, otherwise it would not link.  */
+
+void *
+__tls_get_addr (size_t m, size_t offset)
+{
+  dtv_t *dtv = THREAD_DTV ();
+  return (char *) dtv[1].pointer + offset;
+}
+
+#endif
+
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
index c25df403b6..9b895df3f0 100644
--- a/sysdeps/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
@@ -216,7 +216,7 @@ LT_LABELSUFFIX(name,_name_end): ; \
   DO_CALL (SYS_ify (syscall_name));
 
 #define PSEUDO_RET \
-    bnslr; \
+    bnslr+; \
     b JUMPTARGET(__syscall_error)
 
 #define ret PSEUDO_RET
diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h
index c6d094d26a..6607d9b2f8 100644
--- a/sysdeps/sh/dl-machine.h
+++ b/sysdeps/sh/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  SH version.
-   Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 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
@@ -579,10 +579,10 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 	     It is a positive value which will be added to the thread
 	     pointer.  To get the variable position in the TLS block
 	     we add the offset from that of the TLS block.  */
+	  CHECK_STATIC_TLS (map, sym_map);
 	  *reloc_addr
 	    = ((sym == NULL ? 0 : sym_map->l_tls_offset + sym->st_value)
 	       + reloc->r_addend);
-	  CHECK_STATIC_TLS (map, sym_map);
 # endif
 	  break;
 #endif	/* use TLS */
diff --git a/sysdeps/unix/sysv/linux/arm/socket.S b/sysdeps/unix/sysv/linux/arm/socket.S
index f4ccc5465d..3e93ceb6d2 100644
--- a/sysdeps/unix/sysv/linux/arm/socket.S
+++ b/sysdeps/unix/sysv/linux/arm/socket.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 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
@@ -16,7 +16,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <sysdep.h>
+#include <sysdep-cancel.h>
 #include <socketcall.h>
 
 #define P(a, b) P2(a, b)
@@ -53,6 +53,10 @@
 #define NARGS 3			/* If we were called with no wrapper, this is really socket() */
 #endif
 
+#if defined NEED_CANCELLATION && defined CENABLE
+	PSEUDO_PROLOGUE
+#endif
+
 .globl __socket
 ENTRY (__socket)
 	/* This code previously moved sp into ip and stored the args using
@@ -68,6 +72,15 @@ ENTRY (__socket)
 	/* Push args onto the stack.  */
 	P(PUSHARGS_,NARGS)
 
+#if defined NEED_CANCELLATION && defined CENABLE
+#ifdef PIC
+	SINGLE_THREAD_P_PIC(r3)
+#else
+	SINGLE_THREAD_P
+#endif
+	bne 1f
+#endif
+
         /* Do the system call trap.  */
 	mov a1, $P(SOCKOP_,socket)
 	mov a2, sp
@@ -81,6 +94,30 @@ ENTRY (__socket)
 	RETINSTR(movcc, pc, r14)
 	b PLTJMP(SYSCALL_ERROR)
 
+#if defined NEED_CANCELLATION && defined CENABLE
+1:
+	str lr, [sp, #-4]!
+	CENABLE
+	mov ip, r0
+
+	mov r0, #P(SOCKOP_,socket)
+	add r1, sp, #4
+	swi SYS_ify(socketcall)
+
+	str r0, [sp, #-4]!
+	mov r0, ip
+	CDISABLE
+	ldr r0, [sp], #4
+	ldr lr, [sp], #4
+
+	P(POPARGS_,NARGS)
+
+	/* r0 is < 0 if there was an error.  */
+	cmn r0, $124
+	RETINSTR(movcc, pc, r14)
+	b PLTJMP(SYSCALL_ERROR)
+#endif
+
 PSEUDO_END (__socket)
 
 weak_alias (__socket, socket)
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/stat.h b/sysdeps/unix/sysv/linux/powerpc/bits/stat.h
index 3cff5c8d81..cf3dd1c293 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/stat.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/stat.h
@@ -27,11 +27,11 @@
 #define _STAT_VER_LINUX_OLD	1
 #define _STAT_VER_KERNEL	1
 #define _STAT_VER_SVR4		2
+#define _STAT_VER_LINUX	  3
 #if __WORDSIZE == 32
-# define _STAT_VER_LINUX	3
-# define _STAT_VER		_STAT_VER_LINUX	/* The one defined below.  */
+# define _STAT_VER		_STAT_VER_LINUX
 #else
-# define _STAT_VER		_STAT_VER_KERNEL /* The one defined below.  */
+# define _STAT_VER		_STAT_VER_KERNEL
 #endif
 
 /* Versions of the `xmknod' interface.  */
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
diff --git a/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h b/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h
index e42f848bc5..1322971da4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h
+++ b/sysdeps/unix/sysv/linux/powerpc/sys/procfs.h
@@ -32,6 +32,10 @@
 
 __BEGIN_DECLS
 
+/* These definitions are normally provided by ucontext.h via 
+   asm/sigcontext.h, asm/ptrace.h, and asm/elf.h.  Otherwise we define 
+   them here.  */ 
+#ifndef __PPC64_ELF_H
 #define ELF_NGREG       48      /* includes nip, msr, lr, etc. */
 #define ELF_NFPREG      33      /* includes fpscr */
 #define ELF_NVRREG      33      /* includes vscr */
@@ -41,6 +45,7 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
 typedef double elf_fpreg_t;
 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+#endif
 
 /* gcc 3.1 and newer support __uint128_t.  */
 #if !__GNUC_PREREQ(3,1)
diff --git a/sysdeps/unix/sysv/linux/sh/sysdep.h b/sysdeps/unix/sysv/linux/sh/sysdep.h
index ee39121755..75557f554e 100644
--- a/sysdeps/unix/sysv/linux/sh/sysdep.h
+++ b/sysdeps/unix/sysv/linux/sh/sysdep.h
@@ -66,7 +66,12 @@
   END (name)
 
 #ifndef PIC
-# define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */
+# define SYSCALL_ERROR_HANDLER	\
+	mov.l 0f,r1; \
+	jmp @r1; \
+	 mov r0,r4; \
+	.align 2; \
+     0: .long __syscall_error
 #else
 # if RTLD_PRIVATE_ERRNO
 #  define SYSCALL_ERROR_HANDLER	\