mirror of git://sourceware.org/git/glibc.git
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.
This commit is contained in:
parent
4ae4facccf
commit
592f26a3ed
30
ChangeLog
30
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>
|
2003-12-17 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* malloc/mtrace.c (tr_old_memalign_hook): New variable.
|
* malloc/mtrace.c (tr_old_memalign_hook): New variable.
|
||||||
|
@ -9,7 +37,7 @@
|
||||||
|
|
||||||
2003-12-17 Ulrich Drepper <drepper@redhat.com>
|
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>.
|
Patch by Alexander Achenbach <xela@slit.de>.
|
||||||
|
|
||||||
2003-12-16 Steven Munroe <sjmunroe@us.ibm.com>
|
2003-12-16 Steven Munroe <sjmunroe@us.ibm.com>
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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 */
|
|
@ -26,27 +26,44 @@
|
||||||
/* Forward declaration. */
|
/* Forward declaration. */
|
||||||
struct link_map;
|
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)
|
#define DL_SYMBOL_ADDRESS(map, ref) _dl_symbol_address(map, ref)
|
||||||
|
|
||||||
Elf32_Addr _dl_lookup_address (const void *address);
|
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);
|
void _dl_unmap (struct link_map *map);
|
||||||
|
|
||||||
#define DL_UNMAP(map) _dl_unmap (map)
|
#define DL_UNMAP(map) _dl_unmap (map)
|
||||||
|
|
||||||
extern Elf32_Addr _dl_function_address (const struct link_map *map,
|
#define DL_AUTO_FUNCTION_ADDRESS(map, addr) \
|
||||||
Elf32_Addr start);
|
({ \
|
||||||
|
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
|
/* 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
|
violated the ELF ABI by pointing DT_INIT and DT_FINI at a function
|
||||||
pointer. */
|
descriptor. */
|
||||||
#define DL_DT_INIT_ADDRESS(map, addr) \
|
#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) \
|
#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))
|
||||||
|
|
||||||
|
|
|
@ -21,19 +21,16 @@
|
||||||
#include <dl-machine.h>
|
#include <dl-machine.h>
|
||||||
|
|
||||||
void *
|
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;
|
Elf32_Addr value = (map ? map->l_addr : 0) + ref->st_value;
|
||||||
|
|
||||||
/* On hppa, we have to return the pointer to function descriptor. */
|
/* On hppa, we have to return the pointer to function descriptor.
|
||||||
if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC)
|
This involves an "| 2" to inform $$dyncall that this is a plabel32 */
|
||||||
return (void *) __hppa_make_fptr (map, value, &__fptr_root, NULL);
|
if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC){
|
||||||
|
return (void *)((unsigned long)_dl_make_fptr (map, ref, value) | 2);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return (void *) value;
|
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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ feclearexcept (int excepts)
|
||||||
__asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw));
|
__asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw));
|
||||||
|
|
||||||
/* Clear all the relevant bits. */
|
/* 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));
|
__asm__ ("fldd 0(%0),%%fr0" : : "r" (sw));
|
||||||
|
|
||||||
/* Success. */
|
/* Success. */
|
||||||
|
|
|
@ -24,10 +24,10 @@ int
|
||||||
fegetenv (fenv_t *envp)
|
fegetenv (fenv_t *envp)
|
||||||
{
|
{
|
||||||
__asm__ (
|
__asm__ (
|
||||||
"fstd %%fr0,0(%2)\n"
|
"fstd,ma %%fr0,8(%1)\n"
|
||||||
"fstd,ma %%fr1,8(%2)\n"
|
"fstd,ma %%fr1,8(%1)\n"
|
||||||
"fstd,ma %%fr2,8(%2)\n"
|
"fstd,ma %%fr2,8(%1)\n"
|
||||||
"fstd %%fr3,0(%2)\n"
|
"fstd %%fr3,0(%1)\n"
|
||||||
: "=m" (*envp), "=r" (envp) : "1" (envp));
|
: "=m" (*envp), "+r" (envp));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,18 +25,16 @@ int
|
||||||
feholdexcept (fenv_t *envp)
|
feholdexcept (fenv_t *envp)
|
||||||
{
|
{
|
||||||
fenv_t clear;
|
fenv_t clear;
|
||||||
|
fenv_t * _regs = envp;
|
||||||
|
|
||||||
/* Store the environment. */
|
/* Store the environment. */
|
||||||
{
|
__asm__ (
|
||||||
fenv_t * _regs = envp;
|
"fstd,ma %%fr0,8(%1)\n"
|
||||||
__asm__ (
|
"fstd,ma %%fr1,8(%1)\n"
|
||||||
"fstd %%fr0,0(%2)\n"
|
"fstd,ma %%fr2,8(%1)\n"
|
||||||
"fstd,ma %%fr1,8(%2)\n"
|
"fstd %%fr3,0(%1)\n"
|
||||||
"fstd,ma %%fr2,8(%2)\n"
|
: "=m" (*_regs), "+r" (_regs));
|
||||||
"fstd %%fr3,0(%2)\n"
|
memcpy (&clear, envp, sizeof (clear));
|
||||||
: "=m" (*_regs), "=r" (_regs) : "1" (_regs));
|
|
||||||
memcpy (&clear, envp, sizeof (clear));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now clear all exceptions. */
|
/* Now clear all exceptions. */
|
||||||
clear.__status_word &= ~(FE_ALL_EXCEPT << 27);
|
clear.__status_word &= ~(FE_ALL_EXCEPT << 27);
|
||||||
|
@ -46,15 +44,13 @@ feholdexcept (fenv_t *envp)
|
||||||
clear.__status_word &= ~FE_ALL_EXCEPT;
|
clear.__status_word &= ~FE_ALL_EXCEPT;
|
||||||
|
|
||||||
/* Load the new environment. */
|
/* Load the new environment. */
|
||||||
{
|
_regs = &clear;
|
||||||
fenv_t * _regs = &clear + 1;
|
__asm__ (
|
||||||
__asm__ (
|
"fldd,ma -8(%1),%%fr3\n"
|
||||||
"fldd,mb -8(%2),%%fr3\n"
|
"fldd,ma -8(%1),%%fr2\n"
|
||||||
"fldd,mb -8(%2),%%fr2\n"
|
"fldd,ma -8(%1),%%fr1\n"
|
||||||
"fldd,mb -8(%2),%%fr1\n"
|
"fldd 0(%1),%%fr0\n"
|
||||||
"fldd -8(%2),%%fr0\n"
|
: "=m" (*_regs), "+r" (_regs));
|
||||||
: "=m" (*_regs), "=r" (_regs) : "1" (_regs));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,20 +26,18 @@ int
|
||||||
fesetenv (const fenv_t *envp)
|
fesetenv (const fenv_t *envp)
|
||||||
{
|
{
|
||||||
fenv_t temp;
|
fenv_t temp;
|
||||||
|
fenv_t * _regs = &temp;
|
||||||
|
|
||||||
/* Install the environment specified by ENVP. But there are a few
|
/* Install the environment specified by ENVP. But there are a few
|
||||||
values which we do not want to come from the saved environment.
|
values which we do not want to come from the saved environment.
|
||||||
Therefore, we get the current environment and replace the values
|
Therefore, we get the current environment and replace the values
|
||||||
we want to use from the environment specified by the parameter. */
|
we want to use from the environment specified by the parameter. */
|
||||||
{
|
__asm__ (
|
||||||
fenv_t * _regs = &temp;
|
"fstd,ma %%fr0,8(%1)\n"
|
||||||
__asm__ (
|
"fstd,ma %%fr1,8(%1)\n"
|
||||||
"fstd %%fr0,0(%2)\n"
|
"fstd,ma %%fr2,8(%1)\n"
|
||||||
"fstd,ma %%fr1,8(%2)\n"
|
"fstd %%fr3,0(%1)\n"
|
||||||
"fstd,ma %%fr2,8(%2)\n"
|
: "=m" (*_regs), "+r" (_regs));
|
||||||
"fstd %%fr3,0(%2)\n"
|
|
||||||
: "=m" (*_regs), "=r" (_regs) : "1" (_regs));
|
|
||||||
}
|
|
||||||
|
|
||||||
temp.__status_word &= ~(FE_ALL_EXCEPT
|
temp.__status_word &= ~(FE_ALL_EXCEPT
|
||||||
| (FE_ALL_EXCEPT << 27)
|
| (FE_ALL_EXCEPT << 27)
|
||||||
|
@ -55,15 +53,12 @@ fesetenv (const fenv_t *envp)
|
||||||
| (FE_ALL_EXCEPT << 27)));
|
| (FE_ALL_EXCEPT << 27)));
|
||||||
|
|
||||||
/* Load the new environment. */
|
/* Load the new environment. */
|
||||||
{
|
__asm__ (
|
||||||
fenv_t * _regs = &temp + 1;
|
"fldd,ma -8(%1),%%fr3\n"
|
||||||
__asm__ (
|
"fldd,ma -8(%1),%%fr2\n"
|
||||||
"fldd,mb -8(%2),%%fr3\n"
|
"fldd,ma -8(%1),%%fr1\n"
|
||||||
"fldd,mb -8(%2),%%fr2\n"
|
"fldd 0(%1),%%fr0\n"
|
||||||
"fldd,mb -8(%2),%%fr1\n"
|
: "=m" (*_regs), "+r" (_regs));
|
||||||
"fldd -8(%2),%%fr0\n"
|
|
||||||
: "=m" (*_regs), "=r" (_regs) : "1" (_regs));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Success. */
|
/* Success. */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -27,14 +27,12 @@ feupdateenv (const fenv_t *envp)
|
||||||
|
|
||||||
/* Get the current exception status. */
|
/* Get the current exception status. */
|
||||||
__asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw));
|
__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. */
|
/* Install new environment. */
|
||||||
fesetenv (envp);
|
fesetenv (envp);
|
||||||
|
|
||||||
/* Raise the saved exception. */
|
|
||||||
feraiseexcept (sw[0] >> 27);
|
|
||||||
|
|
||||||
/* Success. */
|
/* Success. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
/* Please see section 10,
|
||||||
|
page 10-5 "Delayed Trapping" in the PA-RISC 2.0 Architecture manual */
|
||||||
|
|
||||||
int
|
int
|
||||||
feraiseexcept (int excepts)
|
feraiseexcept (int excepts)
|
||||||
{
|
{
|
||||||
|
@ -33,56 +36,64 @@ feraiseexcept (int excepts)
|
||||||
|
|
||||||
/* We do these bits in assembly to be certain GCC doesn't optimize
|
/* We do these bits in assembly to be certain GCC doesn't optimize
|
||||||
away something important, and so we can force delayed traps to
|
away something important, and so we can force delayed traps to
|
||||||
occur. */
|
occur. */
|
||||||
|
|
||||||
/* FIXME: These all need verification! */
|
/* We use "fldd 0(%%sr0,%%sp),%0" to flush the delayed exception */
|
||||||
|
|
||||||
/* First: invalid exception. */
|
/* First: Invalid exception. */
|
||||||
if (excepts & FE_INVALID)
|
if (excepts & FE_INVALID)
|
||||||
{
|
{
|
||||||
/* One example of a invalid operation is 0 * Infinity. */
|
/* One example of a invalid operation is 0 * Infinity. */
|
||||||
double d = HUGE_VAL;
|
double d = HUGE_VAL;
|
||||||
__asm__ __volatile__ ("fmpy,dbl %1,%%fr0,%0\n\t"
|
__asm__ __volatile__ (
|
||||||
/* FIXME: is this a proper trap barrier? */
|
" fcpy,dbl %%fr0,%%fr22\n"
|
||||||
"fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d));
|
" 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)
|
if (excepts & FE_DIVBYZERO)
|
||||||
{
|
{
|
||||||
double d = 1.0;
|
double d = 1.0;
|
||||||
__asm__ __volatile__ ("fdiv,dbl %1,%%fr0,%0\n\t"
|
__asm__ __volatile__ (
|
||||||
"fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d));
|
" fcpy,dbl %%fr0,%%fr22\n"
|
||||||
|
" fdiv,dbl %0,%%fr22,%0\n"
|
||||||
|
" fldd 0(%%sr0,%%sp),%0"
|
||||||
|
: "+f" (d) : : "%fr22" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next: overflow. */
|
/* Third: Overflow. */
|
||||||
/* FIXME: Compare with IA-64 - do we have the same problem? */
|
|
||||||
if (excepts & FE_OVERFLOW)
|
if (excepts & FE_OVERFLOW)
|
||||||
{
|
{
|
||||||
double d = DBL_MAX;
|
double d = DBL_MAX;
|
||||||
|
__asm__ __volatile__ (
|
||||||
__asm__ __volatile__ ("fmpy,dbl %1,%1,%0\n\t"
|
" fadd,dbl %0,%0,%0\n"
|
||||||
"fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d));
|
" fldd 0(%%sr0,%%sp),%0"
|
||||||
|
: "+f" (d) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next: underflow. */
|
/* Fourth: Underflow. */
|
||||||
if (excepts & FE_UNDERFLOW)
|
if (excepts & FE_UNDERFLOW)
|
||||||
{
|
{
|
||||||
double d = DBL_MIN;
|
double d = DBL_MIN;
|
||||||
double e = 69.69;
|
double e = 3.0;
|
||||||
|
__asm__ __volatile__ (
|
||||||
__asm__ __volatile__ ("fdiv,dbl %1,%2,%0\n\t"
|
" fdiv,dbl %0,%1,%0\n"
|
||||||
"fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d), "f" (e));
|
" fldd 0(%%sr0,%%sp),%0"
|
||||||
|
: "+f" (d) : "f" (e) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Last: inexact. */
|
/* Fifth: Inexact */
|
||||||
if (excepts & FE_INEXACT)
|
if (excepts & FE_INEXACT)
|
||||||
{
|
{
|
||||||
double d = 1.0;
|
double d = M_PI;
|
||||||
double e = M_PI;
|
double e = 69.69;
|
||||||
|
__asm__ __volatile__ (
|
||||||
__asm__ __volatile__ ("fdiv,dbl %1,%2,%0\n\t"
|
" fdiv,dbl %0,%1,%%fr22\n"
|
||||||
"fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d), "f" (e));
|
" fcnvfxt,dbl,sgl %%fr22,%%fr22L\n"
|
||||||
|
" fldd 0(%%sr0,%%sp),%%fr22"
|
||||||
|
: : "f" (d), "f" (e) : "%fr22" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Success. */
|
/* Success. */
|
||||||
|
|
|
@ -29,8 +29,7 @@ fesetexceptflag (const fexcept_t *flagp, int excepts)
|
||||||
/* Get the current status word. */
|
/* Get the current status word. */
|
||||||
__asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw));
|
__asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw));
|
||||||
|
|
||||||
/* Install the new exception flags bits. */
|
/* Install new enable trap bits */
|
||||||
sw[0] &= ~(excepts & (FE_ALL_EXCEPT >> 27));
|
|
||||||
sw[0] |= (*flagp & excepts & FE_ALL_EXCEPT) << 27;
|
sw[0] |= (*flagp & excepts & FE_ALL_EXCEPT) << 27;
|
||||||
|
|
||||||
/* Store the new status word. */
|
/* Store the new status word. */
|
||||||
|
|
Loading…
Reference in New Issue