about summary refs log tree commit diff
path: root/sysdeps/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc')
-rw-r--r--sysdeps/powerpc/Dist1
-rw-r--r--sysdeps/powerpc/Makefile3
-rw-r--r--sysdeps/powerpc/__longjmp.S82
-rw-r--r--sysdeps/powerpc/__math.h19
-rw-r--r--sysdeps/powerpc/bsd-_setjmp.S2
-rw-r--r--sysdeps/powerpc/bsd-setjmp.S2
-rw-r--r--sysdeps/powerpc/dl-machine.h638
-rw-r--r--sysdeps/powerpc/fclrexcpt.c35
-rw-r--r--sysdeps/powerpc/fegetenv.c26
-rw-r--r--sysdeps/powerpc/fegetround.c31
-rw-r--r--sysdeps/powerpc/feholdexcpt.c38
-rw-r--r--sysdeps/powerpc/fenv_const.c29
-rw-r--r--sysdeps/powerpc/fenv_libc.h57
-rw-r--r--sysdeps/powerpc/fenvbits.h130
-rw-r--r--sysdeps/powerpc/fesetenv.c26
-rw-r--r--sysdeps/powerpc/fesetround.c41
-rw-r--r--sysdeps/powerpc/feupdateenv.c37
-rw-r--r--sysdeps/powerpc/ffs.c10
-rw-r--r--sysdeps/powerpc/fgetexcptflg.c33
-rw-r--r--sysdeps/powerpc/fpu_control.h12
-rw-r--r--sysdeps/powerpc/fraiseexcpt.c44
-rw-r--r--sysdeps/powerpc/fsetexcptflg.c37
-rw-r--r--sysdeps/powerpc/ftestexcept.c38
-rw-r--r--sysdeps/powerpc/mathbits.h72
-rw-r--r--sysdeps/powerpc/setjmp.S80
-rw-r--r--sysdeps/powerpc/strlen.s104
26 files changed, 1147 insertions, 480 deletions
diff --git a/sysdeps/powerpc/Dist b/sysdeps/powerpc/Dist
new file mode 100644
index 0000000000..ba908dc0cb
--- /dev/null
+++ b/sysdeps/powerpc/Dist
@@ -0,0 +1 @@
+fenv_libc.h
diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
new file mode 100644
index 0000000000..4100901d62
--- /dev/null
+++ b/sysdeps/powerpc/Makefile
@@ -0,0 +1,3 @@
+ifeq ($(subdir),math)
+libm-support += fenv_const
+endif
diff --git a/sysdeps/powerpc/__longjmp.S b/sysdeps/powerpc/__longjmp.S
index da621e22c0..02292a0eb2 100644
--- a/sysdeps/powerpc/__longjmp.S
+++ b/sysdeps/powerpc/__longjmp.S
@@ -22,46 +22,46 @@
 #include <jmp_buf.h>
 
 ENTRY (__longjmp)
-	lwz 1,(JB_GPR1*4)(3)
-	lwz 2,(JB_GPR2*4)(3)
-	lwz 0,(JB_LR*4)(3)
-	lwz 14,((JB_GPRS+0)*4)(3)
-	lfd 14,((JB_FPRS+0*2)*4)(3)
-	lwz 15,((JB_GPRS+1)*4)(3)
-	lfd 15,((JB_FPRS+1*2)*4)(3)
-	lwz 16,((JB_GPRS+2)*4)(3)
-	lfd 16,((JB_FPRS+2*2)*4)(3)
-	lwz 17,((JB_GPRS+3)*4)(3)
-	lfd 17,((JB_FPRS+3*2)*4)(3)
-	lwz 18,((JB_GPRS+4)*4)(3)
-	lfd 18,((JB_FPRS+4*2)*4)(3)
-	lwz 19,((JB_GPRS+5)*4)(3)
-	lfd 19,((JB_FPRS+5*2)*4)(3)
-	lwz 20,((JB_GPRS+6)*4)(3)
-	lfd 20,((JB_FPRS+6*2)*4)(3)
-	mtlr 0
-	lwz 21,((JB_GPRS+7)*4)(3)
-	lfd 21,((JB_FPRS+7*2)*4)(3)
-	lwz 22,((JB_GPRS+8)*4)(3)
-	lfd 22,((JB_FPRS+8*2)*4)(3)
-	lwz 23,((JB_GPRS+9)*4)(3)
-	lfd 23,((JB_FPRS+9*2)*4)(3)
-	lwz 24,((JB_GPRS+10)*4)(3)
-	lfd 24,((JB_FPRS+10*2)*4)(3)
-	lwz 25,((JB_GPRS+11)*4)(3)
-	lfd 25,((JB_FPRS+11*2)*4)(3)
-	lwz 26,((JB_GPRS+12)*4)(3)
-	lfd 26,((JB_FPRS+12*2)*4)(3)
-	lwz 27,((JB_GPRS+13)*4)(3)
-	lfd 27,((JB_FPRS+13*2)*4)(3)
-	lwz 28,((JB_GPRS+14)*4)(3)
-	lfd 28,((JB_FPRS+14*2)*4)(3)
-	lwz 29,((JB_GPRS+15)*4)(3)
-	lfd 29,((JB_FPRS+15*2)*4)(3)
-	lwz 30,((JB_GPRS+16)*4)(3)
-	lfd 30,((JB_FPRS+16*2)*4)(3)
-	lwz 31,((JB_GPRS+17)*4)(3)
-	lfd 31,((JB_FPRS+17*2)*4)(3)
-	mr 3,4
+	lwz %r1,(JB_GPR1*4)(%r3)
+	lwz %r2,(JB_GPR2*4)(%r3)
+	lwz %r0,(JB_LR*4)(%r3)
+	lwz %r14,((JB_GPRS+0)*4)(%r3)
+	lfd %f14,((JB_FPRS+0*2)*4)(%r3)
+	lwz %r15,((JB_GPRS+1)*4)(%r3)
+	lfd %f15,((JB_FPRS+1*2)*4)(%r3)
+	lwz %r16,((JB_GPRS+2)*4)(%r3)
+	lfd %f16,((JB_FPRS+2*2)*4)(%r3)
+	lwz %r17,((JB_GPRS+3)*4)(%r3)
+	lfd %f17,((JB_FPRS+3*2)*4)(%r3)
+	lwz %r18,((JB_GPRS+4)*4)(%r3)
+	lfd %f18,((JB_FPRS+4*2)*4)(%r3)
+	lwz %r19,((JB_GPRS+5)*4)(%r3)
+	lfd %f19,((JB_FPRS+5*2)*4)(%r3)
+	lwz %r20,((JB_GPRS+6)*4)(%r3)
+	lfd %f20,((JB_FPRS+6*2)*4)(%r3)
+	mtlr %r0
+	lwz %r21,((JB_GPRS+7)*4)(%r3)
+	lfd %f21,((JB_FPRS+7*2)*4)(%r3)
+	lwz %r22,((JB_GPRS+8)*4)(%r3)
+	lfd %f22,((JB_FPRS+8*2)*4)(%r3)
+	lwz %r23,((JB_GPRS+9)*4)(%r3)
+	lfd %f23,((JB_FPRS+9*2)*4)(%r3)
+	lwz %r24,((JB_GPRS+10)*4)(%r3)
+	lfd %f24,((JB_FPRS+10*2)*4)(%r3)
+	lwz %r25,((JB_GPRS+11)*4)(%r3)
+	lfd %f25,((JB_FPRS+11*2)*4)(%r3)
+	lwz %r26,((JB_GPRS+12)*4)(%r3)
+	lfd %f26,((JB_FPRS+12*2)*4)(%r3)
+	lwz %r27,((JB_GPRS+13)*4)(%r3)
+	lfd %f27,((JB_FPRS+13*2)*4)(%r3)
+	lwz %r28,((JB_GPRS+14)*4)(%r3)
+	lfd %f28,((JB_FPRS+14*2)*4)(%r3)
+	lwz %r29,((JB_GPRS+15)*4)(%r3)
+	lfd %f29,((JB_FPRS+15*2)*4)(%r3)
+	lwz %r30,((JB_GPRS+16)*4)(%r3)
+	lfd %f30,((JB_FPRS+16*2)*4)(%r3)
+	lwz %r31,((JB_GPRS+17)*4)(%r3)
+	lfd %f31,((JB_FPRS+17*2)*4)(%r3)
+	mr %r3,%r4
 	blr
 END (__longjmp)
