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/Makefile6
-rw-r--r--sysdeps/powerpc/bits/mathinline.h44
-rw-r--r--sysdeps/powerpc/bzero.S27
-rw-r--r--sysdeps/powerpc/dl-machine.h71
-rw-r--r--sysdeps/powerpc/machine-gmon.h1
-rw-r--r--sysdeps/powerpc/stpcpy.S100
-rw-r--r--sysdeps/powerpc/strcat.c30
-rw-r--r--sysdeps/powerpc/strcpy.S100
8 files changed, 338 insertions, 41 deletions
diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
index 3e8f22b573..1813c78dd8 100644
--- a/sysdeps/powerpc/Makefile
+++ b/sysdeps/powerpc/Makefile
@@ -21,7 +21,7 @@ endif
 # so that's at least 8192 entries.  Since libc only uses about 1200 entries,
 # we want to use -fpic, because this generates fewer relocs.
 ifeq (yes,$(build-shared))
-CFLAGS-.os = -fpic -fno-common
+pic-ccflag = -fpic
 endif
 
 # The initfini generation code doesn't work in the presence of -fPIC, so
@@ -29,3 +29,7 @@ endif
 ifeq ($(subdir),csu)
 CFLAGS-initfini.s = -g0 -fpic
 endif
+
+ifeq ($(subdir),string)
+CFLAGS-memcmp.c += -Wno-uninitialized
+endif
diff --git a/sysdeps/powerpc/bits/mathinline.h b/sysdeps/powerpc/bits/mathinline.h
index d7f2a3ac0d..d7cabaf28b 100644
--- a/sysdeps/powerpc/bits/mathinline.h
+++ b/sysdeps/powerpc/bits/mathinline.h
@@ -32,34 +32,22 @@ __sgn1 (double __x)
 {
   return __x >= 0.0 ? 1.0 : -1.0;
 }
+#endif /* __NO_MATH_INLINES && __OPTIMZE__ */
 
-/* We'd want to use this if it was implemented in hardware, but
-   how can we tell? */
-#if 0
-__MATH_INLINE double sqrt (double __x);
-__MATH_INLINE double
-sqrt (double __x)
-{
-  register double __value;
-  __asm
-    ("fsqrt %0,%1"
-     : "=f" (__value) : "f" (__x));
-
-  return __value;
-}
-#endif
-
-__MATH_INLINE double fabs (double __x);
-__MATH_INLINE double
-fabs (double __x)
-{
-  register double __value;
-  __asm
-    ("fabs %0,%1"
-     : "=f" (__value) : "f" (__x));
-
-  return __value;
-}
+#if __USE_ISOC9X
+# define __unordered_cmp(x, y) \
+  (__extension__							      \
+   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
+      unsigned __r;							      \
+      __asm__("fcmpu 7,%1,%2 ; mfcr %0" : "=r" (__r) : "f" (__x), "f"(__y));  \
+      __r; }))
+
+# define isgreater(x, y) (__unordered_cmp (x, y) >> 2 & 1)
+# define isgreaterequal(x, y) ((__unordered_cmp (x, y) & 6) != 0)
+# define isless(x, y) (__unordered_cmp (x, y) >> 3 & 1)
+# define islessequal(x, y) ((__unordered_cmp (x, y) & 0xA) != 0)
+# define islessgreater(x, y) ((__unordered_cmp (x, y) & 0xC) != 0)
+# define isunordered(x, y) (__unordered_cmp (x, y) & 1)
+#endif /* __USE_ISOC9X */
 
-#endif /* __NO_MATH_INLINES && __OPTIMZE__ */
 #endif /* __GNUC__  */
