mirror of
https://sourceware.org/git/glibc.git
synced 2026-01-06 11:51:29 +03:00
2007-04-30 Steven Munroe <sjmunroe@us.ibm.com>
Peter Bergner <bergner@us.ibm.com> * sysdeps/powerpc/bits/fenv.h: Declare __fe_mask_env extern. Define FE_NOMASK_ENV as FE_EANBLED_ENV. Define FE_MASK_ENV. * sysdeps/powerpc/fpu/Makefile: Add fe_mask to libm-support. * sysdeps/powerpc/fpu/fe_mask.c: New file. * sysdeps/powerpc/fpu/fe_nomask.c: Correct comment. * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Call __fe_mask_env() if all FP exceptions disabled. * sysdeps/powerpc/fpu/feholdexcpt.c (feholdexcept): Copy high 32-bits from old FPSCR to new fenv to propagate DFP rounding modes. Call __fe_mask_env() if FP exceptions previously enabled. * sysdeps/powerpc/fpu/fesetenv.c (fesetenv): Change mask to merge exceptions from env. Use __fe_nomask_env() or __fe_mask_env() when transitioning from all exceptions disabled to any exception enabled or visa versa. * sysdeps/powerpc/fpu/feupdateenv.c (__feupdateenv): Change mask to merge exceptions from env. Call __fe_nomask_env or __fe_mask_env when transitioning from all exceptions disabled to any exception enabled or visa versa. * sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c: Moved to... * sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c: ...here. * sysdeps/unix/sysv/linux/powerpc/powerpc64/fe_nomask.c: Moved to... * sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c: ...here. * sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_mask.c: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c: New file.
This commit is contained in:
28
ChangeLog
28
ChangeLog
@@ -1,3 +1,31 @@
|
||||
2007-04-30 Steven Munroe <sjmunroe@us.ibm.com>
|
||||
Peter Bergner <bergner@us.ibm.com>
|
||||
|
||||
* sysdeps/powerpc/bits/fenv.h: Declare __fe_mask_env extern.
|
||||
Define FE_NOMASK_ENV as FE_EANBLED_ENV. Define FE_MASK_ENV.
|
||||
* sysdeps/powerpc/fpu/Makefile: Add fe_mask to libm-support.
|
||||
* sysdeps/powerpc/fpu/fe_mask.c: New file.
|
||||
* sysdeps/powerpc/fpu/fe_nomask.c: Correct comment.
|
||||
* sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept):
|
||||
Call __fe_mask_env() if all FP exceptions disabled.
|
||||
* sysdeps/powerpc/fpu/feholdexcpt.c (feholdexcept): Copy high 32-bits
|
||||
from old FPSCR to new fenv to propagate DFP rounding modes.
|
||||
Call __fe_mask_env() if FP exceptions previously enabled.
|
||||
* sysdeps/powerpc/fpu/fesetenv.c (fesetenv): Change mask to merge
|
||||
exceptions from env. Use __fe_nomask_env() or __fe_mask_env() when
|
||||
transitioning from all exceptions disabled to any exception enabled
|
||||
or visa versa.
|
||||
* sysdeps/powerpc/fpu/feupdateenv.c (__feupdateenv): Change mask to
|
||||
merge exceptions from env. Call __fe_nomask_env or __fe_mask_env
|
||||
when transitioning from all exceptions disabled to any exception
|
||||
enabled or visa versa.
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/fe_nomask.c: Moved to...
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c: ...here.
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc64/fe_nomask.c: Moved to...
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c: ...here.
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_mask.c: New file.
|
||||
* sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c: New file.
|
||||
|
||||
2007-05-06 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
[BZ #4465]
|
||||
|
||||
@@ -137,9 +137,19 @@ extern const fenv_t __fe_nonieee_env;
|
||||
# define FE_NONIEEE_ENV (&__fe_nonieee_env)
|
||||
|
||||
/* Floating-point environment with all exceptions enabled. Note that
|
||||
just evaluating this value will set the processor into 'FPU
|
||||
exceptions imprecise recoverable' mode, which may cause a significant
|
||||
performance penalty (but have no other visible effect). */
|
||||
just evaluating this value does not change the processor exception mode.
|
||||
Passing this mask to fesetenv will result in a prctl syscall to change
|
||||
the MSR FE0/FE1 bits to "Precise Mode". On some processors this will
|
||||
result in slower floating point execution. This will last until an
|
||||
fenv or exception mask is installed that disables all FP exceptions. */
|
||||
extern const fenv_t *__fe_nomask_env (void);
|
||||
# define FE_NOMASK_ENV (__fe_nomask_env ())
|
||||
# define FE_NOMASK_ENV FE_ENABLED_ENV
|
||||
|
||||
/* Floating-point environment with all exceptions disabled. Note that
|
||||
just evaluating this value does not change the processor exception mode.
|
||||
Passing this mask to fesetenv will result in a prctl syscall to change
|
||||
the MSR FE0/FE1 bits to "Ignore Exceptions Mode". On most processors
|
||||
this allows the fastest possible floating point execution.*/
|
||||
extern const fenv_t *__fe_mask_env (void);
|
||||
# define FE_MASK_ENV FE_DFL_ENV
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
ifeq ($(subdir),math)
|
||||
libm-support += fenv_const fe_nomask t_sqrt
|
||||
libm-support += fenv_const fe_nomask fe_mask t_sqrt
|
||||
|
||||
# libm needs ld.so to access dl_hwcap
|
||||
$(objpfx)libm.so: $(elfobjdir)/ld.so
|
||||
|
||||
33
sysdeps/powerpc/fpu/fe_mask.c
Normal file
33
sysdeps/powerpc/fpu/fe_mask.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Procedure definition for FE_MASK_ENV.
|
||||
Copyright (C) 2007 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 <fenv.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* This is a generic stub. An OS specific override is required to clear
|
||||
the FE0/FE1 bits in the MSR. MSR update is privileged, so this will
|
||||
normally involve a syscall. */
|
||||
|
||||
const fenv_t *
|
||||
__fe_mask_env(void)
|
||||
{
|
||||
__set_errno (ENOSYS);
|
||||
return FE_DFL_ENV;
|
||||
}
|
||||
stub_warning (__fe_mask_env)
|
||||
@@ -20,8 +20,9 @@
|
||||
#include <fenv.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* This is presently a stub, until it's decided how the kernels should
|
||||
support this. */
|
||||
/* This is a generic stub. An OS specific override is required to set
|
||||
the FE0/FE1 bits in the MSR. MSR update is privileged, so this will
|
||||
normally involve a syscall. */
|
||||
|
||||
const fenv_t *
|
||||
__fe_nomask_env(void)
|
||||
|
||||
@@ -24,7 +24,7 @@ int
|
||||
fedisableexcept (int excepts)
|
||||
{
|
||||
fenv_union_t fe;
|
||||
int result;
|
||||
int result, new;
|
||||
|
||||
result = fegetexcept ();
|
||||
|
||||
@@ -44,7 +44,11 @@ fedisableexcept (int excepts)
|
||||
fe.l[1] &= ~(1 << (31 - FPSCR_VE));
|
||||
fesetenv_register (fe.fenv);
|
||||
|
||||
if ((fegetexcept () & excepts) != 0)
|
||||
new = fegetexcept ();
|
||||
if (new == 0 && result != 0)
|
||||
(void)__fe_mask_env ();
|
||||
|
||||
if ((new & excepts) != 0)
|
||||
result = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -22,17 +22,24 @@
|
||||
int
|
||||
feholdexcept (fenv_t *envp)
|
||||
{
|
||||
fenv_union_t u;
|
||||
fenv_union_t old, new;
|
||||
|
||||
/* Get the current state. */
|
||||
u.fenv = *envp = fegetenv_register ();
|
||||
/* Save the currently set exceptions. */
|
||||
old.fenv = *envp = fegetenv_register ();
|
||||
|
||||
/* Clear everything except for the rounding mode and non-IEEE arithmetic
|
||||
/* Clear everything except for the rounding modes and non-IEEE arithmetic
|
||||
flag. */
|
||||
u.l[1] = u.l[1] & 7;
|
||||
new.l[1] = old.l[1] & 7;
|
||||
new.l[0] = old.l[0];
|
||||
|
||||
/* If the old env had any eabled exceptions, then mask SIGFPE in the
|
||||
MSR FE0/FE1 bits. This may allow the FPU to run faster because it
|
||||
always takes the default action and can not generate SIGFPE. */
|
||||
if ((old.l[1] & 0x000000F8) != 0)
|
||||
(void)__fe_mask_env ();
|
||||
|
||||
/* Put the new state in effect. */
|
||||
fesetenv_register (u.fenv);
|
||||
fesetenv_register (new.fenv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Install given floating-point environment.
|
||||
Copyright (C) 1997,99,2000,01,02 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997,99,2000,01,02,07 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
|
||||
@@ -23,6 +23,26 @@
|
||||
int
|
||||
__fesetenv (const fenv_t *envp)
|
||||
{
|
||||
fenv_union_t old, new;
|
||||
|
||||
/* get the currently set exceptions. */
|
||||
new.fenv = *envp;
|
||||
old.fenv = fegetenv_register ();
|
||||
|
||||
/* If the old env has no eabled exceptions and the new env has any enabled
|
||||
exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put
|
||||
the hardware into "precise mode" and may cause the FPU to run slower on
|
||||
some hardware. */
|
||||
if ((old.l[1] & 0x000000F8) == 0 && (new.l[1] & 0x000000F8) != 0)
|
||||
(void)__fe_nomask_env ();
|
||||
|
||||
/* If the old env had any eabled exceptions and the new env has no enabled
|
||||
exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the
|
||||
FPU to run faster because it always takes the default action and can not
|
||||
generate SIGFPE. */
|
||||
if ((old.l[1] & 0x000000F8) != 0 && (new.l[1] & 0x000000F8) == 0)
|
||||
(void)__fe_mask_env ();
|
||||
|
||||
fesetenv_register (*envp);
|
||||
|
||||
/* Success. */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Install given floating-point environment and raise exceptions.
|
||||
Copyright (C) 1997,99,2000,01 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997,99,2000,01,07 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
@@ -30,8 +30,24 @@ __feupdateenv (const fenv_t *envp)
|
||||
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);
|
||||
/* Restore rounding mode and exception enable from *envp and merge
|
||||
exceptions. Leave fraction rounded/inexact and FP result/CC bits
|
||||
unchanged. */
|
||||
new.l[1] = (old.l[1] & 0x1FFFFF00) | (new.l[1] & 0x1FF80FFF);
|
||||
|
||||
/* If the old env has no eabled exceptions and the new env has any enabled
|
||||
exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put
|
||||
the hardware into "precise mode" and may cause the FPU to run slower on
|
||||
some hardware. */
|
||||
if ((old.l[1] & 0x000000F8) == 0 && (new.l[1] & 0x000000F8) != 0)
|
||||
(void)__fe_nomask_env ();
|
||||
|
||||
/* If the old env had any eabled exceptions and the new env has no enabled
|
||||
exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the
|
||||
FPU to run faster because it always takes the default action and can not
|
||||
generate SIGFPE. */
|
||||
if ((old.l[1] & 0x000000F8) != 0 && (new.l[1] & 0x000000F8) == 0)
|
||||
(void)__fe_mask_env ();
|
||||
|
||||
/* Atomically enable and raise (if appropriate) exceptions set in `new'. */
|
||||
fesetenv_register (new.fenv);
|
||||
|
||||
68
sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_mask.c
Normal file
68
sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_mask.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/* Procedure definition for FE_MASK_ENV for Linux/ppc.
|
||||
Copyright (C) 2007 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 <fenv.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sysdep.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <kernel-features.h>
|
||||
|
||||
#if __ASSUME_NEW_PRCTL_SYSCALL == 0
|
||||
/* This is rather fiddly under Linux. We don't have direct access,
|
||||
and there is no system call, but we can change the bits
|
||||
in a signal handler's context... */
|
||||
|
||||
static struct sigaction oact;
|
||||
|
||||
static void
|
||||
fe_mask_handler (int signum, struct sigcontext *sc)
|
||||
{
|
||||
sc->regs->msr &= ~0x900ul; /* FE0 | FE1 */
|
||||
sigaction (SIGUSR1, &oact, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
const fenv_t *
|
||||
__fe_mask_env (void)
|
||||
{
|
||||
#if __ASSUME_NEW_PRCTL_SYSCALL == 0
|
||||
# if defined PR_SET_FPEXC && defined PR_FP_EXC_DISABLED
|
||||
int result = INLINE_SYSCALL (prctl, 2, PR_SET_FPEXC, PR_FP_EXC_DISABLED);
|
||||
|
||||
if (result == -1 && errno == EINVAL)
|
||||
# endif
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = (sighandler_t) fe_mask_handler;
|
||||
sigemptyset (&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
|
||||
sigaction (SIGUSR1, &act, &oact);
|
||||
raise (SIGUSR1);
|
||||
}
|
||||
#else
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_DISABLED);
|
||||
#endif
|
||||
|
||||
return FE_DFL_ENV;
|
||||
}
|
||||
43
sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c
Normal file
43
sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Procedure definition for FE_MASK_ENV for Linux/ppc64.
|
||||
Copyright (C) 2007 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 <fenv.h>
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <kernel-features.h>
|
||||
|
||||
const fenv_t *
|
||||
__fe_mask_env (void)
|
||||
{
|
||||
#if defined PR_SET_FPEXC && defined PR_FP_EXC_DISABLED
|
||||
int result;
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
result = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_DISABLED);
|
||||
# ifndef __ASSUME_NEW_PRCTL_SYSCALL
|
||||
if (INTERNAL_SYSCALL_ERROR_P (result, err)
|
||||
&& INTERNAL_SYSCALL_ERRNO (result, err) == EINVAL)
|
||||
__set_errno (ENOSYS);
|
||||
# endif
|
||||
#else
|
||||
__set_errno (ENOSYS);
|
||||
#endif
|
||||
return FE_DFL_ENV;
|
||||
}
|
||||
Reference in New Issue
Block a user