mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-26 06:50:07 +00:00
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>
|
||||
|
||||
* 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>
|
||||
|
@ -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;
|
||||
}
|
35
sysdeps/hppa/dl-fptr.h
Normal file
35
sysdeps/hppa/dl-fptr.h
Normal file
@ -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. */
|
||||
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))
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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. */
|
||||
occur. */
|
||||
|
||||
/* FIXME: These all need verification! */
|
||||
|
||||
/* 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. */
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user