glibc/sysdeps/powerpc/fpu/fesetmode.c

45 lines
1.4 KiB
C
Raw Normal View History

/* Install given floating-point control modes. PowerPC version.
Copyright (C) 2016-2019 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, see
<http://www.gnu.org/licenses/>. */
#include <fenv_libc.h>
#include <fpu_control.h>
int
fesetmode (const femode_t *modep)
{
fenv_union_t old, new;
/* Logic regarding enabled exceptions as in fesetenv. */
new.fenv = *modep;
[powerpc] fe{en,dis}ableexcept, fesetmode: optimize FPSCR accesses Since fe{en,dis}ableexcept() and fesetmode() read-modify-write just the "mode" (exception enable and rounding mode) bits of the Floating Point Status Control Register (FPSCR), the lighter weight 'mffsl' instruction can be used to read the FPSCR (enables and rounding mode), and 'mtfsf 0b00000011' can be used to write just those bits back to the FPSCR. The net is better performance. In addition, fe{en,dis}ableexcept() read the FPSCR again after writing it, or they determine that it doesn't need to be written because it is not changing. In either case, the local variable holds the current values of the enable bits in the FPSCR. This local variable can be used instead of again reading the FPSCR. Also, that value of the FPSCR which is read the second time is validated against the requested enables. Since the write can't fail, this validation step is unnecessary, and can be removed. Instead, the exceptions to be enabled (or disabled) are transformed into available bits in the FPSCR, then validated after being transformed back, to ensure that all requested bits are actually being set. For example, FE_INVALID_SQRT can be requested, but cannot actually be set. This bit is not mapped during the transformations, so a test for that bit being set before and after transformations will show the bit would not be set, and the function will return -1 for failure. Finally, convert the local macros in fesetmode.c to more generally useful macros in fenv_libc.h.
2019-07-19 00:37:13 +00:00
old.fenv = fegetenv_status ();
new.l = (new.l & ~FPSCR_STATUS_MASK) | (old.l & FPSCR_STATUS_MASK);
if (old.l == new.l)
return 0;
[powerpc] fe{en,dis}ableexcept, fesetmode: optimize FPSCR accesses Since fe{en,dis}ableexcept() and fesetmode() read-modify-write just the "mode" (exception enable and rounding mode) bits of the Floating Point Status Control Register (FPSCR), the lighter weight 'mffsl' instruction can be used to read the FPSCR (enables and rounding mode), and 'mtfsf 0b00000011' can be used to write just those bits back to the FPSCR. The net is better performance. In addition, fe{en,dis}ableexcept() read the FPSCR again after writing it, or they determine that it doesn't need to be written because it is not changing. In either case, the local variable holds the current values of the enable bits in the FPSCR. This local variable can be used instead of again reading the FPSCR. Also, that value of the FPSCR which is read the second time is validated against the requested enables. Since the write can't fail, this validation step is unnecessary, and can be removed. Instead, the exceptions to be enabled (or disabled) are transformed into available bits in the FPSCR, then validated after being transformed back, to ensure that all requested bits are actually being set. For example, FE_INVALID_SQRT can be requested, but cannot actually be set. This bit is not mapped during the transformations, so a test for that bit being set before and after transformations will show the bit would not be set, and the function will return -1 for failure. Finally, convert the local macros in fesetmode.c to more generally useful macros in fenv_libc.h.
2019-07-19 00:37:13 +00:00
if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0)
(void) __fe_nomask_env_priv ();
[powerpc] fe{en,dis}ableexcept, fesetmode: optimize FPSCR accesses Since fe{en,dis}ableexcept() and fesetmode() read-modify-write just the "mode" (exception enable and rounding mode) bits of the Floating Point Status Control Register (FPSCR), the lighter weight 'mffsl' instruction can be used to read the FPSCR (enables and rounding mode), and 'mtfsf 0b00000011' can be used to write just those bits back to the FPSCR. The net is better performance. In addition, fe{en,dis}ableexcept() read the FPSCR again after writing it, or they determine that it doesn't need to be written because it is not changing. In either case, the local variable holds the current values of the enable bits in the FPSCR. This local variable can be used instead of again reading the FPSCR. Also, that value of the FPSCR which is read the second time is validated against the requested enables. Since the write can't fail, this validation step is unnecessary, and can be removed. Instead, the exceptions to be enabled (or disabled) are transformed into available bits in the FPSCR, then validated after being transformed back, to ensure that all requested bits are actually being set. For example, FE_INVALID_SQRT can be requested, but cannot actually be set. This bit is not mapped during the transformations, so a test for that bit being set before and after transformations will show the bit would not be set, and the function will return -1 for failure. Finally, convert the local macros in fesetmode.c to more generally useful macros in fenv_libc.h.
2019-07-19 00:37:13 +00:00
if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0)
(void) __fe_mask_env ();
[powerpc] fe{en,dis}ableexcept, fesetmode: optimize FPSCR accesses Since fe{en,dis}ableexcept() and fesetmode() read-modify-write just the "mode" (exception enable and rounding mode) bits of the Floating Point Status Control Register (FPSCR), the lighter weight 'mffsl' instruction can be used to read the FPSCR (enables and rounding mode), and 'mtfsf 0b00000011' can be used to write just those bits back to the FPSCR. The net is better performance. In addition, fe{en,dis}ableexcept() read the FPSCR again after writing it, or they determine that it doesn't need to be written because it is not changing. In either case, the local variable holds the current values of the enable bits in the FPSCR. This local variable can be used instead of again reading the FPSCR. Also, that value of the FPSCR which is read the second time is validated against the requested enables. Since the write can't fail, this validation step is unnecessary, and can be removed. Instead, the exceptions to be enabled (or disabled) are transformed into available bits in the FPSCR, then validated after being transformed back, to ensure that all requested bits are actually being set. For example, FE_INVALID_SQRT can be requested, but cannot actually be set. This bit is not mapped during the transformations, so a test for that bit being set before and after transformations will show the bit would not be set, and the function will return -1 for failure. Finally, convert the local macros in fesetmode.c to more generally useful macros in fenv_libc.h.
2019-07-19 00:37:13 +00:00
fesetenv_mode (new.fenv);
return 0;
}