diff --git a/sysdeps/powerpc/__math.h b/sysdeps/powerpc/__math.h
index 9dc19a91a5..db9688cfc5 100644
--- a/sysdeps/powerpc/__math.h
+++ b/sysdeps/powerpc/__math.h
@@ -64,25 +64,6 @@ fabs (double __x)
   return __value;
 }
 
-/* Optimized versions for some non-standardized functions.  */
-#ifdef __USE_MISC
-
-__MATH_INLINE double hypot (double __x, double __y);
-__MATH_INLINE double
-hypot (double __x, double __y)
-{
-  return sqrt (__x * __x + __y * __y);
-}
-
-__MATH_INLINE double __sgn (double __x);
-__MATH_INLINE double
-sgn (double __x)
-{
-  return (__x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0));
-}
-
-#endif /* __USE_MISC  */
-
 #endif /* __NO_MATH_INLINES  */
 #endif /* __GNUC__  */
 
diff --git a/sysdeps/powerpc/bsd-_setjmp.S b/sysdeps/powerpc/bsd-_setjmp.S
index a9aefcc977..ffd90d5bd2 100644
--- a/sysdeps/powerpc/bsd-_setjmp.S
+++ b/sysdeps/powerpc/bsd-_setjmp.S
@@ -24,7 +24,7 @@
 #include <sysdep.h>
 
 ENTRY (_setjmp)
-	li 4,0				/* Set second argument to 0.  */
+	li %r4,0			/* Set second argument to 0.  */
 #ifdef PIC
 	b __sigsetjmp@plt
 #else
diff --git a/sysdeps/powerpc/bsd-setjmp.S b/sysdeps/powerpc/bsd-setjmp.S
index 1a6300660e..f02d7815ed 100644
--- a/sysdeps/powerpc/bsd-setjmp.S
+++ b/sysdeps/powerpc/bsd-setjmp.S
@@ -24,7 +24,7 @@
 #include <sysdep.h>
 
 ENTRY (__setjmp)
-	li 4,1				/* Set second argument to 1.  */
+	li %r4,1			/* Set second argument to 1.  */
 #ifdef PIC
 	b __sigsetjmp@plt
 #else
diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h
index 3ad5ca89c9..cfada93cd4 100644
--- a/sysdeps/powerpc/dl-machine.h
+++ b/sysdeps/powerpc/dl-machine.h
@@ -17,6 +17,9 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#ifndef dl_machine_h
+#define dl_machine_h
+
 #define ELF_MACHINE_NAME "powerpc"
 
 #include <assert.h>
@@ -134,318 +137,13 @@ elf_machine_load_address (void)
 
   /* So now work out the difference between where the branch actually points,
      and the offset of that location in memory from the start of the file.  */
-  return (Elf32_Addr)branchaddr - *got +
-    (*branchaddr & 0x3fffffc |
-     (int)(*branchaddr << 6 & 0x80000000) >> 6);
+  return ((Elf32_Addr)branchaddr - *got
+	  + (*branchaddr & 0x3fffffc
+	     | (int)(*branchaddr << 6 & 0x80000000) >> 6));
 }
 
 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */
 
