1
0
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:
Ulrich Drepper
2007-05-07 06:22:38 +00:00
parent 15eca72044
commit 4a59e9adcb
13 changed files with 249 additions and 19 deletions

View File

@@ -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]

View File

@@ -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

View File

@@ -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

View 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)

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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. */

View File

@@ -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);

View 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;
}

View 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;
}