From 1f205a479b43e5e40672fe5b4ae8f717b28c41b1 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 21 May 1997 01:48:59 +0000 Subject: Update. 1997-05-21 02:49 Ulrich Drepper * gnu-versions.h (_GNU_OBSTACK_INTERFACE_VERSION): Set to 2 since interface was changed with addition of _obstack_memory_used. Suggested by Ian Taylor . * malloc/obstack.c: Include . Include only if __GNU_LIBRARY__ or HAVE_STDLIB_H is defined. Reported by Ian Taylor . * dirent/Makefile (routines): Add versionsort. * dirent/dirent.h: Add prototype for versionsort. * dirent/versionsort.c: New file. * manual/filesys.texi: Add documentation for versionsort. * manual/string.texi: Add documentation for strverscmp. * string/Makefile (routines): Add strverscmp. (tests): Add tst-svc. * string/string.h: Add prototype for strverscmp. * string/strverscmp.c: New file. * string/tst-svc.c: New file. Test for strverscmp. * string/tst-svc.input: New file. Input data for tst-svc. * string/tst-svc.expect: New file. Expected out from tst-svc. * math/Makefile (calls): Add s_signbit. * po/sv.po: Update. * resolv/nss_dns/dns-host.c: Add casts to prevent warnings. * sunrpc/pmap_rmt.c: Likewise. * string/basename.c: Don't use ISO C definition style. Include is HAVE_CONFIG_H is defined. * sunrpc/proto.h: Add `const' wherever possible. * sunrpc/rpc_cout.c: Likewise. * sunrpc/rpc_svcout.c: Likewise. * sunrpc/xdr_mem.c: Likewise. * sunrpc/xdr_rec.c: Likewise. * sunrpc/xdr_stdio.c: Likewise. * sunrpc/rpc_parse.c: Delete comma from end of enum definition. * sunrpc/xdr.c: Little code cleanups. * sunrpc/xdr_flaot.c: Likewise. Patches by Matthew Wilcox . * sysdeps/i386/fpu/__math.h (__finite): Fix typo. * sysdeps/unix/sysv/linux/shmdt.c: Add cast to prevent warning. * time/europe: Update from tzdata1997f. * time/zic.c: Update from tzcode1997e. 1997-05-20 19:20 Miguel de Icaza * sysdeps/sparc/setjmp.S: Flush windows. Bug found by Richard Henderson. 1997-05-19 12:54 Andreas Schwab * misc/efgcvt_r.c (fcvt_r, ecvt_r): Rewritten as to fit the specs. 1997-05-19 18:41 Thorsten Kukuk * nis/nss_nisplus/nisplus-spwd.c (_nss_nisplus_parse_spent): Use atol instead of atoi. 1997-05-18 00:22 Philip Blundell * inet/Makefile (routines): Add if_index. * sysdeps/unix/sysv/linux/if_index.c: New file. * sysdeps/stub/if_index.c: New file. * sysdeps/unix/sysv/linux/net/if.h: Add prototypes for routines in if_index.c (required by IPv6 basic API). * sysdeps/unix/sysv/linux/netinet/in.h: Add struct ipv6_pktinfo. 1997-05-17 23:29 Philip Blundell * sysdeps/unix/sysv/linux/netinet/in.h: Update IPv6 definitions for new advanced API draft. 1997-05-13 21:33 Andreas Schwab * stdio-common/printf_fp.c: Only use the field width for deciding on padding when printing special values. * stdio-common/printf_fphex.c: Likewise. 1997-05-15 13:14 Miles Bader Changes by Thomas Bushnell : * hurd/hurdauth.c (_S_msg_add_auth): Implement correctly. 1997-05-12 14:50 Thomas Bushnell, n/BSG * hurd/hurdsig.c (_hurdsig_init): Double size of sigthread stack; msg_add_auth was overflowing it. 1997-05-12 21:20 Richard Henderson * elf/dl-lookup.c (_dl_lookup_symbol_skip): Call _dl_signal_error when we can't find the symbol. 1997-05-12 16:54 Ulrich Drepper * posix/regex.c: Fix handling of 32-bit Windog environments. Patch by Arnold Robbins . 1997-05-10 23:26 Andreas Schwab * sysdeps/unix/sysv/linux/m68k/syscalls.list: Add cacheflush. 1997-05-10 11:40 Andreas Schwab * elf/ldd.bash.in: Remove spurious quote character from version message. 1997-05-10 08:49 Andreas Schwab * locale/programs/locale.c (write_charmaps): Don't get stuck in a loop if the file ends in a long line without newline. * locale/programs/charmap.c (charmap_read): Likewise. 1997-05-12 03:47 Ulrich Drepper * sunrpc/rpc/xdr.h: Include more headers to be self-contained. * sunrpc/rpc/svc_auth.h: Likewise. * sunrpc/rpc/svc.h: Likewise. * sunrpc/rpc/rpc_msg.h: Likewise. * sunrpc/rpc/pmap_rmt.h: Likewise. * sunrpc/rpc/pmap_clnt.h: Likewise. * sunrpc/rpc/clnt.h: Likewise. * sunrpc/rpc/auth_unix.h: Likewise. * sysdeps/generic/rpc/auth.h: Likewise. Patches by Michael Deutschmann . 1997-05-11 15:29 Philip Blundell * sysdeps/stub/sigaction.c (__sigaction): Correct typo. * sysdeps/standalone/arm/errnos.h: New file. * sysdeps/stub/sys/param.h: Add dummy definition of MAXSYMLINKS. * sysdeps/unix/arm/fork.S: New file. * sysdeps/unix/sysv/linux/arm/sysdep.h: New file. * sysdeps/stub/tempname.c (__stdio_gen_tempname): Add missing `streamptr' argument. * sysdeps/stub/vdprintf.c: Remove second copy of file (!), include to get va_list defined, return 0 not NULL. * sysdeps/unix/sysv/linux/statfsbuf.h: Include . * sysdeps/unix/sysv/linux/arm/syscall.S: New file. * sysdeps/stub/direntry.h (struct dirent): Add missing ';'. * sysdeps/stub/seekdir.c (seekdir): Likewise. * sysdeps/stub/dirfd.c (dirfd): Argument dirp is DIR*, not FILE*. * sysdeps/standalone/dirstream.h: Define struct __dirstream not DIR; provides typedef. * sysdeps/unix/sysv/linux/arm/clone.S: New file. * sysdeps/unix/sysv/linux/arm/socket.S: New file. * sysdeps/stub/sysconf.c (__sysconf): Fix typos. 1997-05-01 06:35 Geoff Keating * sysdeps/powerpc/Dist: New file. * sysdeps/powerpc/Makefile: New file. * sysdeps/powerpc/fclrexcpt.c: New file. * sysdeps/powerpc/fegetenv.c: New file. * sysdeps/powerpc/fegetround.c: New file. * sysdeps/powerpc/feholdexcpt.c: New file. * sysdeps/powerpc/fenvbits.h: New file. * sysdeps/powerpc/fenv_const.c: New file. * sysdeps/powerpc/fenv_libc.h: New file. * sysdeps/powerpc/fesetenv.c: New file. * sysdeps/powerpc/fesetround.c: New file. * sysdeps/powerpc/feupdateenv.c: New file. * sysdeps/powerpc/fgetexcptflg.c: New file. * sysdeps/powerpc/fraiseexcpt.c: New file. * sysdeps/powerpc/fsetexcptflg.c: New file. * sysdeps/powerpc/ftestexcept.c: New file. * sysdeps/powerpc/mathbits.h: New file. * sysdeps/powerpc/dl-machine.h: Wrap in #ifndef dl_machine_h; define elf_machine_lookup_noexec_p, elf_machine_lookup_noplt_p, ELF_MACHINE_RELOC_NOPLT; consequent changes to elf_machine_rela. * sysdeps/powerpc/__math.h: Remove definition for hypot and __sgn. * sysdep/powerpc/fpu_control.h: Correct IEEE default mode. * sysdeps/unix/sysv/linux/powerpc/sysdep.h: Don't use .text, but instead .section ".text". 1997-04-25 05:06 Geoff Keating * sysdeps/powerpc/__longjmp.S: Use symbolic register numbering. * sysdeps/powerpc/bsd-_setjmp.S: Likewise. * sysdeps/powerpc/bsd-setjmp.S: Likewise. * sysdeps/powerpc/setjmp.S: Likewise. * sysdeps/unix/sysv/linux/clone.S: Likewise. * sysdeps/unix/sysv/linux/socket.S: Likewise. * sysdeps/unix/sysv/linux/syscall.S: Likewise. 1997-04-20 04:37 Geoff Keating * sysdeps/powerpc/strchr.s: New file. * sysdeps/powerpc/strcmp.s: New (ugly) file. * sysdeps/powerpc/memset.s: New file. * string/tester.c: Include prototype and _GNU_SOURCE to make standalone compilation possible. Give strcmp a better test. Give memset a better test. 1997-04-05 06:34 Geoff Keating * sysdeps/powerpc/strlen.s: Fixed bugs (how did it ever pass its tests before?). Changed to symbolic register numbering as an experiment. * sysdeps/powerpc/ffs.c: Don't include bstring.h, it doesn't exist. * sysdeps/rs6000/ffs.c: Likewise. 1997-05-12 02:28 Ulrich Drepper * time/sys/time.h: Make second argument of setitimer const. Patch by Michael Deutschmann . * sysdeps/stub/setitimer.c: Likewise. * sysdeps/mach/hurd/setitimer.c: Likewise. --- sysdeps/powerpc/Dist | 1 + sysdeps/powerpc/Makefile | 3 + sysdeps/powerpc/__longjmp.S | 82 ++--- sysdeps/powerpc/__math.h | 19 -- sysdeps/powerpc/bsd-_setjmp.S | 2 +- sysdeps/powerpc/bsd-setjmp.S | 2 +- sysdeps/powerpc/dl-machine.h | 714 +++++++++++++++++++++-------------------- sysdeps/powerpc/fclrexcpt.c | 35 ++ sysdeps/powerpc/fegetenv.c | 26 ++ sysdeps/powerpc/fegetround.c | 31 ++ sysdeps/powerpc/feholdexcpt.c | 38 +++ sysdeps/powerpc/fenv_const.c | 29 ++ sysdeps/powerpc/fenv_libc.h | 57 ++++ sysdeps/powerpc/fenvbits.h | 130 ++++++++ sysdeps/powerpc/fesetenv.c | 26 ++ sysdeps/powerpc/fesetround.c | 41 +++ sysdeps/powerpc/feupdateenv.c | 37 +++ sysdeps/powerpc/ffs.c | 10 +- sysdeps/powerpc/fgetexcptflg.c | 33 ++ sysdeps/powerpc/fpu_control.h | 12 +- sysdeps/powerpc/fraiseexcpt.c | 44 +++ sysdeps/powerpc/fsetexcptflg.c | 37 +++ sysdeps/powerpc/ftestexcept.c | 38 +++ sysdeps/powerpc/mathbits.h | 72 +++++ sysdeps/powerpc/setjmp.S | 80 ++--- sysdeps/powerpc/strlen.s | 104 +++--- 26 files changed, 1185 insertions(+), 518 deletions(-) create mode 100644 sysdeps/powerpc/Dist create mode 100644 sysdeps/powerpc/Makefile create mode 100644 sysdeps/powerpc/fclrexcpt.c create mode 100644 sysdeps/powerpc/fegetenv.c create mode 100644 sysdeps/powerpc/fegetround.c create mode 100644 sysdeps/powerpc/feholdexcpt.c create mode 100644 sysdeps/powerpc/fenv_const.c create mode 100644 sysdeps/powerpc/fenv_libc.h create mode 100644 sysdeps/powerpc/fenvbits.h create mode 100644 sysdeps/powerpc/fesetenv.c create mode 100644 sysdeps/powerpc/fesetround.c create mode 100644 sysdeps/powerpc/feupdateenv.c create mode 100644 sysdeps/powerpc/fgetexcptflg.c create mode 100644 sysdeps/powerpc/fraiseexcpt.c create mode 100644 sysdeps/powerpc/fsetexcptflg.c create mode 100644 sysdeps/powerpc/ftestexcept.c create mode 100644 sysdeps/powerpc/mathbits.h (limited to 'sysdeps/powerpc') 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 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 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 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 @@ -134,182 +137,231 @@ 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. */ +/* The PLT uses Elf32_Rela relocs. */ +#define elf_machine_relplt elf_machine_rela -#ifdef RESOLVE + /* This code is used in dl-runtime.c to call the `fixup' function + and then redirect to the address it returns. It is called + from code built in the PLT by elf_machine_runtime_setup. */ +#define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ + .section \".text\" + .align 2 + .globl _dl_runtime_resolve + .type _dl_runtime_resolve,@function +_dl_runtime_resolve: + # We need to save the registers used to pass parameters. + # We build a stack frame to put them in. + stwu 1,-48(1) + mflr 0 + stw 3,16(1) + stw 4,20(1) + stw 0,52(1) + stw 5,24(1) + # We also need to save some of the condition register fields. + mfcr 0 + stw 6,28(1) + stw 7,32(1) + stw 8,36(1) + stw 9,40(1) + stw 10,44(1) + stw 0,12(1) + # The code that calls this has put parameters for `fixup' in r12 and r11. + mr 3,12 + mr 4,11 + bl 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 0,12(1) + lwz 8,36(1) + lwz 7,32(1) + lwz 6,28(1) + mtcrf 0xFF,0 + lwz 5,24(1) + lwz 4,20(1) + lwz 3,16(1) + # ...unwind the stack frame, and jump to the PLT entry we updated. + addi 1,1,48 + bctr +0: + .size _dl_runtime_resolve,0b-_dl_runtime_resolve + # undo '.section text'. + .previous +"); -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); +/* Initial entry point code for the dynamic linker. + The C function `_dl_start' is the real entry point; + its return value is the user program's entry point. */ +#define RTLD_START \ +static ElfW(Addr) _dl_start (void *arg) __attribute__((unused)); \ +asm ("\ + .section \".text\" + .align 2 + .globl _start + .type _start,@function +_start: + # We start with the following on the stack, from top: + # argc (4 bytes) + # arguments for program (terminated by NULL) + # environment variables (terminated by NULL) + # arguments for the program loader + # FIXME: perhaps this should do the same trick as elf/start.c? - if (rinfo == R_PPC_NONE) - return; + # Call _dl_start with one parameter pointing at argc + mr 3,1 + # (we have to frob the stack pointer a bit to allow room for + # _dl_start to save the link register) + li 4,0 + addi 1,1,-16 + stw 4,0(1) + bl _dl_start@local - 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; + # Now, we do our main work of calling initialisation procedures. + # The ELF ABI doesn't say anything about parameters for these, + # so we just pass argc, argv, and the environment. + # Changing these is strongly discouraged (not least because argc is + # passed by value!). - 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); - } + # put our GOT pointer in r31 + bl _GLOBAL_OFFSET_TABLE_-4@local + mflr 31 + # the address of _start in r30 + mr 30,3 + # &_dl_argc in 29, &_dl_argv in 27, and _dl_default_scope in 28 + lwz 28,_dl_default_scope@got(31) + lwz 29,_dl_argc@got(31) + lwz 27,_dl_argv@got(31) +0: + # call initfunc = _dl_init_next(_dl_default_scope[2]) + lwz 3,8(28) + bl _dl_init_next@plt + # if initfunc is NULL, we exit the loop + mr. 0,3 + beq 1f + # call initfunc(_dl_argc, _dl_argv, _dl_argv+_dl_argc+1) + mtlr 0 + lwz 3,0(29) + lwz 4,0(27) + slwi 5,3,2 + add 5,4,5 + addi 5,5,4 + blrl + # and loop. + b 0b +1: + # Now, to conform to the ELF ABI, we have to: + # pass argv (actually _dl_argv) in r4 + lwz 4,0(27) + # pass argc (actually _dl_argc) in r3 + lwz 3,0(29) + # pass envp (actually _dl_argv+_dl_argc+1) in r5 + slwi 5,3,2 + add 5,4,5 + addi 5,5,4 + # pass the auxilary vector in r6. This is passed just after _envp. + addi 6,5,-4 +2: lwzu 0,4(6) + cmpwi 1,0,0 + bne 2b + addi 6,6,4 + # pass a termination function pointer (in this case _dl_fini) in r7 + lwz 7,_dl_fini@got(31) + # now, call the start function in r30... + mtctr 30 + # pass the stack pointer in r1 (so far so good), pointing to a NULL value + # (this lets our startup code distinguish between a program linked statically, + # which linux will call with argc on top of the stack which will hopefully + # never be zero, and a dynamically linked program which will always have + # a NULL on the top of the stack). + # Take the opportunity to clear LR, so anyone who accidentally returns + # from _start gets SEGV. + li 0,0 + stw 0,0(1) + mtlr 0 + # and also clear _dl_starting_up + lwz 26,_dl_starting_up@got(31) + stw 0,0(26) + # go do it! + bctr +0: + .size _start,0b-_start + # undo '.section text'. + .previous +"); - /* 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; +/* The idea here is that to conform to the ABI, we are supposed to try + to load dynamic objects between 0x10000 (we actually use 0x40000 as + the lower bound, to increase the chance of a memory reference from + a null pointer giving a segfault) and the program's load address. + Regrettably, in this code we can't find the program's load address, + so we punt and choose 0x01800000, which is below the ABI's + recommended default, and what GNU ld currently chooses. We only use + the address as a preference for mmap, so if we get it wrong the + worst that happens is that it gets mapped somewhere else. - 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; + FIXME: Unfortunately, 'somewhere else' is probably right after the + program's break, which causes malloc to fail. We really need more + information here about the way memory is mapped. */ - 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; +#define ELF_PREFERRED_ADDRESS_DATA \ +static ElfW(Addr) _dl_preferred_address = 1 - 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; +#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) \ +( { \ + ElfW(Addr) prefd; \ + if (mapstartpref != 0 && _dl_preferred_address == 1) \ + _dl_preferred_address = mapstartpref; \ + if (mapstartpref != 0) \ + prefd = mapstartpref; \ + else if (_dl_preferred_address == 1) \ + prefd = _dl_preferred_address = \ + (0x01800000 - maplength - 0x10000) & \ + ~(_dl_pagesize - 1); \ + else if (_dl_preferred_address < maplength + 0x50000) \ + prefd = 0; \ + else \ + prefd = _dl_preferred_address = \ + ((_dl_preferred_address - maplength - 0x10000) \ + & ~(_dl_pagesize - 1)); \ + prefd; \ +} ) - num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val - / sizeof(Elf32_Rela)); +#define ELF_FIXED_ADDRESS(loader, mapstart) \ +( { \ + if (mapstart != 0 && _dl_preferred_address == 1) \ + _dl_preferred_address = mapstart; \ +} ) - 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"); +/* 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 - 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); -} +/* 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) -#define ELF_MACHINE_NO_REL 1 +/* 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) -#endif +/* 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. */ @@ -446,203 +498,171 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc) /* elf_machine_runtime_setup handles this. */ } -/* The PLT uses Elf32_Rela relocs. */ -#define elf_machine_relplt elf_machine_rela +#endif /* dl_machine_h */ - /* This code is used in dl-runtime.c to call the `fixup' function - and then redirect to the address it returns. It is called - from code built in the PLT by elf_machine_runtime_setup. */ -#define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ - .section \".text\" - .align 2 - .globl _dl_runtime_resolve - .type _dl_runtime_resolve,@function -_dl_runtime_resolve: - # We need to save the registers used to pass parameters. - # We build a stack frame to put them in. - stwu 1,-48(1) - mflr 0 - stw 3,16(1) - stw 4,20(1) - stw 0,52(1) - stw 5,24(1) - # We also need to save some of the condition register fields. - mfcr 0 - stw 6,28(1) - stw 7,32(1) - stw 8,36(1) - stw 9,40(1) - stw 10,44(1) - stw 0,12(1) - # The code that calls this has put parameters for `fixup' in r12 and r11. - mr 3,12 - mr 4,11 - bl 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 0,12(1) - lwz 8,36(1) - lwz 7,32(1) - lwz 6,28(1) - mtcrf 0xFF,0 - lwz 5,24(1) - lwz 4,20(1) - lwz 3,16(1) - # ...unwind the stack frame, and jump to the PLT entry we updated. - addi 1,1,48 - bctr -0: - .size _dl_runtime_resolve,0b-_dl_runtime_resolve - # undo '.section text'. - .previous -"); +#ifdef RESOLVE -/* Initial entry point code for the dynamic linker. - The C function `_dl_start' is the real entry point; - its return value is the user program's entry point. */ -#define RTLD_START \ -static ElfW(Addr) _dl_start (void *arg) __attribute__((unused)); \ -asm ("\ - .section \".text\" - .align 2 - .globl _start - .type _start,@function -_start: - # We start with the following on the stack, from top: - # argc (4 bytes) - # arguments for program (terminated by NULL) - # environment variables (terminated by NULL) - # arguments for the program loader - # FIXME: perhaps this should do the same trick as elf/start.c? +/* 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. */ - # Call _dl_start with one parameter pointing at argc - mr 3,1 - # (we have to frob the stack pointer a bit to allow room for - # _dl_start to save the link register) - li 4,0 - addi 1,1,-16 - stw 4,0(1) - bl _dl_start@local +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); - # Now, we do our main work of calling initialisation procedures. - # The ELF ABI doesn't say anything about parameters for these, - # so we just pass argc, argv, and the environment. - # Changing these is strongly discouraged (not least because argc is - # passed by value!). + if (rinfo == R_PPC_NONE) + return; - # put our GOT pointer in r31 - bl _GLOBAL_OFFSET_TABLE_-4@local - mflr 31 - # the address of _start in r30 - mr 30,3 - # &_dl_argc in 29, &_dl_argv in 27, and _dl_default_scope in 28 - lwz 28,_dl_default_scope@got(31) - lwz 29,_dl_argc@got(31) - lwz 27,_dl_argv@got(31) -0: - # call initfunc = _dl_init_next(_dl_default_scope[2]) - lwz 3,8(28) - bl _dl_init_next@plt - # if initfunc is NULL, we exit the loop - mr. 0,3 - beq 1f - # call initfunc(_dl_argc, _dl_argv, _dl_argv+_dl_argc+1) - mtlr 0 - lwz 3,0(29) - lwz 4,0(27) - slwi 5,3,2 - add 5,4,5 - addi 5,5,4 - blrl - # and loop. - b 0b -1: - # Now, to conform to the ELF ABI, we have to: - # pass argv (actually _dl_argv) in r4 - lwz 4,0(27) - # pass argc (actually _dl_argc) in r3 - lwz 3,0(29) - # pass envp (actually _dl_argv+_dl_argc+1) in r5 - slwi 5,3,2 - add 5,4,5 - addi 5,5,4 - # pass the auxilary vector in r6. This is passed just after _envp. - addi 6,5,-4 -2: lwzu 0,4(6) - cmpwi 1,0,0 - bne 2b - addi 6,6,4 - # pass a termination function pointer (in this case _dl_fini) in r7 - lwz 7,_dl_fini@got(31) - # now, call the start function in r30... - mtctr 30 - # pass the stack pointer in r1 (so far so good), pointing to a NULL value - # (this lets our startup code distinguish between a program linked statically, - # which linux will call with argc on top of the stack which will hopefully - # never be zero, and a dynamically linked program which will always have - # a NULL on the top of the stack). - # Take the opportunity to clear LR, so anyone who accidentally returns - # from _start gets SEGV. - li 0,0 - stw 0,0(1) - mtlr 0 - # and also clear _dl_starting_up - lwz 26,_dl_starting_up@got(31) - stw 0,0(26) - # go do it! - bctr -0: - .size _start,0b-_start - # undo '.section text'. - .previous -"); + 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); + } -/* The idea here is that to conform to the ABI, we are supposed to try - to load dynamic objects between 0x10000 (we actually use 0x40000 as - the lower bound, to increase the chance of a memory reference from - a null pointer giving a segfault) and the program's load address. - Regrettably, in this code we can't find the program's load address, - so we punt and choose 0x01800000, which is below the ABI's - recommended default, and what GNU ld currently chooses. We only use - the address as a preference for mmap, so if we get it wrong the - worst that happens is that it gets mapped somewhere else. + /* 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; - FIXME: Unfortunately, 'somewhere else' is probably right after the - program's break, which causes malloc to fail. We really need more - information here about the way memory is mapped. */ + 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; -#define ELF_PREFERRED_ADDRESS_DATA \ -static ElfW(Addr) _dl_preferred_address = 1; + 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; -#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) \ -( { \ - ElfW(Addr) prefd; \ - if (mapstartpref != 0 && _dl_preferred_address == 1) \ - _dl_preferred_address = mapstartpref; \ - if (mapstartpref != 0) \ - prefd = mapstartpref; \ - else if (_dl_preferred_address == 1) \ - prefd = _dl_preferred_address = \ - (0x01800000 - maplength - 0x10000) & \ - ~(_dl_pagesize - 1); \ - else if (_dl_preferred_address < maplength + 0x50000) \ - prefd = 0; \ - else \ - prefd = _dl_preferred_address = \ - ((_dl_preferred_address - maplength - 0x10000) \ - & ~(_dl_pagesize - 1)); \ - prefd; \ -} ) + 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 -#define ELF_FIXED_ADDRESS(loader, mapstart) \ -( { \ - if (mapstart != 0 && _dl_preferred_address == 1) \ - _dl_preferred_address = mapstart; \ -} ) -#define ELF_FIXUP_RETURNS_ADDRESS 1 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 + +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 + +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 + +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 + +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 + +/* 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 + +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 , 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 + +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 , 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 + +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 - -#undef ffs - -#ifdef __GNUC__ +#include 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 -#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 + +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 + +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 + +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 + +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 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 -- cgit v1.2.3