-/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
-   LOADADDR is the load address of the object; INFO is an array indexed
-   by DT_* of the .dynamic section info.  */
-
-#ifdef RESOLVE
-
-static inline void
-elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
-		  const Elf32_Sym *sym, const struct r_found_version *version)
-{
-  const Elf32_Sym *const refsym = sym;
-  Elf32_Addr *const reloc_addr = (Elf32_Addr *)(map->l_addr + reloc->r_offset);
-  Elf32_Word loadbase, finaladdr;
-  const int rinfo = ELF32_R_TYPE (reloc->r_info);
-
-  if (rinfo == R_PPC_NONE)
-    return;
-
-  assert (sym != NULL);
-  if (ELF32_ST_TYPE (sym->st_info) == STT_SECTION ||
-      rinfo == R_PPC_RELATIVE)
-    {
-      /* Has already been relocated.  */
-      loadbase = map->l_addr;
-      finaladdr = loadbase + reloc->r_addend;
-    }
-  else
-    {
-      int flags;
-
-      /* We never want to use a PLT entry as the destination of a
-	 reloc, when what is being relocated is a branch. This is
-	 partly for efficiency, but mostly so we avoid loops.  */
-      if (rinfo == R_PPC_REL24 ||
-	  rinfo == R_PPC_ADDR24 ||
-	  rinfo == R_PPC_JMP_SLOT)
-	flags = DL_LOOKUP_NOPLT;
-      else if (rinfo == R_PPC_COPY)
-	flags = DL_LOOKUP_NOEXEC;
-      else
-	flags = 0;
-
-      loadbase = (Elf32_Word) (char *) (RESOLVE (&sym, version, flags));
-      if (sym == NULL)
-	{
-	  /* Weak symbol that wasn't actually defined anywhere.  */
-	  assert(loadbase == 0);
-	  finaladdr = reloc->r_addend;
-	}
-      else
-	finaladdr = (loadbase + (Elf32_Word) (char *) sym->st_value
-		     + reloc->r_addend);
-    }
-
-  /* This is an if/else if chain because GCC 2.7.2.[012] turns case
-     statements into non-PIC table lookups.  When a later version
-     comes out that fixes this, this should be changed.  */
-  if (rinfo == R_PPC_UADDR32 ||
-      rinfo == R_PPC_GLOB_DAT ||
-      rinfo == R_PPC_ADDR32 ||
-      rinfo == R_PPC_RELATIVE)
-    {
-      *reloc_addr = finaladdr;
-    }
-  else if (rinfo == R_PPC_ADDR16_LO)
-    {
-      *(Elf32_Half*) reloc_addr = finaladdr;
-    }
-  else if (rinfo == R_PPC_ADDR16_HI)
-    {
-      *(Elf32_Half*) reloc_addr = finaladdr >> 16;
-    }
-  else if (rinfo == R_PPC_ADDR16_HA)
-    {
-      *(Elf32_Half*) reloc_addr = (finaladdr + 0x8000) >> 16;
-    }
-#ifndef RTLD_BOOTSTRAP
-  else if (rinfo == R_PPC_REL24)
-    {
-      Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
-      if (delta << 6 >> 6 != delta)
-	_dl_signal_error (0, map->l_name,
-			  "R_PPC_REL24 relocation out of range");
-      *reloc_addr = *reloc_addr & 0xfc000003 | delta & 0x3fffffc;
-    }
-  else if (rinfo == R_PPC_ADDR24)
-    {
-      if (finaladdr << 6 >> 6 != finaladdr)
-	_dl_signal_error (0, map->l_name,
-			  "R_PPC_ADDR24 relocation out of range");
-      *reloc_addr = *reloc_addr & 0xfc000003 | finaladdr & 0x3fffffc;
-    }
-  else if (rinfo == R_PPC_COPY)
-    {
-      if (sym->st_size != refsym->st_size)
-	{
-	  const char *strtab;
-
-	  strtab = ((void *) map->l_addr
-		    + map->l_info[DT_STRTAB]->d_un.d_ptr);
-	  _dl_sysdep_error ("Symbol `", strtab + refsym->st_name,
-			    "' has different size in shared object, "
-			    "consider re-linking\n", NULL);
-	}
-      memcpy (reloc_addr, (char *) finaladdr, MIN (sym->st_size,
-						   refsym->st_size));
-    }
-#endif
-  else if (rinfo == R_PPC_REL32)
-    {
-      *reloc_addr = finaladdr - (Elf32_Word) (char *) reloc_addr;
-    }
-  else if (rinfo == R_PPC_JMP_SLOT)
-    {
-      Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
-      if (delta << 6 >> 6 == delta)
-	*reloc_addr = OPCODE_B (delta);
-      else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
-	*reloc_addr = OPCODE_BA (finaladdr);
-      else
-	{
-	  Elf32_Word *plt;
-	  Elf32_Word index;
-
-	  plt = (Elf32_Word *)((char *)map->l_addr
-			       + map->l_info[DT_PLTGOT]->d_un.d_val);
-	  index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2;
-
-	  if (index >= PLT_DOUBLE_SIZE)
-	    {
-	      /* Slots greater than or equal to 2^13 have 4 words available
-		 instead of two.  */
-	      reloc_addr[0] = OPCODE_LI (11, finaladdr);
-	      reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16);
-	      reloc_addr[2] = OPCODE_MTCTR (11);
-	      reloc_addr[3] = OPCODE_BCTR ();
-	    }
-	  else
-	    {
-	      Elf32_Word num_plt_entries;
-
-	      num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
-				 / sizeof(Elf32_Rela));
-
-	      reloc_addr[0] = OPCODE_LI (11, index*4);
-	      reloc_addr[1] =
-		OPCODE_B (-(4*(index*2
-			       + 1
-			       - PLT_LONGBRANCH_ENTRY_WORDS
-			       + PLT_INITIAL_ENTRY_WORDS)));
-	      plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr;
-	    }
-	}
-      MODIFIED_CODE (reloc_addr);
-    }
-  else
-    assert (! "unexpected dynamic reloc type");
-
-  if (rinfo == R_PPC_ADDR16_LO ||
-      rinfo == R_PPC_ADDR16_HI ||
-      rinfo == R_PPC_ADDR16_HA ||
-      rinfo == R_PPC_REL24 ||
-      rinfo == R_PPC_ADDR24)
-    MODIFIED_CODE_NOQUEUE (reloc_addr);
-}
-
-#define ELF_MACHINE_NO_REL 1
-
-#endif
-
-/* Nonzero iff TYPE describes relocation of a PLT entry, so
-   PLT entries should not be allowed to define the value.  */
-#define elf_machine_pltrel_p(type) ((type) == R_PPC_JMP_SLOT)
-
-/* Set up the loaded object described by L so its unrelocated PLT
-   entries will jump to the on-demand fixup code in dl-runtime.c.
-   Also install a small trampoline to be used by entries that have
-   been relocated to an address too far away for a single branch.  */
-
-/* A PLT entry does one of three things:
-   (i)   Jumps to the actual routine. Such entries are set up above, in
-         elf_machine_rela.
-
-   (ii)  Jumps to the actual routine via glue at the start of the PLT.
-         We do this by putting the address of the routine in space
-         allocated at the end of the PLT, and when the PLT entry is
-         called we load the offset of that word (from the start of the
-         space) into r11, then call the glue, which loads the word and
-         branches to that address. These entries are set up in
-         elf_machine_rela, but the glue is set up here.
-
-   (iii) Loads the index of this PLT entry (we count the double-size
-	 entries as one entry for this purpose) into r11, then
-	 branches to code at the start of the PLT. This code then
-	 calls `fixup', in dl-runtime.c, via the glue in the macro
-	 ELF_MACHINE_RUNTIME_TRAMPOLINE, which resets the PLT entry to
-	 be one of the above two types. These entries are set up here.  */
-static inline void
-elf_machine_runtime_setup (struct link_map *map, int lazy)
-{
-  if (map->l_info[DT_JMPREL])
-    {
-      int i;
-      /* Fill in the PLT. Its initial contents are directed to a
-	 function earlier in the PLT which arranges for the dynamic
-	 linker to be called back.  */
-      Elf32_Word *plt = (Elf32_Word *) ((char *) map->l_addr
-					+ map->l_info[DT_PLTGOT]->d_un.d_val);
-      Elf32_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
-				    / sizeof (Elf32_Rela));
-      Elf32_Word rel_offset_words = PLT_DATA_START_WORDS (num_plt_entries);
-      extern void _dl_runtime_resolve (void);
-      Elf32_Word size_modified;
-
-      if (lazy)
-	for (i = 0; i < num_plt_entries; i++)
-	{
-	  Elf32_Word offset = PLT_ENTRY_START_WORDS (i);
-
-	  if (i >= PLT_DOUBLE_SIZE)
-	    {
-	      plt[offset  ] = OPCODE_LI (11, i * 4);
-	      plt[offset+1] = OPCODE_ADDIS (11, 11, (i * 4 + 0x8000) >> 16);
-	      plt[offset+2] = OPCODE_B (-(4 * (offset + 2)));
-	    }
-	  else
-	    {
-	      plt[offset  ] = OPCODE_LI (11, i * 4);
-	      plt[offset+1] = OPCODE_B (-(4 * (offset + 1)));
-	    }
-	}
-
-      /* Multiply index of entry by 3 (in r11).  */
-      plt[0] = OPCODE_SLWI (12, 11, 1);
-      plt[1] = OPCODE_ADD (11, 12, 11);
-      if ((Elf32_Word) (char *) _dl_runtime_resolve <= 0x01fffffc ||
-	  (Elf32_Word) (char *) _dl_runtime_resolve >= 0xfe000000)
-	{
-	  /* Load address of link map in r12.  */
-	  plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) map);
-	  plt[3] = OPCODE_ADDIS (12, 12, (((Elf32_Word) (char *) map
-					   + 0x8000) >> 16));
-
-	  /* Call _dl_runtime_resolve.  */
-	  plt[4] = OPCODE_BA ((Elf32_Word) (char *) _dl_runtime_resolve);
-	}
-      else
-	{
-	  /* Get address of _dl_runtime_resolve in CTR.  */
-	  plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) _dl_runtime_resolve);
-	  plt[3] = OPCODE_ADDIS (12, 12, ((((Elf32_Word) (char *)
-					    _dl_runtime_resolve)
-					   + 0x8000) >> 16));
-	  plt[4] = OPCODE_MTCTR (12);
-
-	  /* Load address of link map in r12.  */
-	  plt[5] = OPCODE_LI (12, (Elf32_Word) (char *) map);
-	  plt[6] = OPCODE_ADDIS (12, 12, (((Elf32_Word) (char *) map
-					   + 0x8000) >> 16));
-
-	  /* Call _dl_runtime_resolve.  */
-	  plt[7] = OPCODE_BCTR ();
-	}
-
-
-      /* Convert the index in r11 into an actual address, and get the
-	 word at that address.  */
-      plt[PLT_LONGBRANCH_ENTRY_WORDS] =
-	OPCODE_ADDIS (11, 11, (((Elf32_Word) (char*) (plt + rel_offset_words)
-				+ 0x8000) >> 16));
-      plt[PLT_LONGBRANCH_ENTRY_WORDS+1] =
-	OPCODE_LWZ (11, (Elf32_Word) (char*) (plt+rel_offset_words), 11);
-
-      /* Call the procedure at that address.  */
-      plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR (11);
-      plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR ();
-
-
-      /* Now, we've modified code (quite a lot of code, possibly).  We
-	 need to write the changes from the data cache to a
-	 second-level unified cache, then make sure that stale data in
-	 the instruction cache is removed.  (In a multiprocessor
-	 system, the effect is more complex.)
-
-	 Assumes the cache line size is at least 32 bytes, or at least
-	 that dcbst and icbi apply to 32-byte lines. At present, all
-	 PowerPC processors have line sizes of exactly 32 bytes.  */
-
-      size_modified = lazy ? rel_offset_words : PLT_INITIAL_ENTRY_WORDS;
-      for (i = 0; i < size_modified; i+=8)
-	PPC_DCBST (plt + i);
-      PPC_SYNC;
-      for (i = 0; i < size_modified; i+=8)
-	PPC_ICBI (plt + i);
-      PPC_ISYNC;
-    }
-}
-
-static inline void
-elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
-{
-  assert (ELF32_R_TYPE (reloc->r_info) == R_PPC_JMP_SLOT);
-  /* elf_machine_runtime_setup handles this. */
-}
-
 /* The PLT uses Elf32_Rela relocs.  */
 #define elf_machine_relplt elf_machine_rela
 
@@ -617,7 +315,7 @@ _start:
    information here about the way memory is mapped.  */
 
 #define ELF_PREFERRED_ADDRESS_DATA					      \
-static ElfW(Addr) _dl_preferred_address = 1;
+static ElfW(Addr) _dl_preferred_address = 1
 
 #define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref)		      \
 ( {									      \
@@ -645,4 +343,326 @@ static ElfW(Addr) _dl_preferred_address = 1;
      _dl_preferred_address = mapstart;					      \
 } )
 
+/* We require the address of the PLT entry returned from fixup, not
+   the first word of the PLT entry. */
 #define ELF_FIXUP_RETURNS_ADDRESS 1
