diff options
Diffstat (limited to 'sysdeps')
59 files changed, 1723 insertions, 589 deletions
diff --git a/sysdeps/generic/rpc/auth.h b/sysdeps/generic/rpc/auth.h index 61cd351..532c4d2 100644 --- a/sysdeps/generic/rpc/auth.h +++ b/sysdeps/generic/rpc/auth.h @@ -42,6 +42,8 @@ #define _RPC_AUTH_H 1 #include <features.h> +#include <sys/types.h> +#include <rpc/types.h> #include <rpc/xdr.h> __BEGIN_DECLS @@ -99,7 +101,7 @@ struct AUTH { struct auth_ops { void (*ah_nextverf) __P ((AUTH *)); int (*ah_marshal) __P ((AUTH *, XDR *)); /* nextverf & serialize */ - int (*ah_validate) __P ((AUTH *, struct opaque_auth *)); + int (*ah_validate) __P ((AUTH *, struct opaque_auth *)); /* validate verifier */ int (*ah_refresh) __P ((AUTH *)); /* refresh credentials */ void (*ah_destroy) __P ((AUTH *)); /* destroy this structure */ @@ -163,7 +165,7 @@ extern AUTH *authunix_create __P ((char *__machname, __uid_t __uid, __gid_t *__aup_gids)); extern AUTH *authunix_create_default __P ((void)); extern AUTH *authnone_create __P ((void)); -extern AUTH *authdes_create __P ((char *__servername, u_int __window, +extern AUTH *authdes_create __P ((char *__servername, u_int __window, struct sockaddr *__syncaddr, des_block *__ckey)); diff --git a/sysdeps/i386/fpu/__math.h b/sysdeps/i386/fpu/__math.h index d79fe7d..7758fe8 100644 --- a/sysdeps/i386/fpu/__math.h +++ b/sysdeps/i386/fpu/__math.h @@ -460,7 +460,7 @@ __finite (double __x) { register int __result; __asm__ __volatile__ - ("orl $x0x800fffff, %0\n\t" + ("orl $0x800fffff, %0\n\t" "incl %0\n\t" "shrl $31, %0" : "=q" (__result) : "0" (((int *) &__x)[1])); diff --git a/sysdeps/mach/hurd/setitimer.c b/sysdeps/mach/hurd/setitimer.c index 6cad6ea..b0e70e8 100644 --- a/sysdeps/mach/hurd/setitimer.c +++ b/sysdeps/mach/hurd/setitimer.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. +/* Copyright (C) 1994, 1995, 1996, 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 @@ -16,7 +16,6 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <ansidecl.h> #include <stddef.h> #include <errno.h> #include <sys/time.h> @@ -310,9 +309,8 @@ setitimer_locked (const struct itimerval *new, struct itimerval *old, set *OLD to the old value of timer WHICH. Returns 0 on success, -1 on errors. */ int -DEFUN(__setitimer, (which, new, old), - enum __itimer_which which AND - struct itimerval *new AND struct itimerval *old) +__setitimer (enum __itimer_which which, const struct itimerval *new, + struct itimerval *old) { void *crit; diff --git a/sysdeps/powerpc/Dist b/sysdeps/powerpc/Dist new file mode 100644 index 0000000..ba908dc --- /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 0000000..4100901 --- /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 da621e2..02292a0 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 9dc19a9..db9688c 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 a9aefcc..ffd90d5 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 1a63006..f02d781 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 3ad5ca8..cfada93 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 0000000..1e66140 --- /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 0000000..de778fa --- /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 0000000..05395f0 --- /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 0000000..a75adbf --- /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 0000000..fa35fbc --- /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 0000000..45d61e1 --- /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 0000000..867ea5f --- /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 0000000..136a835 --- /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 0000000..0afd6ce --- /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 0000000..b3a3f95 --- /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 d9d7f26..1e65bea 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 0000000..d6bd58d --- /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 b31e0ee..d21987f 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 0000000..aa8f1fc --- /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 0000000..4279b74 --- /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 0000000..52733f7 --- /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 0000000..2cecb6f --- /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 755ef65..af10581 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 eb6a88e..fa1c670 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 diff --git a/sysdeps/rs6000/ffs.c b/sysdeps/rs6000/ffs.c index 44e7a43..598c15c 100644 --- a/sysdeps/rs6000/ffs.c +++ b/sysdeps/rs6000/ffs.c @@ -19,7 +19,7 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> -#include <bstring.h> +#include <string.h> #undef ffs diff --git a/sysdeps/sparc/setjmp.S b/sysdeps/sparc/setjmp.S index 9e93668..84c6354 100644 --- a/sysdeps/sparc/setjmp.S +++ b/sysdeps/sparc/setjmp.S @@ -25,6 +25,7 @@ ENTRY (__sigsetjmp) /* Save our SP and FP; in the delay slot of the jump, save our return PC. Save the signal mask if requested with a tail-call for simplicity; it always returns zero. */ + ta ST_FLUSH_WINDOWS #ifdef PIC mov %o7,%g1 2: diff --git a/sysdeps/standalone/arm/errnos.h b/sysdeps/standalone/arm/errnos.h new file mode 100644 index 0000000..0b635e6 --- /dev/null +++ b/sysdeps/standalone/arm/errnos.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1991, 1994, 1996, 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* This file defines the `errno' constants for standalone ARM machines. + These constants are essentially arbitrary. */ + +#if !defined(__Emath_defined) && (defined(_ERRNO_H) || defined(__need_Emath)) +#undef __need_Emath +#define __Emath_defined 1 + +#define EDOM 1 +#define ERANGE 2 +#endif + +#ifdef _ERRNO_H +#define ENOSYS 3 +#define EINVAL 4 +#define ESPIPE 5 +#define EBADF 6 +#define ENOMEM 7 +#define EACCES 8 +#define ENFILE 9 +#define EMFILE 10 +#define ENAMETOOLONG 11 /* File name too long */ +#define ELOOP 12 /* Too many symbolic links encountered */ +#define ENOMSG 13 /* No message of desired type */ +#define E2BIG 14 /* Arg list too long */ +#define EINTR 15 +#define EILSEQ 16 +#define ENOEXEC 17 +#define ENOENT 18 +#endif + +#define __set_errno(val) errno = (val) diff --git a/sysdeps/standalone/dirstream.h b/sysdeps/standalone/dirstream.h index 20c4922..0645132 100644 --- a/sysdeps/standalone/dirstream.h +++ b/sysdeps/standalone/dirstream.h @@ -28,7 +28,7 @@ Cambridge, MA 02139, USA. */ The miscellaneous Unix `readdir' implementations read directory data into a buffer and fill in a `struct dirent' copy in the `DIR' object. */ -typedef struct +struct __dirstream { int __fd; /* File descriptor. */ @@ -38,6 +38,6 @@ typedef struct size_t __size; /* Total valid data in the block. */ struct dirent __entry; /* Returned by `readdir'. */ - } DIR; + }; #endif /* dirstream.h */ diff --git a/sysdeps/stub/direntry.h b/sysdeps/stub/direntry.h index f84425b..4b22f31 100644 --- a/sysdeps/stub/direntry.h +++ b/sysdeps/stub/direntry.h @@ -20,4 +20,4 @@ struct dirent { char d_name[1]; /* Variable length. */ - } + }; diff --git a/sysdeps/stub/dirfd.c b/sysdeps/stub/dirfd.c index ce40a28..767bc21 100644 --- a/sysdeps/stub/dirfd.c +++ b/sysdeps/stub/dirfd.c @@ -23,7 +23,7 @@ int dirfd (dirp) - FILE *dirp; + DIR *dirp; { __set_errno (ENOSYS); return -1; diff --git a/sysdeps/stub/if_index.c b/sysdeps/stub/if_index.c new file mode 100644 index 0000000..f1cb0c5 --- /dev/null +++ b/sysdeps/stub/if_index.c @@ -0,0 +1,36 @@ +/* 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +unsigned int if_nametoindex(const char *ifname) +{ + return 0; +} + +char *if_indextoname(unsigned int ifindex, char *ifname) +{ + return NULL; +} + +void if_freenameindex(struct if_nameindex *ifn) +{ +} + +struct if_nameindex *if_nameindex(void) +{ + return NULL; +} diff --git a/sysdeps/stub/seekdir.c b/sysdeps/stub/seekdir.c index fe40c8b..514b59d 100644 --- a/sysdeps/stub/seekdir.c +++ b/sysdeps/stub/seekdir.c @@ -24,7 +24,7 @@ Cambridge, MA 02139, USA. */ /* Seek to position POS in DIRP. */ void seekdir (dirp, pos) - DIR *dirp + DIR *dirp; off_t pos; { if (dirp == NULL) diff --git a/sysdeps/stub/setitimer.c b/sysdeps/stub/setitimer.c index 737257f..21af517 100644 --- a/sysdeps/stub/setitimer.c +++ b/sysdeps/stub/setitimer.c @@ -1,20 +1,20 @@ -/* Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. -This file is part of the GNU C Library. +/* Copyright (C) 1991, 1994, 1995, 1996, 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 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. + 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., 675 Mass Ave, -Cambridge, MA 02139, USA. */ + 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 <stddef.h> #include <errno.h> @@ -26,7 +26,7 @@ Cambridge, MA 02139, USA. */ int __setitimer (which, new, old) enum __itimer_which which; - struct itimerval *new; + const struct itimerval *new; struct itimerval *old; { if (new == NULL) diff --git a/sysdeps/stub/sigaction.c b/sysdeps/stub/sigaction.c index 1344d45..523daec 100644 --- a/sysdeps/stub/sigaction.c +++ b/sysdeps/stub/sigaction.c @@ -26,7 +26,7 @@ int __sigaction (sig, act, oact) int sig; const struct sigaction *act; - struct sigaction *OACT; + struct sigaction *oact; { if (sig <= 0 || sig >= NSIG) { diff --git a/sysdeps/stub/sys/param.h b/sysdeps/stub/sys/param.h index 8a3e73b..b1ea52a 100644 --- a/sysdeps/stub/sys/param.h +++ b/sysdeps/stub/sys/param.h @@ -6,3 +6,5 @@ the installed headers on the system. */ #include <limits.h> + +#define MAXSYMLINKS 1 diff --git a/sysdeps/stub/sysconf.c b/sysdeps/stub/sysconf.c index 00480fb..3d3c0e9 100644 --- a/sysdeps/stub/sysconf.c +++ b/sysdeps/stub/sysconf.c @@ -164,10 +164,10 @@ __sysconf (name) case _SC_SEMAPHORES: case _SC_SHARED_MEMORY_OBJECTS: - case _SC_AIO_LIST_MAX: + case _SC_AIO_LISTIO_MAX: case _SC_AIO_MAX: case _SC_AIO_PRIO_DELTA_MAX: - case _SC_DELAYTIME_MAX: + case _SC_DELAYTIMER_MAX: case _SC_MQ_OPEN_MAX: case _SC_MQ_PRIO_MAX: case _SC_VERSION: diff --git a/sysdeps/stub/tempname.c b/sysdeps/stub/tempname.c index 984d4be..b93b948 100644 --- a/sysdeps/stub/tempname.c +++ b/sysdeps/stub/tempname.c @@ -26,7 +26,7 @@ Return the generated filename or NULL if one could not be generated, putting the length of the string in *LENPTR. */ char * -__stdio_gen_tempname (buf, bufsize, dir, pfx, dir_search, lenptr) +__stdio_gen_tempname (buf, bufsize, dir, pfx, dir_search, lenptr, streamptr) char *buf; size_t bufsize; const char *dir; diff --git a/sysdeps/stub/vdprintf.c b/sysdeps/stub/vdprintf.c index f7ae121..88c855e 100644 --- a/sysdeps/stub/vdprintf.c +++ b/sysdeps/stub/vdprintf.c @@ -18,6 +18,7 @@ Cambridge, MA 02139, USA. */ #include <errno.h> #include <stdio.h> +#include <stdarg.h> /* Write formatted output to file descriptor D according to the format string FORMAT, using the argument list in ARG. */ @@ -25,38 +26,7 @@ int vdprintf (int d, const char *format, va_list arg) { __set_errno (ENOSYS); - return NULL; -} - -stub_warning (vdprintf) -/* 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., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -#include <errno.h> -#include <stdio.h> - -/* Write formatted output to file descriptor D according to the format string - FORMAT, using the argument list in ARG. */ -int -vdprintf (int d, const char *format, va_list arg) -{ - __set_errno (ENOSYS); - return NULL; + return 0; } stub_warning (vdprintf) diff --git a/sysdeps/unix/arm/fork.S b/sysdeps/unix/arm/fork.S new file mode 100644 index 0000000..baa33e3 --- /dev/null +++ b/sysdeps/unix/arm/fork.S @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 1992, 1994, 1995, 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <sysdep.h> + +/* ARM version. */ + +SYSCALL__ (fork, 0) + /* R1 is now 0 for the parent and 1 for the child. Decrement it to + make it -1 (all bits set) for the parent, and 0 (no bits set) + for the child. Then AND it with R0, so the parent gets + R0&-1==R0, and the child gets R0&0==0. */ + sub r1, r1, $1 + and r0, r0, r1 + RETINSTR(mov, pc, r14) +PSEUDO_END(fork) + +weak_alias (__fork, fork) diff --git a/sysdeps/unix/arm/sysdep.h b/sysdeps/unix/arm/sysdep.h index 18e812b..1c58073 100644 --- a/sysdeps/unix/arm/sysdep.h +++ b/sysdeps/unix/arm/sysdep.h @@ -19,3 +19,8 @@ Cambridge, MA 02139, USA. */ #include <sysdeps/unix/sysdep.h> #include <sysdeps/arm/sysdep.h> +/* Some definitions to allow the assembler in sysdeps/unix/*.S to build + without needing ARM-specific versions of all the files. */ + +#define ret RETINSTR(mov, pc, r14) +#define MOVE(a,b) mov b,a diff --git a/sysdeps/unix/sysv/linux/arm/clone.S b/sysdeps/unix/sysv/linux/arm/clone.S new file mode 100644 index 0000000..c7e7aed --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/clone.S @@ -0,0 +1,33 @@ +/* Copyright (C) 1996, 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. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <errnos.h> + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .text +ENTRY(__clone) + /* Somebody needs to write this. */ +PSEUDO_END (__clone) + +weak_alias (__clone, clone) diff --git a/sysdeps/unix/sysv/linux/arm/socket.S b/sysdeps/unix/sysv/linux/arm/socket.S new file mode 100644 index 0000000..e8db072 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/socket.S @@ -0,0 +1,49 @@ +/* Copyright (C) 1995, 1996, 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> +#include <sys/socketcall.h> + +#define P(a, b) P2(a, b) +#define P2(a, b) a##b + + .text +/* The socket-oriented system calls are handled unusally in Linux. + They are all gated through the single `socketcall' system call number. + `socketcall' takes two arguments: the first is the subcode, specifying + which socket function is being called; and the second is a pointer to + the arguments to the specific function. + + The .S files for the other calls just #define socket and #include this. */ + +.globl P(__,socket) +ENTRY (P(__,socket)) + + /* Do the system call trap. */ + swi SYS_ify(socketcall) + + /* %eax is < 0 if there was an error. */ + cmn r0, $124 + bge syscall_error + + /* Successful; return the syscall's value. */ + RETINSTR(mov,pc,r14) + +PSEUDO_END (P(__,socket)) + +weak_alias (P(__,socket), socket) diff --git a/sysdeps/unix/sysv/linux/arm/syscall.S b/sysdeps/unix/sysv/linux/arm/syscall.S new file mode 100644 index 0000000..7a87278 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/syscall.S @@ -0,0 +1,47 @@ +/* Copyright (C) 1995, 1996 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> + +/* Please consult the file sysdeps/unix/sysv/linux/arm/sysdep.h for + more information about the value -4095 used below.*/ + + .text +ENTRY (syscall) + + /* Normally encoding the system call number in the instruction is + good. But we pay the price here. */ + + sub sp, sp, $0xc @ get 3 words on the stack + orr r0, r0, $0xef000000 @ make up a SWI instruction + orr r0, r0, $SWI_BASE + str r0, [sp] + ldr r0, _reti + str r0, [sp, $4] + adr r0, _ret + str r0, [sp, $8] + mov r0, r1 + mov r1, r2 + mov r2, r3 + mov pc, sp +_ret: add sp, sp, $0xc + RETINSTR(mov, pc, r14) + +_reti: .word 0xe51ff004 @ ldr pc, [pc, $4] + +PSEUDO_END (syscall) diff --git a/sysdeps/unix/sysv/linux/arm/sysdep.h b/sysdeps/unix/sysv/linux/arm/sysdep.h new file mode 100644 index 0000000..6478a5d --- /dev/null +++ b/sysdeps/unix/sysv/linux/arm/sysdep.h @@ -0,0 +1,73 @@ +/* Copyright (C) 1992, 93, 95, 96, 97 Free Software Foundation, Inc. +This file is part of the GNU C Library. +Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995. +ARM changes by Philip Blundell, <pjb27@cam.ac.uk>, May 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _LINUX_ARM_SYSDEP_H +#define _LINUX_ARM_SYSDEP_H 1 + +/* There is some commonality. */ +#include <sysdeps/unix/arm/sysdep.h> + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#define SWI_BASE (9 << 20) +#define SYS_ify(syscall_name) (SWI_BASE + __NR_##syscall_name) + + +#ifdef ASSEMBLER + +/* Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the `lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in %eax + is a real error number. Linus said he will make sure the no syscall + returns a value in -1 .. -4095 as a valid result so we can savely + test with -4095. */ +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (args, syscall_name); \ + cmn r0, $4096; \ + bge syscall_error; + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + SYSCALL_ERROR_HANDLER \ + END (name) + +#ifndef PIC +#define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +#else +#error Aiee +#endif /* PIC */ + +#undef DO_CALL +#define DO_CALL(args, syscall_name) \ + swi SYS_ify (syscall_name); + +#endif /* ASSEMBLER */ + +#endif /* linux/arm/sysdep.h */ diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c new file mode 100644 index 0000000..3f5a890 --- /dev/null +++ b/sysdeps/unix/sysv/linux/if_index.c @@ -0,0 +1,140 @@ +/* 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <net/if.h> + +#define IF_INET6_FILENAME "/proc/net/if_inet6" + +/* /proc/net/if_inet6 contains lines that look like this: + * + * fe8000000000000000000000836fc168 0b 00 20 80 sit7 + * + * | | | | | | + * address --' | | | | | + * index --------' | | | | + * prefix length ---' | | | + * scope --------------' | | + * flags -----------------' | + * name -------------------------' + * + */ + +static int get_one_interface(FILE *fd, char *interface, int iflen, unsigned int *index) +{ + char buffer[80]; + static char seps[] = " \012"; + char *c = buffer; + char *sp; + if (!fgets(buffer, 80, fd)) + return 1; + if (strtok_r(buffer, seps, &sp) == NULL) return 1; + if (c = strtok_r(NULL, seps, &sp), c == NULL) return 1; + *index = strtoul(c, NULL, 16); + if (strtok_r(NULL, seps, &sp) == NULL) return 1; + if (strtok_r(NULL, seps, &sp) == NULL) return 1; + if (strtok_r(NULL, seps, &sp) == NULL) return 1; + if (c = strtok_r(NULL, seps, &sp), c == NULL) return 1; + strncpy(interface, c, iflen); + return 0; +} + +unsigned int if_nametoindex(const char *ifname) +{ + FILE *fd = fopen(IF_INET6_FILENAME, "r"); + char this_ifname[IFNAMSIZ]; + unsigned int this_index; + if (!fd) return 0; + while (get_one_interface(fd, this_ifname, IFNAMSIZ, &this_index) == 0) { + if (!strcmp(this_ifname, ifname)) { + fclose(fd); + return this_index; + } + } + fclose(fd); + return 0; +} + +char *if_indextoname(unsigned int ifindex, char *ifname) +{ + FILE *fd = fopen(IF_INET6_FILENAME, "r"); + unsigned int this_index; + if (!fd) return NULL; + while (get_one_interface(fd, ifname, IFNAMSIZ, &this_index) == 0) { + if (this_index == ifindex) { + fclose(fd); + return ifname; + } + } + fclose(fd); + return NULL; +} + +void if_freenameindex(struct if_nameindex *ifn) +{ + struct if_nameindex *ptr = ifn; + while (ptr->if_name || ptr->if_index) + { + if (ptr->if_name) + free(ptr->if_name); + ptr++; + } + free(ifn); +} + +struct if_nameindex *if_nameindex(void) +{ + FILE *fd = fopen(IF_INET6_FILENAME, "r"); + struct if_nameindex *ifn = NULL; + int nifs = 0; + if (!fd) return NULL; + do + { + struct if_nameindex *newifn; + nifs++; + newifn = realloc(ifn, nifs*sizeof(struct if_nameindex)); + if (!newifn) + { + /* We ran out of memory. */ + if (--nifs) + { + free(ifn[nifs-1].if_name); + ifn[nifs-1].if_name = 0; + ifn[nifs-1].if_index = 0; + if_freenameindex(ifn); + } + return NULL; + } + ifn = newifn; + ifn[nifs-1].if_index = 0; + ifn[nifs-1].if_name = malloc(IFNAMSIZ); + if (ifn[nifs-1].if_name == NULL) + { + if_freenameindex(ifn); + return NULL; + } + } + while (get_one_interface(fd, ifn[nifs-1].if_name, IFNAMSIZ, + &ifn[nifs-1].if_index) == 0); + free(ifn[nifs-1].if_name); + ifn[nifs-1].if_name = NULL; + fclose(fd); + return ifn; +} diff --git a/sysdeps/unix/sysv/linux/m68k/syscalls.list b/sysdeps/unix/sysv/linux/m68k/syscalls.list index 9a3e4d0..473c2ec 100644 --- a/sysdeps/unix/sysv/linux/m68k/syscalls.list +++ b/sysdeps/unix/sysv/linux/m68k/syscalls.list @@ -1,5 +1,7 @@ # File name Caller Syscall name # args Strong name Weak names +cacheflush EXTRA cacheflush 4 __cacheflush cacheflush + s_getgroups getgroups getgroups 2 __syscall_getgroups s_llseek llseek _llseek 5 __sys_llseek s_setgroups setgroups setgroups 2 __syscall_setgroups diff --git a/sysdeps/unix/sysv/linux/net/if.h b/sysdeps/unix/sysv/linux/net/if.h index db86d20..01e9f00 100644 --- a/sysdeps/unix/sysv/linux/net/if.h +++ b/sysdeps/unix/sysv/linux/net/if.h @@ -144,4 +144,23 @@ struct ifconf #define ifc_buf ifc_ifcu.ifcu_buf /* Buffer address. */ #define ifc_req ifc_ifcu.ifcu_req /* Array of structures. */ + +/* Convert an interface name to an index, and vice versa. */ + +unsigned int if_nametoindex(const char *ifname); +char *if_indextoname(unsigned int ifindex, char *ifname); + +/* Return a list of all interfaces and their indices. */ + +struct if_nameindex { + unsigned int if_index; /* 1, 2, ... */ + char *if_name; /* null terminated name: "eth0", ... */ +}; + +struct if_nameindex *if_nameindex(void); + +/* Free the data returned from if_nameindex. */ + +void if_freenameindex(struct if_nameindex *ptr); + #endif /* net/if.h */ diff --git a/sysdeps/unix/sysv/linux/netinet/in.h b/sysdeps/unix/sysv/linux/netinet/in.h index bbc6254..451f8f5 100644 --- a/sysdeps/unix/sysv/linux/netinet/in.h +++ b/sysdeps/unix/sysv/linux/netinet/in.h @@ -259,7 +259,7 @@ extern u_int16_t htons __P ((u_int16_t __hostshort)); /* IPV6 socket options. */ #define IPV6_ADDRFORM 1 -#define IPV6_RXINFO 2 +#define IPV6_PKTINFO 2 #define IPV6_RXHOPOPTS 3 #define IPV6_RXDSTOPTS 4 #define IPV6_RXSRCRT 5 @@ -267,8 +267,6 @@ extern u_int16_t htons __P ((u_int16_t __hostshort)); #define IPV6_CHECKSUM 7 #define IPV6_HOPLIMIT 8 -#define IPV6_TXINFO IPV6_RXINFO -#define SCM_SRCINFO IPV6_TXINFO #define SCM_SRCRT IPV6_RXSRCRT #define IPV6_UNICAST_HOPS 16 @@ -306,6 +304,14 @@ extern u_int16_t htons __P ((u_int16_t __hostshort)); /* Bind socket to a priviledged IP port. */ extern int bindresvport __P ((int __sockfd, struct sockaddr_in *__sin)); + +/* IPv6 packet information. */ +struct in6_pktinfo + { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + int ipi6_ifindex; /* send/recv interface index */ + }; + __END_DECLS #endif /* netinet/in.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/clone.S b/sysdeps/unix/sysv/linux/powerpc/clone.S index d255abf..068b14c 100644 --- a/sysdeps/unix/sysv/linux/powerpc/clone.S +++ b/sysdeps/unix/sysv/linux/powerpc/clone.S @@ -29,45 +29,45 @@ ENTRY(__clone) /* Set up stack frame, save registers. */ - stwu 1,-32(1) - stw 31,16(1) - stw 30,20(1) + stwu %r1,-32(%r1) + stw %r31,16(%r1) + stw %r30,20(%r1) /* Check for child_stack == NULL || fn == NULL. */ - cmpwi 0,4,0 - cmpwi 1,3,0 - cror 2+0*4,2+0*4,2+1*4 - beq- 0,badargs + cmpwi %cr0,%r4,0 + beq- %cr0,badargs + cmpwi %cr1,%r3,0 + beq- %cr1,badargs /* Set up stack frame for child. */ - addi 4,4,-16 - clrrwi 4,4,4 - li 0,0 - stw 0,0(4) + addi %r4,%r4,-16 + clrrwi %r4,%r4,4 + li %r0,0 + stw %r0,0(%r4) /* Save new stack, fn, args across syscall. */ - mr 30,3 /* Function in r30. */ - mr 31,6 /* Arguments in r31. */ + mr %r30,%r3 /* Function in r30. */ + mr %r31,%r6 /* Arguments in r31. */ /* 'flags' argument is first parameter to clone syscall. (The other argument is the stack pointer, already in r4.) */ - mr 3,5 + mr %r3,%r5 /* Do the call. */ DO_CALL(SYS_ify(clone)) - bso- error - beq child + bso- error + beq child /* Parent. Restore registers & return. */ - lwz 31,16(1) - lwz 30,20(1) - addi 1,1,32 + lwz %r31,16(%r1) + lwz %r30,20(%r1) + addi %r1,%r1,32 blr child: /* Call procedure. */ - mtlr 30 - mr 3,31 + mtlr %r30 + mr %r3,%r31 blrl /* Call _exit with result from procedure. */ #ifdef PIC diff --git a/sysdeps/unix/sysv/linux/powerpc/socket.S b/sysdeps/unix/sysv/linux/powerpc/socket.S index 12417fa..305aba9 100644 --- a/sysdeps/unix/sysv/linux/powerpc/socket.S +++ b/sysdeps/unix/sysv/linux/powerpc/socket.S @@ -43,38 +43,38 @@ .text ENTRY(P(__,socket)) - stwu 1,-48(1) + stwu %r1,-48(%r1) #if NARGS >= 1 - stw 3,stackblock(1) + stw %r3,stackblock(%r1) #endif #if NARGS >= 2 - stw 4,4+stackblock(1) + stw %r4,4+stackblock(%r1) #endif #if NARGS >= 3 - stw 5,8+stackblock(1) + stw %r5,8+stackblock(%r1) #endif #if NARGS >= 4 - stw 6,12+stackblock(1) + stw %r6,12+stackblock(%r1) #endif #if NARGS >= 5 - stw 7,16+stackblock(1) + stw %r7,16+stackblock(%r1) #endif #if NARGS >= 6 - stw 8,20+stackblock(1) + stw %r8,20+stackblock(%r1) #endif #if NARGS >= 7 - stw 9,24+stackblock(1) + stw %r9,24+stackblock(%r1) #endif #if NARGS >= 8 - stw 10,28+stackblock(1) + stw %r10,28+stackblock(%r1) #endif #if NARGS >= 9 #error too many arguments! #endif - li 3,P(SOCKOP_,socket) - addi 4,1,stackblock + li %r3,P(SOCKOP_,socket) + addi %r4,%r1,stackblock DO_CALL(SYS_ify(socketcall)) - addi 1,1,48 + addi %r1,%r1,48 bnslr #ifdef PIC b __syscall_error@plt diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S index 441dd5d..2cb5482 100644 --- a/sysdeps/unix/sysv/linux/powerpc/syscall.S +++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S @@ -20,12 +20,12 @@ .text ENTRY (syscall) - mr 0,3 - mr 3,4 - mr 4,5 - mr 5,6 - mr 6,7 - mr 7,8 + mr %r0,%r3 + mr %r3,%r4 + mr %r4,%r5 + mr %r5,%r6 + mr %r6,%r7 + mr %r7,%r8 sc bnslr #ifdef PIC diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/sysdep.h index 6cad9ae..577809a 100644 --- a/sysdeps/unix/sysv/linux/powerpc/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.h @@ -50,7 +50,7 @@ b __syscall_error@plt #else #define PSEUDO(name, syscall_name, args) \ - .text; \ + .section ".text"; \ ENTRY (name) \ DO_CALL (SYS_ify (syscall_name)); \ bnslr; \ diff --git a/sysdeps/unix/sysv/linux/shmdt.c b/sysdeps/unix/sysv/linux/shmdt.c index dcda701..70526e6 100644 --- a/sysdeps/unix/sysv/linux/shmdt.c +++ b/sysdeps/unix/sysv/linux/shmdt.c @@ -26,5 +26,5 @@ int shmdt (shmaddr) const void *shmaddr; { - return __ipc (IPCOP_shmdt, 0, 0, 0, shmaddr); + return __ipc (IPCOP_shmdt, 0, 0, 0, (void *) shmaddr); } diff --git a/sysdeps/unix/sysv/linux/statfsbuf.h b/sysdeps/unix/sysv/linux/statfsbuf.h index 1d1bbda..7e1aa55 100644 --- a/sysdeps/unix/sysv/linux/statfsbuf.h +++ b/sysdeps/unix/sysv/linux/statfsbuf.h @@ -19,6 +19,8 @@ #ifndef _STATFSBUF_H #define _STATFSBUF_H +#include <gnu/types.h> /* for __fsid_t */ + struct statfs { int f_type; |