diff --git a/sysdeps/powerpc/bzero.S b/sysdeps/powerpc/bzero.S
new file mode 100644
index 0000000000..783a91fdcb
--- /dev/null
+++ b/sysdeps/powerpc/bzero.S
@@ -0,0 +1,27 @@
+/* Optimized bzero `implementation' for PowerPC.
+   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 <sysdep.h>
+
+ENTRY(__bzero)
+	mr	%r5,%r4
+	li	%r4,0
+	b	memset@local
+END(__bzero)
+weak_alias (__bzero, bzero)
diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h
index 771b711a14..70a3f20b31 100644
--- a/sysdeps/powerpc/dl-machine.h
+++ b/sysdeps/powerpc/dl-machine.h
@@ -199,6 +199,53 @@ _dl_runtime_resolve:
 	bctr
 0:
 	.size	 _dl_runtime_resolve,0b-_dl_runtime_resolve
+
+	.align 2
+	.globl _dl_prof_resolve
+	.type _dl_prof_resolve,@function
+_dl_prof_resolve:
+ # We need to save the registers used to pass parameters, and register 0,
+ # which is used by _mcount; the registers are saved in a stack frame.
+	stwu 1,-48(1)
+        stw 0,12(1)
+	stw 3,16(1)
+	stw 4,20(1)
+ # The code that calls this has put parameters for `fixup' in r12 and r11.
+	mr 3,12
+	stw 5,24(1)
+	mr 4,11
+	stw 6,28(1)
+	mflr 5
+ # We also need to save some of the condition register fields.
+	stw 7,32(1)
+	stw 5,52(1)
+	stw 8,36(1)
+	mfcr 0
+	stw 9,40(1)
+	stw 10,44(1)
+	stw 0,8(1)
+	bl profile_fixup@local
+ # 'fixup' returns the address we want to branch to.
+	mtctr 3
+ # Put the registers back...
+	lwz 0,52(1)
+	lwz 10,44(1)
+	lwz 9,40(1)
+	mtlr 0
+	lwz 8,36(1)
+	lwz 0,8(1)
+	lwz 7,32(1)
+	lwz 6,28(1)
+	mtcrf 0xFF,0
+	lwz 5,24(1)
+	lwz 4,20(1)
+	lwz 3,16(1)
+        lwz 0,12(1)
+ # ...unwind the stack frame, and jump to the PLT entry we updated.
+	addi 1,1,48
+	bctr
+0:
+	.size	 _dl_prof_resolve,0b-_dl_prof_resolve
  # Undo '.section text'.
 	.previous
 ");
@@ -409,8 +456,14 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
       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;
+      extern void _dl_runtime_resolve (void);
+      extern void _dl_prof_resolve (void);
+      Elf32_Word dlrr;
+
+      dlrr = (Elf32_Word)(char *)(profile
+				  ? _dl_prof_resolve
+				  : _dl_runtime_resolve);
 
       if (lazy)
 	for (i = 0; i < num_plt_entries; i++)
@@ -433,8 +486,7 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
       /* 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)
+      if (dlrr <= 0x01fffffc || dlrr >= 0xfe000000)
 	{
 	  /* Load address of link map in r12.  */
 	  plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) map);
@@ -442,15 +494,13 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
 					   + 0x8000) >> 16));
 
 	  /* Call _dl_runtime_resolve.  */
-	  plt[4] = OPCODE_BA ((Elf32_Word) (char *) _dl_runtime_resolve);
+	  plt[4] = OPCODE_BA (dlrr);
 	}
       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[2] = OPCODE_LI (12, dlrr);
+	  plt[3] = OPCODE_ADDIS (12, 12, (dlrr + 0x8000) >> 16);
 	  plt[4] = OPCODE_MTCTR (12);
 
 	  /* Load address of link map in r12.  */
@@ -501,7 +551,6 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
 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. */
 }
 
@@ -513,7 +562,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
    LOADADDR is the load address of the object; INFO is an array indexed
    by DT_* of the .dynamic section info.  */
 
-static inline void
+static void
 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 		  const Elf32_Sym *sym, const struct r_found_version *version,
 		  Elf32_Addr *const reloc_addr)
@@ -709,4 +758,4 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 
 #define ELF_MACHINE_NO_REL 1
 