+
+/* Nonzero iff TYPE should not be allowed to resolve to one of
+   the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_lookup_noexec_p(type) ((type) == R_PPC_COPY)
+
+/* Nonzero iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.  */
+/* We never want to use a PLT entry as the destination of a
+   reloc, when what is being relocated is a branch. This is
+   partly for efficiency, but mostly so we avoid loops.  */
+#define elf_machine_lookup_noplt_p(type) ((type) == R_PPC_REL24 ||            \
+					  (type) == R_PPC_ADDR24 ||           \
+					  (type) == R_PPC_JMP_SLOT)
+
+/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
+#define ELF_MACHINE_RELOC_NOPLT	R_PPC_JMP_SLOT
+
+/* Nonzero iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.  */
+#define elf_machine_pltrel_p(type) ((type) == R_PPC_JMP_SLOT)
+
+/* Set up the loaded object described by L so its unrelocated PLT
+   entries will jump to the on-demand fixup code in dl-runtime.c.
+   Also install a small trampoline to be used by entries that have
+   been relocated to an address too far away for a single branch.  */
+
+/* A PLT entry does one of three things:
+   (i)   Jumps to the actual routine. Such entries are set up above, in
+         elf_machine_rela.
+
+   (ii)  Jumps to the actual routine via glue at the start of the PLT.
+         We do this by putting the address of the routine in space
+         allocated at the end of the PLT, and when the PLT entry is
+         called we load the offset of that word (from the start of the
+         space) into r11, then call the glue, which loads the word and
+         branches to that address. These entries are set up in
+         elf_machine_rela, but the glue is set up here.
+
+   (iii) Loads the index of this PLT entry (we count the double-size
+	 entries as one entry for this purpose) into r11, then
+	 branches to code at the start of the PLT. This code then
+	 calls `fixup', in dl-runtime.c, via the glue in the macro
+	 ELF_MACHINE_RUNTIME_TRAMPOLINE, which resets the PLT entry to
+	 be one of the above two types. These entries are set up here.  */
+static inline void
+elf_machine_runtime_setup (struct link_map *map, int lazy)
+{
+  if (map->l_info[DT_JMPREL])
+    {
+      int i;
+      /* Fill in the PLT. Its initial contents are directed to a
+	 function earlier in the PLT which arranges for the dynamic
+	 linker to be called back.  */
+      Elf32_Word *plt = (Elf32_Word *) ((char *) map->l_addr
+					+ map->l_info[DT_PLTGOT]->d_un.d_val);
+      Elf32_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
+				    / sizeof (Elf32_Rela));
+      Elf32_Word rel_offset_words = PLT_DATA_START_WORDS (num_plt_entries);
+      extern void _dl_runtime_resolve (void);
+      Elf32_Word size_modified;
+
+      if (lazy)
+	for (i = 0; i < num_plt_entries; i++)
+	{
+	  Elf32_Word offset = PLT_ENTRY_START_WORDS (i);
+
+	  if (i >= PLT_DOUBLE_SIZE)
+	    {
+	      plt[offset  ] = OPCODE_LI (11, i * 4);
+	      plt[offset+1] = OPCODE_ADDIS (11, 11, (i * 4 + 0x8000) >> 16);
+	      plt[offset+2] = OPCODE_B (-(4 * (offset + 2)));
+	    }
+	  else
+	    {
+	      plt[offset  ] = OPCODE_LI (11, i * 4);
+	      plt[offset+1] = OPCODE_B (-(4 * (offset + 1)));
+	    }
+	}
+
+      /* Multiply index of entry by 3 (in r11).  */
+      plt[0] = OPCODE_SLWI (12, 11, 1);
+      plt[1] = OPCODE_ADD (11, 12, 11);
+      if ((Elf32_Word) (char *) _dl_runtime_resolve <= 0x01fffffc ||
+	  (Elf32_Word) (char *) _dl_runtime_resolve >= 0xfe000000)
+	{
+	  /* Load address of link map in r12.  */
+	  plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) map);
+	  plt[3] = OPCODE_ADDIS (12, 12, (((Elf32_Word) (char *) map
+					   + 0x8000) >> 16));
+
+	  /* Call _dl_runtime_resolve.  */
+	  plt[4] = OPCODE_BA ((Elf32_Word) (char *) _dl_runtime_resolve);
+	}
+      else
+	{
+	  /* Get address of _dl_runtime_resolve in CTR.  */
+	  plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) _dl_runtime_resolve);
+	  plt[3] = OPCODE_ADDIS (12, 12, ((((Elf32_Word) (char *)
+					    _dl_runtime_resolve)
+					   + 0x8000) >> 16));
+	  plt[4] = OPCODE_MTCTR (12);
+
+	  /* Load address of link map in r12.  */
+	  plt[5] = OPCODE_LI (12, (Elf32_Word) (char *) map);
+	  plt[6] = OPCODE_ADDIS (12, 12, (((Elf32_Word) (char *) map
+					   + 0x8000) >> 16));
+
+	  /* Call _dl_runtime_resolve.  */
+	  plt[7] = OPCODE_BCTR ();
+	}
+
+
+      /* Convert the index in r11 into an actual address, and get the
+	 word at that address.  */
+      plt[PLT_LONGBRANCH_ENTRY_WORDS] =
+	OPCODE_ADDIS (11, 11, (((Elf32_Word) (char*) (plt + rel_offset_words)
+				+ 0x8000) >> 16));
+      plt[PLT_LONGBRANCH_ENTRY_WORDS+1] =
+	OPCODE_LWZ (11, (Elf32_Word) (char*) (plt+rel_offset_words), 11);
+
+      /* Call the procedure at that address.  */
+      plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR (11);
+      plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR ();
+
+
+      /* Now, we've modified code (quite a lot of code, possibly).  We
+	 need to write the changes from the data cache to a
+	 second-level unified cache, then make sure that stale data in
+	 the instruction cache is removed.  (In a multiprocessor
+	 system, the effect is more complex.)
+
+	 Assumes the cache line size is at least 32 bytes, or at least
+	 that dcbst and icbi apply to 32-byte lines. At present, all
+	 PowerPC processors have line sizes of exactly 32 bytes.  */
+
+      size_modified = lazy ? rel_offset_words : PLT_INITIAL_ENTRY_WORDS;
+      for (i = 0; i < size_modified; i+=8)
+	PPC_DCBST (plt + i);
+      PPC_SYNC;
+      for (i = 0; i < size_modified; i+=8)
+	PPC_ICBI (plt + i);
+      PPC_ISYNC;
+    }
+}
+
+static inline void
+elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
+{
+  assert (ELF32_R_TYPE (reloc->r_info) == R_PPC_JMP_SLOT);
+  /* elf_machine_runtime_setup handles this. */
+}
+
+#endif /* dl_machine_h */
+
+#ifdef RESOLVE
+
+/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
+   LOADADDR is the load address of the object; INFO is an array indexed
+   by DT_* of the .dynamic section info.  */
+
+static inline void
+elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
+		  const Elf32_Sym *sym, const struct r_found_version *version)
+{
+  const Elf32_Sym *const refsym = sym;
+  Elf32_Addr *const reloc_addr = (Elf32_Addr *)(map->l_addr + reloc->r_offset);
+  Elf32_Word loadbase, finaladdr;
+  const int rinfo = ELF32_R_TYPE (reloc->r_info);
+
+  if (rinfo == R_PPC_NONE)
+    return;
+
+  assert (sym != NULL);
+  /* The condition on the next two lines is a hack around a bug in Solaris
+     tools on Sparc.  It's not clear whether it should really be here at all,
+     but if not the binutils need to be changed.  */
+  if ((sym->st_shndx != SHN_UNDEF
+       && ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
+      || rinfo == R_PPC_RELATIVE)
+    {
+      /* Has already been relocated.  */
+      loadbase = map->l_addr;
+      finaladdr = loadbase + reloc->r_addend;
+    }
+  else
+    {
+      loadbase = (Elf32_Word) (char *) (RESOLVE (&sym, version,
+						 ELF32_R_TYPE(reloc->r_info)));
+      if (sym == NULL)
+	{
+	  /* Weak symbol that wasn't actually defined anywhere.  */
+	  assert(loadbase == 0);
+	  finaladdr = reloc->r_addend;
+	}
+      else
+	finaladdr = (loadbase + (Elf32_Word) (char *) sym->st_value
+		     + reloc->r_addend);
+    }
+
+  /* This is an if/else if chain because GCC 2.7.2.[012] turns case
+     statements into non-PIC table lookups.  When a later version
+     comes out that fixes this, this should be changed.  */
+  if (rinfo == R_PPC_UADDR32 ||
+      rinfo == R_PPC_GLOB_DAT ||
+      rinfo == R_PPC_ADDR32 ||
+      rinfo == R_PPC_RELATIVE)
+    {
+      *reloc_addr = finaladdr;
+    }
+  else if (rinfo == R_PPC_ADDR16_LO)
+    {
+      *(Elf32_Half*) reloc_addr = finaladdr;
+    }
+  else if (rinfo == R_PPC_ADDR16_HI)
+    {
+      *(Elf32_Half*) reloc_addr = finaladdr >> 16;
+    }
+  else if (rinfo == R_PPC_ADDR16_HA)
+    {
+      *(Elf32_Half*) reloc_addr = (finaladdr + 0x8000) >> 16;
+    }
+#ifndef RTLD_BOOTSTRAP
+  else if (rinfo == R_PPC_REL24)
+    {
+      Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
+      if (delta << 6 >> 6 != delta)
+	{
+	  _dl_signal_error(0, map->l_name,
+			   "R_PPC_REL24 relocation out of range");
+	}
+      *reloc_addr = *reloc_addr & 0xfc000003 | delta & 0x3fffffc;
+    }
+  else if (rinfo == R_PPC_ADDR24)
+    {
+      if (finaladdr << 6 >> 6 != finaladdr)
+	{
+	  _dl_signal_error(0, map->l_name,
+			   "R_PPC_ADDR24 relocation out of range");
+	}
+      *reloc_addr = *reloc_addr & 0xfc000003 | finaladdr & 0x3fffffc;
+    }
+  else if (rinfo == R_PPC_COPY)
+    {
+      if (sym->st_size != refsym->st_size)
+	{
+	  const char *strtab;
+
+	  strtab = ((void *) map->l_addr
+		    + map->l_info[DT_STRTAB]->d_un.d_ptr);
+	  _dl_sysdep_error ("Symbol `", strtab + refsym->st_name,
+			    "' has different size in shared object, "
+			    "consider re-linking\n", NULL);
+	}
+      memcpy (reloc_addr, (char *) finaladdr, MIN (sym->st_size,
+						   refsym->st_size));
+    }
+#endif
+  else if (rinfo == R_PPC_REL32)
+    {
+      *reloc_addr = finaladdr - (Elf32_Word) (char *) reloc_addr;
+    }
+  else if (rinfo == R_PPC_JMP_SLOT)
+    {
+      Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
+      if (delta << 6 >> 6 == delta)
+	*reloc_addr = OPCODE_B (delta);
+      else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
+	*reloc_addr = OPCODE_BA (finaladdr);
+      else
+	{
+	  Elf32_Word *plt;
+	  Elf32_Word index;
+
+	  plt = (Elf32_Word *)((char *)map->l_addr
+			       + map->l_info[DT_PLTGOT]->d_un.d_val);
+	  index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2;
+
+	  if (index >= PLT_DOUBLE_SIZE)
+	    {
+	      /* Slots greater than or equal to 2^13 have 4 words available
+		 instead of two.  */
+	      reloc_addr[0] = OPCODE_LI (11, finaladdr);
+	      reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16);
+	      reloc_addr[2] = OPCODE_MTCTR (11);
+	      reloc_addr[3] = OPCODE_BCTR ();
+	    }
+	  else
+	    {
+	      Elf32_Word num_plt_entries;
+
+	      num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
+				 / sizeof(Elf32_Rela));
+
+	      reloc_addr[0] = OPCODE_LI (11, index*4);
+	      reloc_addr[1] =
+		OPCODE_B (-(4*(index*2
+			       + 1
+			       - PLT_LONGBRANCH_ENTRY_WORDS
+			       + PLT_INITIAL_ENTRY_WORDS)));
+	      plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr;
+	    }
+	}
+      MODIFIED_CODE (reloc_addr);
+    }
+  else
+    assert (! "unexpected dynamic reloc type");
+
+  if (rinfo == R_PPC_ADDR16_LO ||
+      rinfo == R_PPC_ADDR16_HI ||
+      rinfo == R_PPC_ADDR16_HA ||
+      rinfo == R_PPC_REL24 ||
+      rinfo == R_PPC_ADDR24)
+    MODIFIED_CODE_NOQUEUE (reloc_addr);
+}
+
+#define ELF_MACHINE_NO_REL 1
+
+#endif
+
+
diff --git a/sysdeps/powerpc/fclrexcpt.c b/sysdeps/powerpc/fclrexcpt.c
new file mode 100644
index 0000000000..1e66140c2e
--- /dev/null
+++ b/sysdeps/powerpc/fclrexcpt.c
@@ -0,0 +1,35 @@
+/* Clear given exceptions in current floating-point environment.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+void
+feclearexcept (int excepts)
+{
+  fenv_union_t u;
+
+  /* Get the current state.  */
+  u.fenv = fegetenv_register ();
+
+  /* Clear the relevant bits.  */
+  u.l[1] = u.l[1] & ~FE_to_sticky (excepts);
+
+  /* Put the new state in effect.  */
+  fesetenv_register (u.fenv);
+}
diff --git a/sysdeps/powerpc/fegetenv.c b/sysdeps/powerpc/fegetenv.c
new file mode 100644
index 0000000000..de778fa5a9
--- /dev/null
+++ b/sysdeps/powerpc/fegetenv.c
@@ -0,0 +1,26 @@
+/* Store current floating-point environment.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+void
+fegetenv (fenv_t *envp)
+{
+  *envp = fegetenv_register ();
+}
diff --git a/sysdeps/powerpc/fegetround.c b/sysdeps/powerpc/fegetround.c
new file mode 100644
index 0000000000..05395f0797
--- /dev/null
+++ b/sysdeps/powerpc/fegetround.c
@@ -0,0 +1,31 @@
+/* Return current rounding direction.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+int
+fegetround (void)
+{
+  fenv_union_t u;
+
+  u.fenv = fegetenv_register ();
+
+  /* The rounding mode is bits 30 and 31 of the FPSCR.  */
+  return u.l[1] & 3;
+}
diff --git a/sysdeps/powerpc/feholdexcpt.c b/sysdeps/powerpc/feholdexcpt.c
new file mode 100644
index 0000000000..a75adbf49e
--- /dev/null
+++ b/sysdeps/powerpc/feholdexcpt.c
@@ -0,0 +1,38 @@
+/* Store current floating-point environment and clear exceptions.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+int
+feholdexcept (fenv_t *envp)
+{
+  fenv_union_t u;
+
+  /* Get the current state.  */
+  u.fenv = *envp = fegetenv_register ();
+
+  /* Clear everything except for the rounding mode and non-IEEE arithmetic
+     flag.  */
+  u.l[1] = u.l[1] & 7;
+
+  /* Put the new state in effect.  */
+  fesetenv_register (u.fenv);
+
+  return 1;
+}
diff --git a/sysdeps/powerpc/fenv_const.c b/sysdeps/powerpc/fenv_const.c
new file mode 100644
index 0000000000..fa35fbc0cf
--- /dev/null
+++ b/sysdeps/powerpc/fenv_const.c
@@ -0,0 +1,29 @@
+/* Constants for fenv_bits.h.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* We want to specify the bit pattern of the __fe_*_env constants, so 
+   pretend they're really `long long' instead of `double'.  */
+
+/* If the default argument is used we use this value.  */
+const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) = 
+0xfff8000000000000ULL;
+
+/* Floating-point environment where none of the exceptions are masked.  */
+const unsigned long long __fe_nomask_env __attribute__ ((aligned (8))) = 
+0xfff80000000000f8ULL;
diff --git a/sysdeps/powerpc/fenv_libc.h b/sysdeps/powerpc/fenv_libc.h
new file mode 100644
index 0000000000..45d61e1565
--- /dev/null
+++ b/sysdeps/powerpc/fenv_libc.h
@@ -0,0 +1,57 @@
+/* Internal libc stuff for floating point environment routines.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _FENV_LIBC_H
+#define _FENV_LIBC_H	1
+
+#include <fenv.h>
+
+/* Transform a logical or of the FE_* bits to a bit pattern for the
+   appropriate sticky bits in the FPSCR.  */
+#define FE_to_sticky(excepts) \
+        (-(excepts & FE_INVALID) & FE_ALL_INVALID \
+	 |  (excepts) & (FE_ALL_EXCEPT & ~FE_INVALID  | FE_ALL_INVALID))
+
+/* The sticky bits in the FPSCR indicating exceptions have occurred.  */
+#define FPSCR_STICKY_BITS ((FE_ALL_EXCEPT | FE_ALL_INVALID) & ~FE_INVALID)
+
+/* Equivalent to fegetenv, but returns a fenv_t instead of taking a
+   pointer.  */
+#define fegetenv_register() \
+        ({ fenv_t env; asm ("mffs %0" : "=f" (env)); env; })
+
+/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer.  */
+#define fesetenv_register(env) \
+        ({ double d = (env); asm ("mtfsf 0xff,%0" : : "f" (d)); })
+
+/* This very handy macro:
+   - Sets the rounding mode to 'round to nearest';
+   - Sets the processor into IEEE mode; and
+   - Prevents exceptions from being raised for inexact results.
+   These things happen to be exactly what you need for typical elementary
+   functions.  */
+#define relax_fenv_state() asm ("mtfsfi 7,0")
+
+typedef union
+{
+  fenv_t fenv;
+  unsigned int l[2];
+} fenv_union_t;
+
+#endif /* fenv_libc.h */
diff --git a/sysdeps/powerpc/fenvbits.h b/sysdeps/powerpc/fenvbits.h
new file mode 100644
index 0000000000..867ea5f5b4
--- /dev/null
+++ b/sysdeps/powerpc/fenvbits.h
@@ -0,0 +1,130 @@
+/* Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* This file should never be included directly.  */
+
+#ifndef _FENVBITS_H
+#define _FENVBITS_H	1
+
+/* Define bits representing the exception.  We use the bit positions of
+   the appropriate bits in the FPSCR...  */
+enum
+  {
+    FE_INEXACT = 1 << 31-6,
+#define FE_INEXACT	FE_INEXACT
+    FE_DIVBYZERO = 1 << 31-5,
+#define FE_DIVBYZERO	FE_DIVBYZERO
+    FE_UNDERFLOW = 1 << 31-4,
+#define FE_UNDERFLOW	FE_UNDERFLOW
+    FE_OVERFLOW = 1 << 31-3,
+#define FE_OVERFLOW	FE_OVERFLOW
+
+    /* ... except for FE_INVALID, for which we use bit 31. FE_INVALID
+       actually corresponds to bits 7 through 12 and 21 through 23
+       in the FPSCR, but we can't use that because the current draft
+       says that it must be a power of 2.  Instead we use bit 24 which
+       is the enable bit for all the FE_INVALID exceptions.  */
+    FE_INVALID = 1 << 31-24,
+#define FE_INVALID	FE_INVALID
+
+#ifdef __USE_GNU
+    /* Breakdown of the FE_INVALID bits. Setting FE_INVALID on an
+       input to a routine is equivalent to setting all of these bits;
+       FE_INVALID will be set on output from a routine iff one of
+       these bits is set.  Note, though, that you can't disable or
+       enable these exceptions individually.  */
+
+    /* Operation with SNaN. */
+    FE_INVALID_SNAN = 1 << 31-7,
+#define FE_INVALID_SNAN	FE_INVALID_SNAN
+
+    /* Inf - Inf */
+    FE_INVALID_ISI = 1 << 31-8,
+#define FE_INVALID_ISI	FE_INVALID_ISI
+
+    /* Inf / Inf */
+    FE_INVALID_IDI = 1 << 31-9,
+#define FE_INVALID_IDI	FE_INVALID_IDI
+
+    /* 0 / 0 */
+    FE_INVALID_ZDZ = 1 << 31-10,
+#define FE_INVALID_ZDZ	FE_INVALID_ZDZ
+
+    /* Inf * 0 */
+    FE_INVALID_IMZ = 1 << 31-11,
+#define FE_INVALID_IMZ	FE_INVALID_IMZ
+
+    /* Comparison with NaN or SNaN. */
+    FE_INVALID_COMPARE = 1 << 31-12,
+#define FE_INVALID_COMPARE	FE_INVALID_COMPARE
+
+    /* Invalid operation flag for software (not set by hardware). */
+    FE_INVALID_SOFTWARE = 1 << 31-21,
+#define FE_INVALID_SOFTWARE	FE_INVALID_SOFTWARE
+
+    /* Square root of negative number (including -Inf). */
+    FE_INVALID_SQRT = 1 << 31-22,
+#define FE_INVALID_SQRT	FE_INVALID_SQRT
+
+    /* Conversion-to-integer of a NaN or a number too large or too small. */
+    FE_INVALID_INTEGER_CONVERSION = 1 << 31-23,
+#define FE_INVALID_INTEGER_CONVERSION	FE_INVALID_INTEGER_CONVERSION
+
+#define __FE_ALL_INVALID \
+        (FE_INVALID_SNAN | FE_INVALID_ISI | FE_INVALID_IDI | FE_INVALID_ZDZ \
+	 | FE_INVALID_IMZ | FE_INVALID_COMPARE | FE_INVALID_SOFTWARE \
+	 | FE_INVALID_SQRT | FE_INVALID_INTEGER_CONVERSION)
+#endif
+  };
+
+#define FE_ALL_EXCEPT \
+	(FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
+
+/* PowerPC chips support all of the four defined rounding modes.  We
+   use the bit pattern in the FPSCR as the values for the
+   appropriate macros.  */
+enum
+  {
+    FE_TONEAREST = 0,
+#define FE_TONEAREST	FE_TONEAREST
+    FE_TOWARDSZERO = 1,
+#define FE_TOWARDSZERO	FE_TOWARDSZERO
+    FE_UPWARD = 2,
+#define FE_UPWARD	FE_UPWARD
+    FE_DOWNWARD = 3,
+#define FE_DOWNWARD	FE_DOWNWARD
+  };
+
+/* Type representing exception flags.  */
+typedef unsigned int fexcept_t;
+
+/* Type representing floating-point environment.  We leave it as 'double'
+   for efficiency reasons (rather than writing it to a 32-bit integer). */
+typedef double fenv_t;
+
+/* If the default argument is used we use this value.  */
+extern const fenv_t __fe_dfl_env;
+#define FE_DFL_ENV	(&__fe_dfl_env);
+
+#ifdef __USE_GNU
+/* Floating-point environment where none of the exceptions are masked.  */
+extern const fenv_t __fe_nomask_env;
+# define FE_NOMASK_ENV	(&__fe_nomask_env);
+#endif
+
+#endif /* fenvbits.h */
diff --git a/sysdeps/powerpc/fesetenv.c b/sysdeps/powerpc/fesetenv.c
new file mode 100644
index 0000000000..136a835d21
--- /dev/null
+++ b/sysdeps/powerpc/fesetenv.c
@@ -0,0 +1,26 @@
+/* Install given floating-point environment.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+void
+fesetenv (const fenv_t *envp)
+{
+  fesetenv_register (*envp);
+}
diff --git a/sysdeps/powerpc/fesetround.c b/sysdeps/powerpc/fesetround.c
new file mode 100644
index 0000000000..0afd6ceaa5
--- /dev/null
+++ b/sysdeps/powerpc/fesetround.c
@@ -0,0 +1,41 @@
+/* Set current rounding direction.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+int
+fesetround (int round)
+{
+  fenv_union_t u;
+
+  if ((unsigned int) round > 3)
+    return 0;
+
+  /* Get the current state.  */
+  u.fenv = fegetenv_register ();
+
+  /* Set the relevant bits.  */
+  u.l[1] = u.l[1] & ~3  |  round & 3;
+
+  /* Put the new state in effect.  */
+  fesetenv_register (u.fenv);
+
+  return 1;
+}
diff --git a/sysdeps/powerpc/feupdateenv.c b/sysdeps/powerpc/feupdateenv.c
new file mode 100644
index 0000000000..b3a3f95ac3
--- /dev/null
+++ b/sysdeps/powerpc/feupdateenv.c
@@ -0,0 +1,37 @@
+/* Install given floating-point environment and raise exceptions.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+void
+feupdateenv (const fenv_t *envp)
+{
+  fenv_union_t old, new;
+
+  /* Save the currently set exceptions.  */
+  new.fenv = *envp;
+  old.fenv = fegetenv_register ();
+
+  /* Copy the set exceptions from `old' to `new'.  */
+  new.l[1] = new.l[1] & 0xE00000FF | old.l[1] & 0x1FFFFF00;
+
+  /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
+  fesetenv_register (new.fenv);
+}
diff --git a/sysdeps/powerpc/ffs.c b/sysdeps/powerpc/ffs.c
index d9d7f267af..1e65bea459 100644
--- a/sysdeps/powerpc/ffs.c
+++ b/sysdeps/powerpc/ffs.c
@@ -18,11 +18,7 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <bstring.h>
-
-#undef	ffs
-
-#ifdef	__GNUC__
+#include <string.h>
 
 int
 ffs (int x)
