diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-12-18 04:02:31 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-12-18 04:02:31 +0000 |
commit | 592f26a3ed6e74aad8ff65eec9c139a6bc4aa89e (patch) | |
tree | 3eabb471cd2153b059302d3dedc628241fbb9071 | |
parent | 4ae4facccf1286dae59ccc4758b64a76ab985aff (diff) | |
download | glibc-592f26a3ed6e74aad8ff65eec9c139a6bc4aa89e.zip glibc-592f26a3ed6e74aad8ff65eec9c139a6bc4aa89e.tar.gz glibc-592f26a3ed6e74aad8ff65eec9c139a6bc4aa89e.tar.bz2 |
Update.
2003-12-17 Carlos O'Donell <carlos@baldric.uwo.ca>
* sysdeps/hppa/fpu/fclrexcpt.c (feclearexcept): Right shift
FE_ALL_EXCEPT before complimenting.
* sysdeps/hppa/fpu/fegetenv.c (fegetenv): Use asm 'ma,' completer,
and gcc '+r' constraint.
* sysdeps/hppa/fpu/feholdexcpt.c (feholdexcept): Likewise.
* sysdeps/hppa/fpu/fesetenv.c (fesetenv): Likewise.
* sysdeps/hppa/fpu/feupdateenv.c (feupdateenv): Read raised
exception bits, OR with envp, pass to fesetenv.
* sysdeps/hppa/fpu/fraiseexcpt.c (feraiseexcept): Add delayed
exception flushing, FE_UNDERFLOW is DBL_MIN/3.0, FE_INEXACT is
triggered by M_PI/69.69 converted to single precision.
* sysdeps/hppa/fpu/fsetexcptflg.c (fesetexceptflag): Set enable
bits not raised exception bits.
* sysdeps/hppa/Makefile: Add dl-symaddr and dl-fptr to the
correct build strings.
* sysdeps/hppa/dl-fptr.h: New file.
* sysdeps/hppa/dl-fptr.c: Removed.
* sysdeps/hppa/dl-symaddr.c (_dl_symbol_address): Use _dl_make_ftpr,
remove const qualifier for map.
(_dl_function_address): Removed.
* sysdeps/hppa/dl-lookupcfg.h: DL_LOOKUP_ADDRESS must clear
PLABEL32 bits, define DL_AUTO_FUNCTION_ADDRESS and
DL_STATIC_FUNCTION_ADDRESS, DL_DT_INIT_ADDRESS and
DL_DT_FINI_ADDRESS use the previous two macros.
* misc/mntent_r.c: Change encoding to match recently changed decoder.
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | sysdeps/hppa/dl-fptr.c | 211 | ||||
-rw-r--r-- | sysdeps/hppa/dl-fptr.h | 35 | ||||
-rw-r--r-- | sysdeps/hppa/dl-lookupcfg.h | 33 | ||||
-rw-r--r-- | sysdeps/hppa/dl-symaddr.c | 17 | ||||
-rw-r--r-- | sysdeps/hppa/fpu/fclrexcpt.c | 2 | ||||
-rw-r--r-- | sysdeps/hppa/fpu/fegetenv.c | 10 | ||||
-rw-r--r-- | sysdeps/hppa/fpu/feholdexcpt.c | 34 | ||||
-rw-r--r-- | sysdeps/hppa/fpu/fesetenv.c | 31 | ||||
-rw-r--r-- | sysdeps/hppa/fpu/feupdateenv.c | 8 | ||||
-rw-r--r-- | sysdeps/hppa/fpu/fraiseexcpt.c | 63 | ||||
-rw-r--r-- | sysdeps/hppa/fpu/fsetexcptflg.c | 3 |
12 files changed, 171 insertions, 306 deletions
@@ -1,3 +1,31 @@ +2003-12-17 Carlos O'Donell <carlos@baldric.uwo.ca> + + * sysdeps/hppa/fpu/fclrexcpt.c (feclearexcept): Right shift + FE_ALL_EXCEPT before complimenting. + * sysdeps/hppa/fpu/fegetenv.c (fegetenv): Use asm 'ma,' completer, + and gcc '+r' constraint. + * sysdeps/hppa/fpu/feholdexcpt.c (feholdexcept): Likewise. + * sysdeps/hppa/fpu/fesetenv.c (fesetenv): Likewise. + * sysdeps/hppa/fpu/feupdateenv.c (feupdateenv): Read raised + exception bits, OR with envp, pass to fesetenv. + * sysdeps/hppa/fpu/fraiseexcpt.c (feraiseexcept): Add delayed + exception flushing, FE_UNDERFLOW is DBL_MIN/3.0, FE_INEXACT is + triggered by M_PI/69.69 converted to single precision. + * sysdeps/hppa/fpu/fsetexcptflg.c (fesetexceptflag): Set enable + bits not raised exception bits. + + * sysdeps/hppa/Makefile: Add dl-symaddr and dl-fptr to the + correct build strings. + * sysdeps/hppa/dl-fptr.h: New file. + * sysdeps/hppa/dl-fptr.c: Removed. + * sysdeps/hppa/dl-symaddr.c (_dl_symbol_address): Use _dl_make_ftpr, + remove const qualifier for map. + (_dl_function_address): Removed. + * sysdeps/hppa/dl-lookupcfg.h: DL_LOOKUP_ADDRESS must clear + PLABEL32 bits, define DL_AUTO_FUNCTION_ADDRESS and + DL_STATIC_FUNCTION_ADDRESS, DL_DT_INIT_ADDRESS and + DL_DT_FINI_ADDRESS use the previous two macros. + 2003-12-17 Jakub Jelinek <jakub@redhat.com> * malloc/mtrace.c (tr_old_memalign_hook): New variable. @@ -9,7 +37,7 @@ 2003-12-17 Ulrich Drepper <drepper@redhat.com> - * misc/mntent_r.c: Change encoding to match recently change decoder. + * misc/mntent_r.c: Change encoding to match recently changed decoder. Patch by Alexander Achenbach <xela@slit.de>. 2003-12-16 Steven Munroe <sjmunroe@us.ibm.com> diff --git a/sysdeps/hppa/dl-fptr.c b/sysdeps/hppa/dl-fptr.c deleted file mode 100644 index f8b6424..0000000 --- a/sysdeps/hppa/dl-fptr.c +++ /dev/null @@ -1,211 +0,0 @@ -/* Make dynamic PLABELs for function pointers. HPPA version. - Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <unistd.h> -#include <string.h> -#include <sys/param.h> -#include <sys/mman.h> -#include <link.h> -#include <errno.h> -#include <ldsodefs.h> -#include <elf/dynamic-link.h> -#include <dl-machine.h> -#ifdef _LIBC_REENTRANT -# include <pt-machine.h> - -/* Remember, we use 0 to mean that a lock is taken on PA-RISC. */ -static int __hppa_fptr_lock = 1; -#endif - -/* Because ld.so is now versioned, these functions can be in their own - file; no relocations need to be done to call them. Of course, if - ld.so is not versioned... */ -#if 0 -#ifndef DO_VERSIONING -# error "This will not work with versioning turned off, sorry." -#endif -#endif - -#ifdef MAP_ANON -/* The fd is not examined when using MAP_ANON. */ -# define ANONFD -1 -#else -# define ANONFD GL(dl_zerofd) -#endif - -struct hppa_fptr __boot_ldso_fptr[HPPA_BOOT_FPTR_SIZE]; -struct hppa_fptr *__fptr_root = NULL; -struct hppa_fptr *__fptr_next = __boot_ldso_fptr; -static struct hppa_fptr *__fptr_free = NULL; -int __fptr_count = HPPA_BOOT_FPTR_SIZE; - -Elf32_Addr -__hppa_make_fptr (const struct link_map *sym_map, Elf32_Addr value, - struct hppa_fptr **root, struct hppa_fptr *mem) -{ - struct hppa_fptr **loc; - struct hppa_fptr *f; - -#ifdef _LIBC_REENTRANT - /* Make sure we are alone. We don't need a lock during bootstrap. */ - if (mem == NULL) - while (testandset (&__hppa_fptr_lock)); -#endif - - /* Search the sorted linked list for an existing entry for this - symbol. */ - loc = root; - f = *loc; - while (f != NULL && f->func <= value) - { - if (f->func == value) - goto found; - loc = &f->next; - f = *loc; - } - - /* Not found. Create a new one. */ - if (mem != NULL) - f = mem; - else if (__fptr_free != NULL) - { - f = __fptr_free; - __fptr_free = f->next; - } - else - { - if (__fptr_count == 0) - { -#ifndef MAP_ANON -# define MAP_ANON 0 - if (GL(dl_zerofd) == -1) - { - GL(dl_zerofd) = _dl_sysdep_open_zero_fill (); - if (GL(dl_zerofd) == -1) - { - __close (fd); - _dl_signal_error (errno, NULL, NULL, - "cannot open zero fill device"); - } - } -#endif - - __fptr_next = __mmap (0, GL(dl_pagesize), PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, ANONFD, 0); - if (__fptr_next == MAP_FAILED) - _dl_signal_error(errno, NULL, NULL, "cannot map page for fptr"); - __fptr_count = GL(dl_pagesize) / sizeof (struct hppa_fptr); - } - f = __fptr_next++; - __fptr_count--; - } - - f->func = value; - /* GOT has already been relocated in elf_get_dynamic_info - don't - try to relocate it again. */ - f->gp = sym_map->l_info[DT_PLTGOT]->d_un.d_ptr; - f->next = *loc; - *loc = f; - -found: -#ifdef _LIBC_REENTRANT - /* Release the lock. Again, remember, zero means the lock is taken! */ - if (mem == NULL) - __hppa_fptr_lock = 1; -#endif - - /* Set bit 30 to indicate to $$dyncall that this is a PLABEL. */ - return (Elf32_Addr) f | 2; -} - -void -_dl_unmap (struct link_map *map) -{ - struct hppa_fptr **floc; - struct hppa_fptr *f; - struct hppa_fptr **lloc; - struct hppa_fptr *l; - - __munmap ((void *) map->l_map_start, map->l_map_end - map->l_map_start); - -#ifdef _LIBC_REENTRANT - /* Make sure we are alone. */ - while (testandset (&__hppa_fptr_lock)); -#endif - - /* Search the sorted linked list for the first entry for this object. */ - floc = &__fptr_root; - f = *floc; - while (f != NULL && f->func < map->l_map_start) - { - floc = &f->next; - f = *floc; - } - - /* We found one. */ - if (f != NULL && f->func < map->l_map_end) - { - /* Get the last entry. */ - lloc = floc; - l = f; - while (l && l->func < map->l_map_end) - { - lloc = &l->next; - l = *lloc; - } - - /* Updated FPTR. */ - *floc = l; - - /* Prepend them to the free list. */ - *lloc = __fptr_free; - __fptr_free = f; - } - -#ifdef _LIBC_REENTRANT - /* Release the lock. */ - __hppa_fptr_lock = 1; -#endif -} - -Elf32_Addr -_dl_lookup_address (const void *address) -{ - Elf32_Addr addr = (Elf32_Addr) address; - struct hppa_fptr *f; - -#ifdef _LIBC_REENTRANT - /* Make sure we are alone. */ - while (testandset (&__hppa_fptr_lock)); -#endif - - for (f = __fptr_root; f != NULL; f = f->next) - if (f == address) - { - addr = f->func; - break; - } - -#ifdef _LIBC_REENTRANT - /* Release the lock. */ - __hppa_fptr_lock = 1; -#endif - - return addr; -} diff --git a/sysdeps/hppa/dl-fptr.h b/sysdeps/hppa/dl-fptr.h new file mode 100644 index 0000000..2ac9740 --- /dev/null +++ b/sysdeps/hppa/dl-fptr.h @@ -0,0 +1,35 @@ +/* Function descriptors. HPPA version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef dl_hppa_fptr_h +#define dl_hppa_fptr_h 1 + +#include <sysdeps/generic/dl-fptr.h> + +/* There are currently 20 dynamic symbols in ld.so. + ELF_MACHINE_BOOT_FPTR_TABLE_LEN needs to be at least that big. */ +#define ELF_MACHINE_BOOT_FPTR_TABLE_LEN 200 + +#define ELF_MACHINE_LOAD_ADDRESS(var, symbol) \ + asm (" addil LT%%" #symbol ", %%r19\n" \ + " ldw RT%%" #symbol "(%%sr0,%%r1), %0\n" \ + : "=&r" (var)); + + +#endif /* !dl_hppa_fptr_h */ diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h index d76ea12..d393b3e 100644 --- a/sysdeps/hppa/dl-lookupcfg.h +++ b/sysdeps/hppa/dl-lookupcfg.h @@ -26,27 +26,44 @@ /* Forward declaration. */ struct link_map; -void *_dl_symbol_address (const struct link_map *map, const ElfW(Sym) *ref); +void *_dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref); #define DL_SYMBOL_ADDRESS(map, ref) _dl_symbol_address(map, ref) Elf32_Addr _dl_lookup_address (const void *address); -#define DL_LOOKUP_ADDRESS(addr) _dl_lookup_address (addr) +/* Clear the bottom two bits so generic code can find the fdesc entry */ +#define DL_LOOKUP_ADDRESS(addr) \ + (_dl_lookup_address ((void *)((unsigned long)addr & ~3))) void _dl_unmap (struct link_map *map); #define DL_UNMAP(map) _dl_unmap (map) -extern Elf32_Addr _dl_function_address (const struct link_map *map, - Elf32_Addr start); +#define DL_AUTO_FUNCTION_ADDRESS(map, addr) \ +({ \ + unsigned int fptr[2]; \ + fptr[0] = (unsigned int) (addr); \ + fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr; \ + /* Set bit 30 to indicate to $$dyncall that this is a PLABEL. */ \ + (ElfW(Addr))((unsigned int)fptr | 2); \ +}) + +#define DL_STATIC_FUNCTION_ADDRESS(map, addr) \ +({ \ + static unsigned int fptr[2]; \ + fptr[0] = (unsigned int) (addr); \ + fptr[1] = (map)->l_info[DT_PLTGOT]->d_un.d_ptr; \ + /* Set bit 30 to indicate to $$dyncall that this is a PLABEL. */ \ + (ElfW(Addr))((unsigned int)fptr | 2); \ +}) -#define DL_FUNCTION_ADDRESS(map, addr) _dl_function_address (map, addr) /* The test for "addr & 2" below is to accomodate old binaries which violated the ELF ABI by pointing DT_INIT and DT_FINI at a function - pointer. */ + descriptor. */ #define DL_DT_INIT_ADDRESS(map, addr) \ - ((Elf32_Addr)(addr) & 2 ? (addr) : DL_FUNCTION_ADDRESS (map, addr)) + ((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr)) #define DL_DT_FINI_ADDRESS(map, addr) \ - ((Elf32_Addr)(addr) & 2 ? (addr) : DL_FUNCTION_ADDRESS (map, addr)) + ((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr)) + diff --git a/sysdeps/hppa/dl-symaddr.c b/sysdeps/hppa/dl-symaddr.c index 1aec19a..e5ce6a9 100644 --- a/sysdeps/hppa/dl-symaddr.c +++ b/sysdeps/hppa/dl-symaddr.c @@ -21,19 +21,16 @@ #include <dl-machine.h> void * -_dl_symbol_address (const struct link_map *map, const ElfW(Sym) *ref) +_dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref) { + /* Find the "ip" from the "map" and symbol "ref" */ Elf32_Addr value = (map ? map->l_addr : 0) + ref->st_value; - /* On hppa, we have to return the pointer to function descriptor. */ - if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC) - return (void *) __hppa_make_fptr (map, value, &__fptr_root, NULL); + /* On hppa, we have to return the pointer to function descriptor. + This involves an "| 2" to inform $$dyncall that this is a plabel32 */ + if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC){ + return (void *)((unsigned long)_dl_make_fptr (map, ref, value) | 2); + } else return (void *) value; } - -ElfW(Addr) -_dl_function_address (const struct link_map *map, ElfW(Addr) start) -{ - return __hppa_make_fptr (map, start, &__fptr_root, NULL); -} diff --git a/sysdeps/hppa/fpu/fclrexcpt.c b/sysdeps/hppa/fpu/fclrexcpt.c index 8ad67b9..a7c6982 100644 --- a/sysdeps/hppa/fpu/fclrexcpt.c +++ b/sysdeps/hppa/fpu/fclrexcpt.c @@ -29,7 +29,7 @@ feclearexcept (int excepts) __asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw)); /* Clear all the relevant bits. */ - sw[0] &= ~(excepts & FE_ALL_EXCEPT) << 27; + sw[0] &= ~((excepts & FE_ALL_EXCEPT) << 27); __asm__ ("fldd 0(%0),%%fr0" : : "r" (sw)); /* Success. */ diff --git a/sysdeps/hppa/fpu/fegetenv.c b/sysdeps/hppa/fpu/fegetenv.c index 1ed18da..b87317b 100644 --- a/sysdeps/hppa/fpu/fegetenv.c +++ b/sysdeps/hppa/fpu/fegetenv.c @@ -24,10 +24,10 @@ int fegetenv (fenv_t *envp) { __asm__ ( - "fstd %%fr0,0(%2)\n" - "fstd,ma %%fr1,8(%2)\n" - "fstd,ma %%fr2,8(%2)\n" - "fstd %%fr3,0(%2)\n" - : "=m" (*envp), "=r" (envp) : "1" (envp)); + "fstd,ma %%fr0,8(%1)\n" + "fstd,ma %%fr1,8(%1)\n" + "fstd,ma %%fr2,8(%1)\n" + "fstd %%fr3,0(%1)\n" + : "=m" (*envp), "+r" (envp)); return 0; } diff --git a/sysdeps/hppa/fpu/feholdexcpt.c b/sysdeps/hppa/fpu/feholdexcpt.c index 2713336..db9fb40 100644 --- a/sysdeps/hppa/fpu/feholdexcpt.c +++ b/sysdeps/hppa/fpu/feholdexcpt.c @@ -25,18 +25,16 @@ int feholdexcept (fenv_t *envp) { fenv_t clear; + fenv_t * _regs = envp; /* Store the environment. */ - { - fenv_t * _regs = envp; - __asm__ ( - "fstd %%fr0,0(%2)\n" - "fstd,ma %%fr1,8(%2)\n" - "fstd,ma %%fr2,8(%2)\n" - "fstd %%fr3,0(%2)\n" - : "=m" (*_regs), "=r" (_regs) : "1" (_regs)); - memcpy (&clear, envp, sizeof (clear)); - } + __asm__ ( + "fstd,ma %%fr0,8(%1)\n" + "fstd,ma %%fr1,8(%1)\n" + "fstd,ma %%fr2,8(%1)\n" + "fstd %%fr3,0(%1)\n" + : "=m" (*_regs), "+r" (_regs)); + memcpy (&clear, envp, sizeof (clear)); /* Now clear all exceptions. */ clear.__status_word &= ~(FE_ALL_EXCEPT << 27); @@ -46,15 +44,13 @@ feholdexcept (fenv_t *envp) clear.__status_word &= ~FE_ALL_EXCEPT; /* Load the new environment. */ - { - fenv_t * _regs = &clear + 1; - __asm__ ( - "fldd,mb -8(%2),%%fr3\n" - "fldd,mb -8(%2),%%fr2\n" - "fldd,mb -8(%2),%%fr1\n" - "fldd -8(%2),%%fr0\n" - : "=m" (*_regs), "=r" (_regs) : "1" (_regs)); - } + _regs = &clear; + __asm__ ( + "fldd,ma -8(%1),%%fr3\n" + "fldd,ma -8(%1),%%fr2\n" + "fldd,ma -8(%1),%%fr1\n" + "fldd 0(%1),%%fr0\n" + : "=m" (*_regs), "+r" (_regs)); return 0; } diff --git a/sysdeps/hppa/fpu/fesetenv.c b/sysdeps/hppa/fpu/fesetenv.c index 2c79869..5267732 100644 --- a/sysdeps/hppa/fpu/fesetenv.c +++ b/sysdeps/hppa/fpu/fesetenv.c @@ -26,20 +26,18 @@ int fesetenv (const fenv_t *envp) { fenv_t temp; + fenv_t * _regs = &temp; /* Install the environment specified by ENVP. But there are a few values which we do not want to come from the saved environment. Therefore, we get the current environment and replace the values we want to use from the environment specified by the parameter. */ - { - fenv_t * _regs = &temp; - __asm__ ( - "fstd %%fr0,0(%2)\n" - "fstd,ma %%fr1,8(%2)\n" - "fstd,ma %%fr2,8(%2)\n" - "fstd %%fr3,0(%2)\n" - : "=m" (*_regs), "=r" (_regs) : "1" (_regs)); - } + __asm__ ( + "fstd,ma %%fr0,8(%1)\n" + "fstd,ma %%fr1,8(%1)\n" + "fstd,ma %%fr2,8(%1)\n" + "fstd %%fr3,0(%1)\n" + : "=m" (*_regs), "+r" (_regs)); temp.__status_word &= ~(FE_ALL_EXCEPT | (FE_ALL_EXCEPT << 27) @@ -55,15 +53,12 @@ fesetenv (const fenv_t *envp) | (FE_ALL_EXCEPT << 27))); /* Load the new environment. */ - { - fenv_t * _regs = &temp + 1; - __asm__ ( - "fldd,mb -8(%2),%%fr3\n" - "fldd,mb -8(%2),%%fr2\n" - "fldd,mb -8(%2),%%fr1\n" - "fldd -8(%2),%%fr0\n" - : "=m" (*_regs), "=r" (_regs) : "1" (_regs)); - } + __asm__ ( + "fldd,ma -8(%1),%%fr3\n" + "fldd,ma -8(%1),%%fr2\n" + "fldd,ma -8(%1),%%fr1\n" + "fldd 0(%1),%%fr0\n" + : "=m" (*_regs), "+r" (_regs)); /* Success. */ return 0; diff --git a/sysdeps/hppa/fpu/feupdateenv.c b/sysdeps/hppa/fpu/feupdateenv.c index c61b7b2..8980dfd 100644 --- a/sysdeps/hppa/fpu/feupdateenv.c +++ b/sysdeps/hppa/fpu/feupdateenv.c @@ -27,14 +27,12 @@ feupdateenv (const fenv_t *envp) /* Get the current exception status. */ __asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw)); - sw[0] &= (FE_ALL_EXCEPT << 27); - + sw[0] &= FE_ALL_EXCEPT; + envp->__status_word = envp->__status_word | sw[0]; + /* Install new environment. */ fesetenv (envp); - /* Raise the saved exception. */ - feraiseexcept (sw[0] >> 27); - /* Success. */ return 0; } diff --git a/sysdeps/hppa/fpu/fraiseexcpt.c b/sysdeps/hppa/fpu/fraiseexcpt.c index a13668f..b064dc1 100644 --- a/sysdeps/hppa/fpu/fraiseexcpt.c +++ b/sysdeps/hppa/fpu/fraiseexcpt.c @@ -22,6 +22,9 @@ #include <float.h> #include <math.h> +/* Please see section 10, + page 10-5 "Delayed Trapping" in the PA-RISC 2.0 Architecture manual */ + int feraiseexcept (int excepts) { @@ -33,56 +36,64 @@ feraiseexcept (int excepts) /* We do these bits in assembly to be certain GCC doesn't optimize away something important, and so we can force delayed traps to - occur. */ - - /* FIXME: These all need verification! */ + occur. */ - /* First: invalid exception. */ + /* We use "fldd 0(%%sr0,%%sp),%0" to flush the delayed exception */ + + /* First: Invalid exception. */ if (excepts & FE_INVALID) { /* One example of a invalid operation is 0 * Infinity. */ double d = HUGE_VAL; - __asm__ __volatile__ ("fmpy,dbl %1,%%fr0,%0\n\t" - /* FIXME: is this a proper trap barrier? */ - "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d)); + __asm__ __volatile__ ( + " fcpy,dbl %%fr0,%%fr22\n" + " fmpy,dbl %0,%%fr22,%0\n" + " fldd 0(%%sr0,%%sp),%0" + : "+f" (d) : : "%fr22" ); } - /* Next: division by zero. */ + /* Second: Division by zero. */ if (excepts & FE_DIVBYZERO) { double d = 1.0; - __asm__ __volatile__ ("fdiv,dbl %1,%%fr0,%0\n\t" - "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d)); + __asm__ __volatile__ ( + " fcpy,dbl %%fr0,%%fr22\n" + " fdiv,dbl %0,%%fr22,%0\n" + " fldd 0(%%sr0,%%sp),%0" + : "+f" (d) : : "%fr22" ); } - /* Next: overflow. */ - /* FIXME: Compare with IA-64 - do we have the same problem? */ + /* Third: Overflow. */ if (excepts & FE_OVERFLOW) { double d = DBL_MAX; - - __asm__ __volatile__ ("fmpy,dbl %1,%1,%0\n\t" - "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d)); + __asm__ __volatile__ ( + " fadd,dbl %0,%0,%0\n" + " fldd 0(%%sr0,%%sp),%0" + : "+f" (d) ); } - /* Next: underflow. */ + /* Fourth: Underflow. */ if (excepts & FE_UNDERFLOW) { double d = DBL_MIN; - double e = 69.69; - - __asm__ __volatile__ ("fdiv,dbl %1,%2,%0\n\t" - "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d), "f" (e)); + double e = 3.0; + __asm__ __volatile__ ( + " fdiv,dbl %0,%1,%0\n" + " fldd 0(%%sr0,%%sp),%0" + : "+f" (d) : "f" (e) ); } - /* Last: inexact. */ + /* Fifth: Inexact */ if (excepts & FE_INEXACT) { - double d = 1.0; - double e = M_PI; - - __asm__ __volatile__ ("fdiv,dbl %1,%2,%0\n\t" - "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d), "f" (e)); + double d = M_PI; + double e = 69.69; + __asm__ __volatile__ ( + " fdiv,dbl %0,%1,%%fr22\n" + " fcnvfxt,dbl,sgl %%fr22,%%fr22L\n" + " fldd 0(%%sr0,%%sp),%%fr22" + : : "f" (d), "f" (e) : "%fr22" ); } /* Success. */ diff --git a/sysdeps/hppa/fpu/fsetexcptflg.c b/sysdeps/hppa/fpu/fsetexcptflg.c index 343ddad..af35f5a 100644 --- a/sysdeps/hppa/fpu/fsetexcptflg.c +++ b/sysdeps/hppa/fpu/fsetexcptflg.c @@ -29,8 +29,7 @@ fesetexceptflag (const fexcept_t *flagp, int excepts) /* Get the current status word. */ __asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw)); - /* Install the new exception flags bits. */ - sw[0] &= ~(excepts & (FE_ALL_EXCEPT >> 27)); + /* Install new enable trap bits */ sw[0] |= (*flagp & excepts & FE_ALL_EXCEPT) << 27; /* Store the new status word. */ |