-#endif
+#endif /* RESOLVE */
diff --git a/sysdeps/powerpc/machine-gmon.h b/sysdeps/powerpc/machine-gmon.h
index ba53807308..b890dd5c53 100644
--- a/sysdeps/powerpc/machine-gmon.h
+++ b/sysdeps/powerpc/machine-gmon.h
@@ -1,7 +1,6 @@
 /* PowerPC-specific implementation of profiling support.
    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
diff --git a/sysdeps/powerpc/stpcpy.S b/sysdeps/powerpc/stpcpy.S
new file mode 100644
index 0000000000..58ad5b12b6
--- /dev/null
+++ b/sysdeps/powerpc/stpcpy.S
@@ -0,0 +1,100 @@
+/* Optimized stpcpy implementation for PowerPC.
+   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 <sysdep.h>
+
+/* See strlen.s for comments on how the end-of-string testing works.  */
+
+EALIGN(__stpcpy,4,0)
+/* char * [r3] stpcpy (char *dest [r3], const char *src [r4])  */
+
+/* General register assignments:
+   r0:	temporary
+   r3:	pointer to previous word in dest
+   r4:	pointer to previous word in src
+   r6:	current word from src
+   r7:	0xfefefeff
+   r8:	0x7f7f7f7f
+   r9:	~(word in src | 0x7f7f7f7f)
+   r10:	alternate word from src.  */
+
+	or    %r0,%r4,%r3
+	clrlwi. %r0,%r0,30
+	addi  %r3,%r3,-4
+	bne   L(unaligned)
+
+	lis   %r7,0xfeff
+	lis   %r8,0x7f7f
+	lwz   %r6,0(%r4)
+	addi  %r7,%r7,-0x101
+	addi  %r8,%r8,0x7f7f
+	b     2f
+
+0:	lwzu  %r10,4(%r4)
+	stwu  %r6,4(%r3)
+	add   %r0,%r7,%r10
+	nor   %r9,%r8,%r10
+	and.  %r0,%r0,%r9
+	bne-  1f
+	lwzu  %r6,4(%r4)
+	stwu  %r10,4(%r3)
+2:	add   %r0,%r7,%r6
+	nor   %r9,%r8,%r6
+	and.  %r0,%r0,%r9
+	beq+  0b
+
+	mr    %r10,%r6
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+1:	rlwinm. %r0,%r10,8,24,31
+	stbu  %r0,4(%r3)
+	beqlr-
+	rlwinm. %r0,%r10,16,24,31
+	stbu  %r0,1(%r3)
+	beqlr-
+	rlwinm. %r0,%r10,24,24,31
+	stbu  %r0,1(%r3)
+	beqlr-
+	stbu  %r10,1(%r3)
+	blr
+
+/* Oh well.  In this case, we just do a byte-by-byte copy.  */
+	.align 4
+	nop
+L(unaligned):
+	lbz   %r6,0(%r4)
+	addi  %r3,%r3,3
+	cmpwi %r6,0
+	beq-  2f
+
+0:	lbzu  %r10,1(%r4)
+	stbu  %r6,1(%r3)
+	cmpwi %r10,0
+	beq-  1f
+	nop		/* Let 601 load start of loop.  */
+	lbzu  %r6,1(%r4)
+	stbu  %r10,1(%r3)
+	cmpwi %r6,0
+	bne+  0b
+2:	stbu  %r6,1(%r3)
+	blr
+1:	stbu  %r10,1(%r3)
+	blr
+END(__stpcpy)
+
+weak_alias (__stpcpy, stpcpy)
diff --git a/sysdeps/powerpc/strcat.c b/sysdeps/powerpc/strcat.c
new file mode 100644
index 0000000000..9d9ab6549a
--- /dev/null
+++ b/sysdeps/powerpc/strcat.c
@@ -0,0 +1,30 @@
+/* strcat version that uses fast strcpy/strlen.
+   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 <string.h>
+
+#undef strcat
+
+/* Append SRC on the end of DEST.  */
+char *
+strcat (char *dest, const char *src)
+{
+  strcpy (dest + strlen (dest), src);
+  return dest;
+}
diff --git a/sysdeps/powerpc/strcpy.S b/sysdeps/powerpc/strcpy.S
new file mode 100644
index 0000000000..3c0cce7844
--- /dev/null
+++ b/sysdeps/powerpc/strcpy.S
@@ -0,0 +1,100 @@
+/* Optimized strcpy implementation for PowerPC.
+   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 <sysdep.h>
+
+/* See strlen.s for comments on how the end-of-string testing works.  */
+
+EALIGN(strcpy,4,0)
+/* char * [r3] strcpy (char *dest [r3], const char *src [r4])  */
+
+/* General register assignments:
+   r0:	temporary
+   r3:	saved `dest'
+   r4:	pointer to previous word in src
+   r5:	pointer to previous word in dest
+   r6:	current word from src
+   r7:	0xfefefeff
+   r8:	0x7f7f7f7f
+   r9:	~(word in src | 0x7f7f7f7f)
+   r10:	alternate word from src.  */
+
+	or    %r0,%r4,%r3
+	clrlwi. %r0,%r0,30
+	addi  %r5,%r3,-4
+	bne   L(unaligned)
+
+	lis   %r7,0xfeff
+	lis   %r8,0x7f7f
+	lwz   %r6,0(%r4)
+	addi  %r7,%r7,-0x101
+	addi  %r8,%r8,0x7f7f
+	b     2f
+
+0:	lwzu  %r10,4(%r4)
+	stwu  %r6,4(%r5)
+	add   %r0,%r7,%r10
+	nor   %r9,%r8,%r10
+	and.  %r0,%r0,%r9
+	bne-  1f
+	lwzu  %r6,4(%r4)
+	stwu  %r10,4(%r5)
+2:	add   %r0,%r7,%r6
+	nor   %r9,%r8,%r6
+	and.  %r0,%r0,%r9
+	beq+  0b
+
+	mr    %r10,%r6
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+1:	rlwinm. %r0,%r10,8,24,31
+	stb   %r0,4(%r5)
+	beqlr-
+	rlwinm. %r0,%r10,16,24,31
+	stb   %r0,5(%r5)
+	beqlr-
+	rlwinm. %r0,%r10,24,24,31
+	stb   %r0,6(%r5)
+	beqlr-
+	stb   %r10,7(%r5)
+	blr
+
+/* Oh well.  In this case, we just do a byte-by-byte copy.  */
+	.align 4
+	nop
+L(unaligned):
+	lbz   %r6,0(%r4)
+	addi  %r5,%r3,-1
+	cmpwi %r6,0
+	beq-  2f
+
+0:	lbzu  %r10,1(%r4)
+	stbu  %r6,1(%r5)
+	cmpwi %r10,0
+	beq-  1f
+	nop		/* Let 601 load start of loop.  */
+	lbzu  %r6,1(%r4)
+	stbu  %r10,1(%r5)
+	cmpwi %r6,0
+	bne+  0b
+2:	stb   %r6,1(%r5)
+	blr
+1:	stb   %r10,1(%r5)
+	blr
+
+END(strcpy)