@@ -32,7 +28,3 @@ ffs (int x)
   asm ("cntlzw %0,%1" : "=r" (cnt) : "r" (x & -x));
   return 32 - cnt;
 }
-
-#else
-#include <sysdeps/generic/ffs.c>
-#endif
diff --git a/sysdeps/powerpc/fgetexcptflg.c b/sysdeps/powerpc/fgetexcptflg.c
new file mode 100644
index 0000000000..d6bd58dc69
--- /dev/null
+++ b/sysdeps/powerpc/fgetexcptflg.c
@@ -0,0 +1,33 @@
+/* Store current representation for exceptions.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+void
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+  fenv_union_t u;
+  unsigned int flag;
+
+  /* Get the current state.  */
+  u.fenv = fegetenv_register ();
+
+  /* Return that portion that corresponds to the requested exceptions. */
+  *flagp = flag = u.l[1] & FPSCR_STICKY_BITS & FE_to_sticky (excepts);
+}
diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h
index b31e0eeefd..d21987ffd8 100644
--- a/sysdeps/powerpc/fpu_control.h
+++ b/sysdeps/powerpc/fpu_control.h
@@ -34,20 +34,16 @@
 #define _FPU_MASK_UM  0x20 /* underflow */
 #define _FPU_MASK_XM  0x08 /* inexact */
 #define _FPU_MASK_IM  0x80 /* invalid operation */
