summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-12-18 04:02:31 +0000
committerUlrich Drepper <drepper@redhat.com>2003-12-18 04:02:31 +0000
commit592f26a3ed6e74aad8ff65eec9c139a6bc4aa89e (patch)
tree3eabb471cd2153b059302d3dedc628241fbb9071
parent4ae4facccf1286dae59ccc4758b64a76ab985aff (diff)
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--ChangeLog30
-rw-r--r--sysdeps/hppa/dl-fptr.c211
-rw-r--r--sysdeps/hppa/dl-fptr.h35
-rw-r--r--sysdeps/hppa/dl-lookupcfg.h33
-rw-r--r--sysdeps/hppa/dl-symaddr.c17
-rw-r--r--sysdeps/hppa/fpu/fclrexcpt.c2
-rw-r--r--sysdeps/hppa/fpu/fegetenv.c10
-rw-r--r--sysdeps/hppa/fpu/feholdexcpt.c34
-rw-r--r--sysdeps/hppa/fpu/fesetenv.c31
-rw-r--r--sysdeps/hppa/fpu/feupdateenv.c8
-rw-r--r--sysdeps/hppa/fpu/fraiseexcpt.c63
-rw-r--r--sysdeps/hppa/fpu/fsetexcptflg.c3
12 files changed, 171 insertions, 306 deletions
diff --git a/ChangeLog b/ChangeLog
index 72b76776ca..cc81360383 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 f8b6424abf..0000000000
--- 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 0000000000..2ac9740e30
--- /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 d76ea1221d..d393b3e427 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 1aec19ab19..e5ce6a9c03 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 8ad67b9698..a7c698206e 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 1ed18daa2c..b87317b789 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 27133365bc..db9fb409ae 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 2c7986987b..526773214b 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 c61b7b298a..8980dfd69c 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 a13668f954..b064dc1527 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 343ddad943..af35f5ae35 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. */