-#define _FPU_MASK_VXCVI 0x100 /* invalid operation for integer convert */
-#define _FPU_MASK_VXSQRT 0x200 /* invalid operation for square root */
-#define _FPU_MASK_VXSOFT 0x400 /* invalid operation raised by software */
 
-#define _FPU_RESERVED 0xfffff800 /* These bits are reserved are not changed. */
+#define _FPU_RESERVED 0xffffff00 /* These bits are reserved are not changed. */
 
-/* The fdlibm code requires no interrupts for exceptions.  Don't
-   change the rounding mode, it would break long double I/O!  */
+/* The fdlibm code requires no interrupts for exceptions.  */
 #define _FPU_DEFAULT  0x00000000 /* Default value.  */
 
 /* IEEE:  same as above, but (some) exceptions;
    we leave the 'inexact' exception off.
  */
-#define _FPU_IEEE     0x000003f0
+#define _FPU_IEEE     0x000000f0
 
 /* Type of the control word.  */
 typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
@@ -59,7 +55,7 @@ typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
   tmp[1]; } )
 #define _FPU_SETCW(cw) { \
   fpu_control_t tmp[2] __attribute__ ((__aligned__(8))); \
-  tmp[0] = 0xFFF80000; /* arbitrary, more-or-less */ \
+  tmp[0] = 0xFFF80000; /* More-or-less arbitrary; this is a QNaN. */ \
   tmp[1] = cw; \
   __asm__ ("lfd 0,%0; mtfsf 255,0" : : "m" (*tmp) : "fr0"); \
 }
diff --git a/sysdeps/powerpc/fraiseexcpt.c b/sysdeps/powerpc/fraiseexcpt.c
new file mode 100644
index 0000000000..aa8f1fcdc6
--- /dev/null
+++ b/sysdeps/powerpc/fraiseexcpt.c
@@ -0,0 +1,44 @@
+/* Raise given exceptions.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+void
+feraiseexcept (int excepts)
+{
+  fenv_union_t u;
+
+  /* Raise exceptions represented by EXCEPTS.  It is the responsibility of
+     the OS to ensure that if multiple exceptions occur they are fed back
+     to this process in the proper way; this can happen in hardware,
+     anyway (in particular, inexact with overflow or underflow). */
+
+  /* Get the current state.  */
+  u.fenv = fegetenv_register ();
+
+  /* Add the exceptions */
+  u.l[1] = (u.l[1]
+	    | excepts & __FPSCR_STICKY_BITS
+	    /* Turn FE_INVALID into FE_INVALID_SOFTWARE.  */
+	    | excepts << (31 - 21) - (31 - 24)  &  __FE_INVALID_SOFTWARE);
+
+  /* Store the new status word (along with the rest of the environment),
+     triggering any appropriate exceptions.  */
+  fesetenv_register (u.fenv);
+}
diff --git a/sysdeps/powerpc/fsetexcptflg.c b/sysdeps/powerpc/fsetexcptflg.c
new file mode 100644
index 0000000000..4279b74849
--- /dev/null
+++ b/sysdeps/powerpc/fsetexcptflg.c
@@ -0,0 +1,37 @@
+/* Set floating-point environment exception handling.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+void
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+  fenv_union_t u;
+
+  /* Get the current state.  */
+  u.fenv = fegetenv_register ();
+
+  /* Replace the exception status */
+  u.l[1] = u.l[1] & FPSCR_STICKY_BITS  |  *flagp & FE_to_sticky (excepts);
+
+  /* Store the new status word (along with the rest of the environment).
+     This may cause floating-point exceptions if the restored state
+     requests it.  */
+  fesetenv_register (u.fenv);
+}
diff --git a/sysdeps/powerpc/ftestexcept.c b/sysdeps/powerpc/ftestexcept.c
new file mode 100644
index 0000000000..52733f7ae7
--- /dev/null
+++ b/sysdeps/powerpc/ftestexcept.c
@@ -0,0 +1,38 @@
+/* Test exception in current environment.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <fenv_libc.h>
+
+int
+fetestexcept (int excepts)
+{
+  fenv_union_t u;
+  int flags;
+
+  /* Get the current state.  */
+  u.fenv = fegetenv_register ();
+
+  /* Find the bits that indicate exceptions have occurred.  */
+  flags = u.l[1] & FPSCR_STICKY_BITS;
+
+  /* Set the FE_INVALID bit if any of the FE_INVALID_* bits are set.  */
+  flags |= ((u.l[1] & FE_ALL_INVALID) != 0) << 31-24;
+
+  return flags & excepts;
+}
diff --git a/sysdeps/powerpc/mathbits.h b/sysdeps/powerpc/mathbits.h
new file mode 100644
index 0000000000..2cecb6fa88
--- /dev/null
+++ b/sysdeps/powerpc/mathbits.h
@@ -0,0 +1,72 @@
+/* Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _MATHBITS_H
+#define _MATHBITS_H	1
+
+/* FIXME! This file describes properties of the compiler, not the machine;
+   it should not be part of libc!
+
+   FIXME! This file does not deal with the -fshort-double option of
+   gcc! */
+
+#ifdef __GNUC__
+#if __STDC__ == 1
+
+/* In GNU or ANSI mode, gcc leaves `float' expressions as-is, I think.  */
+typedef float float_t;		/* `float' expressions are evaluated as
+				   `float'.  */
+typedef double double_t;	/* `double' expressions are evaluated as
+				   `double'.  */
+
+/* Signal that types stay as they were declared.  */
+#define FLT_EVAL_METHOD	0
+
+/* Define `INFINITY' as value of type `float_t'.  */
+#define INFINITY	HUGE_VALF
+
+#else 
+
+/* For `gcc -traditional', `float' expressions are evaluated as `double'. */
+typedef double float_t;		/* `float' expressions are evaluated as
+				   `double'.  */
+typedef double double_t;	/* `double' expressions are evaluated as
+				   `double'.  */
+
+/* Signal that both types are `double'.  */
+#define FLT_EVAL_METHOD	1
+
+/* Define `INFINITY' as value of type `float_t'.  */
+#define INFINITY	HUGE_VAL
+
+#endif
+#else
+
+/* Wild guess at types for float_t and double_t. */
+typedef double float_t;
+typedef double double_t;
+
+/* Strange compiler, we don't know how it works.  */
+#define FLT_EVAL_METHOD	-1
+
+/* Define `INFINITY' as value of type `float_t'.  */
+#define INFINITY	HUGE_VAL
+
+#endif
+
+#endif /* mathbits.h */
diff --git a/sysdeps/powerpc/setjmp.S b/sysdeps/powerpc/setjmp.S
index 755ef6504c..af10581af0 100644
--- a/sysdeps/powerpc/setjmp.S
+++ b/sysdeps/powerpc/setjmp.S
@@ -22,46 +22,46 @@
 #include <jmp_buf.h>
 
 ENTRY (__sigsetjmp)
-	stw 1,(JB_GPR1*4)(3)
-	mflr 0
-	stw 2,(JB_GPR2*4)(3)
-	stw 14,((JB_GPRS+0)*4)(3)
-	stfd 14,((JB_FPRS+0*2)*4)(3)
-	stw 0,(JB_LR*4)(3)
-	stw 15,((JB_GPRS+1)*4)(3)
-	stfd 15,((JB_FPRS+1*2)*4)(3)
-	stw 16,((JB_GPRS+2)*4)(3)
-	stfd 16,((JB_FPRS+2*2)*4)(3)
-	stw 17,((JB_GPRS+3)*4)(3)
-	stfd 17,((JB_FPRS+3*2)*4)(3)
-	stw 18,((JB_GPRS+4)*4)(3)
-	stfd 18,((JB_FPRS+4*2)*4)(3)
-	stw 19,((JB_GPRS+5)*4)(3)
-	stfd 19,((JB_FPRS+5*2)*4)(3)
-	stw 20,((JB_GPRS+6)*4)(3)
-	stfd 20,((JB_FPRS+6*2)*4)(3)
-	stw 21,((JB_GPRS+7)*4)(3)
-	stfd 21,((JB_FPRS+7*2)*4)(3)
-	stw 22,((JB_GPRS+8)*4)(3)
-	stfd 22,((JB_FPRS+8*2)*4)(3)
-	stw 23,((JB_GPRS+9)*4)(3)
-	stfd 23,((JB_FPRS+9*2)*4)(3)
-	stw 24,((JB_GPRS+10)*4)(3)
-	stfd 24,((JB_FPRS+10*2)*4)(3)
-	stw 25,((JB_GPRS+11)*4)(3)
-	stfd 25,((JB_FPRS+11*2)*4)(3)
-	stw 26,((JB_GPRS+12)*4)(3)
-	stfd 26,((JB_FPRS+12*2)*4)(3)
-	stw 27,((JB_GPRS+13)*4)(3)
-	stfd 27,((JB_FPRS+13*2)*4)(3)
-	stw 28,((JB_GPRS+14)*4)(3)
-	stfd 28,((JB_FPRS+14*2)*4)(3)
-	stw 29,((JB_GPRS+15)*4)(3)
-	stfd 29,((JB_FPRS+15*2)*4)(3)
-	stw 30,((JB_GPRS+16)*4)(3)
-	stfd 30,((JB_FPRS+16*2)*4)(3)
-	stw 31,((JB_GPRS+17)*4)(3)
-	stfd 31,((JB_FPRS+17*2)*4)(3)
+	stw  %r1,(JB_GPR1*4)(3)
+	mflr %r0
+	stw  %r2,(JB_GPR2*4)(3)
+	stw  %r14,((JB_GPRS+0)*4)(3)
+	stfd %f14,((JB_FPRS+0*2)*4)(3)
+	stw  %r0,(JB_LR*4)(3)
+	stw  %r15,((JB_GPRS+1)*4)(3)
+	stfd %f15,((JB_FPRS+1*2)*4)(3)
+	stw  %r16,((JB_GPRS+2)*4)(3)
+	stfd %f16,((JB_FPRS+2*2)*4)(3)
+	stw  %r17,((JB_GPRS+3)*4)(3)
+	stfd %f17,((JB_FPRS+3*2)*4)(3)
+	stw  %r18,((JB_GPRS+4)*4)(3)
+	stfd %f18,((JB_FPRS+4*2)*4)(3)
+	stw  %r19,((JB_GPRS+5)*4)(3)
+	stfd %f19,((JB_FPRS+5*2)*4)(3)
+	stw  %r20,((JB_GPRS+6)*4)(3)
+	stfd %f20,((JB_FPRS+6*2)*4)(3)
+	stw  %r21,((JB_GPRS+7)*4)(3)
+	stfd %f21,((JB_FPRS+7*2)*4)(3)
+	stw  %r22,((JB_GPRS+8)*4)(3)
+	stfd %f22,((JB_FPRS+8*2)*4)(3)
+	stw  %r23,((JB_GPRS+9)*4)(3)
+	stfd %f23,((JB_FPRS+9*2)*4)(3)
+	stw  %r24,((JB_GPRS+10)*4)(3)
+	stfd %f24,((JB_FPRS+10*2)*4)(3)
+	stw  %r25,((JB_GPRS+11)*4)(3)
+	stfd %f25,((JB_FPRS+11*2)*4)(3)
+	stw  %r26,((JB_GPRS+12)*4)(3)
+	stfd %f26,((JB_FPRS+12*2)*4)(3)
+	stw  %r27,((JB_GPRS+13)*4)(3)
+	stfd %f27,((JB_FPRS+13*2)*4)(3)
+	stw  %r28,((JB_GPRS+14)*4)(3)
+	stfd %f28,((JB_FPRS+14*2)*4)(3)
+	stw  %r29,((JB_GPRS+15)*4)(3)
+	stfd %f29,((JB_FPRS+15*2)*4)(3)
+	stw  %r30,((JB_GPRS+16)*4)(3)
+	stfd %f30,((JB_FPRS+16*2)*4)(3)
+	stw  %r31,((JB_GPRS+17)*4)(3)
+	stfd %f31,((JB_FPRS+17*2)*4)(3)
 #ifdef PIC
 	b __sigjmp_save@plt
 #else
diff --git a/sysdeps/powerpc/strlen.s b/sysdeps/powerpc/strlen.s
index eb6a88e2b8..fa1c670912 100644
--- a/sysdeps/powerpc/strlen.s
+++ b/sysdeps/powerpc/strlen.s
@@ -68,78 +68,78 @@
  # them, the others we must save.
 
 	.section ".text"
-	.align 3
+	.align 2
 	.globl strlen
 	.type strlen,@function
 strlen:
  # On entry, r3 points to the string, and it's left that way.
- # We use r6 to store 0x01010101, and r7 to store 0x7f7f7f7f.
+ # We use r6 to store 0xfefefeff, and r7 to store 0x7f7f7f7f.
  # r4 is used to keep the current index into the string; r5 holds
  # the number of padding bits we prepend to the string to make it
  # start at a word boundary. r8 holds the 'current' word.
  # r9-12 are temporaries. r0 is used as a temporary and for discarded
  # results.
-	clrrwi 4,3,2
-	lis 6,0xfeff
-	lis 7,0x7f7f
-	rlwinm 10,3,0,29,29
-	lwz 8,0(4)
-	addi 7,7,0x7f7f
-	rlwinm 5,3,3,27,28
-	cmpwi 1,10,0
-	li 9,-1
+	clrrwi %r4,%r3,2
+	lis   %r6,0xfeff
+	lis   %r7,0x7f7f
+	rlwinm %r10,%r3,0,29,29
+	lwz   %r8,0(%r4)
+	addi  %r7,%r7,0x7f7f
+	rlwinm %r5,%r3,3,27,28
+	cmpwi %cr1,%r10,0
+	li    %r9,-1
  # That's the setup done, now do the first pair of words.
  # We make an exception and use method (2) on the first two words, to reduce
  # overhead.
-	srw 9,9,5
-	and 0,7,8
-	or 10,7,8
-	add 0,0,7
-	nor 0,10,0
-	and. 8,0,9
-	bne done0
+	srw   %r9,%r9,%r5
+	and   %r0,%r7,%r8
+	or    %r10,%r7,%r8
+	add   %r0,%r0,%r7
+	nor   %r0,%r10,%r0
+	and.  %r8,%r0,%r9
+	bne   done0
  # Handle second word of pair. Put addi between branches to avoid hurting
  # branch prediction.
-	addi 6,6,0xfffffeff
-
-	bne 1,loop
-	lwzu 8,4(4)
-	and 0,7,8
-	or 10,7,8
-	add 0,0,7
-	nor. 0,10,0
-	bne done0
+	addi  %r6,%r6,0xfffffeff
+	
+	bne   %cr1,loop
+	lwzu  %r8,4(%r4)
+	and   %r0,%r7,%r8
+	or    %r10,%r7,%r8
+	add   %r0,%r0,%r7
+	nor.  %r8,%r10,%r0
+	bne   done0
 
  # The loop.
+	
+loop:	lwz   %r8,4(%r4)
+	lwzu  %r9,8(%r4)
+	add   %r0,%r6,%r8
+	nor   %r10,%r7,%r8
+	and.  %r0,%r0,%r10
+	add   %r11,%r6,%r9
+	nor   %r12,%r7,%r9
+	bne   done1
+	and.  %r0,%r11,%r12
+	beq   loop
 
-loop:	lwz 8,4(4)
-	lwzu 9,8(4)
-	add 0,6,8
-	nor 10,7,8
-	and. 0,0,10
-	add 11,6,9
-	nor 12,7,9
-	bne done1
-	and. 0,11,12
-	beq loop
-
-	and 0,7,9
-	or 10,7,9
-	b done2
-
-done1:	addi 4,4,-4
-	and 0,7,9
-	or 10,7,9
-done2:	add 0,0,7
-	nor 0,10,0
-
+	and   %r0,%r7,%r9
+	add   %r0,%r0,%r7
+	andc  %r8,%r12,%r0
+	b     done0
+	
+done1:	and   %r0,%r7,%r8
+	subi  %r4,%r4,4
+	add   %r0,%r0,%r7
+	andc  %r8,%r10,%r0
+	
  # When we get to here, r4 points to the first word in the string that
  # contains a zero byte, and the most significant set bit in r8 is in that
  # byte.
-done0:	cntlzw 11,8
-	subf 0,3,4
-	srwi 11,11,3
-	add 3,0,11
+done0:	cntlzw %r11,%r8
+	subf  %r0,%r3,%r4
+	srwi  %r11,%r11,3
+	add   %r3,%r0,%r11
 	blr
 0:
 	.size	 strlen,0b-strlen