aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog168
-rw-r--r--NEWS13
-rw-r--r--elf/get-dynamic-info.h5
-rw-r--r--iconv/Makefile2
-rw-r--r--iconv/gconv_simple.c16
-rw-r--r--iconv/tst-iconv8.c50
-rw-r--r--iconv/tst-iconv_prog.sh284
-rw-r--r--iconvdata/ibm1364.c14
-rw-r--r--sysdeps/powerpc/fpu/fedisblxcpt.c26
-rw-r--r--sysdeps/powerpc/fpu/feenablxcpt.c27
-rw-r--r--sysdeps/powerpc/fpu/fegetexcept.c2
-rw-r--r--sysdeps/powerpc/fpu/fegetmode.c2
-rw-r--r--sysdeps/powerpc/fpu/feholdexcpt.c7
-rw-r--r--sysdeps/powerpc/fpu/fenv_libc.h169
-rw-r--r--sysdeps/powerpc/fpu/fenv_private.h129
-rw-r--r--sysdeps/powerpc/fpu/fesetenv.c27
-rw-r--r--sysdeps/powerpc/fpu/fesetmode.c18
-rw-r--r--sysdeps/powerpc/fpu/feupdateenv.c17
18 files changed, 749 insertions, 227 deletions
diff --git a/ChangeLog b/ChangeLog
index bc2f4aa..14d2cdd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -209,6 +209,174 @@
* malloc/malloc.c (__malloc_info): Remove unwanted leading
whitespace.
+2019-10-02 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_private.h:
+ (__TEST_AND_BEGIN_NON_STOP): New.
+ (__TEST_AND_END_NON_STOP): New.
+ (libc_feholdexcept_setround_ppc): Use __TEST_AND_BEGIN_NON_STOP.
+ (__libc_femergeenv_ppc): Use __TEST_AND_BEGIN_NON_STOP and
+ __TEST_AND_END_NON_STOP.
+ (libc_feholdsetround_noex_ppc_ctx): Use __TEST_AND_END_NON_STOP.
+
+2019-09-27 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_libc.h (fesetenv_mode): Rename to
+ fesetenv_control.
+ * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Accommodate
+ rename of fesetenv_mode to fegetenv_control.
+ * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Likewise.
+ * sysdeps/powerpc/fpu/fesetmode.c (fesetmode): Likewise.
+ * sysdeps/powerpc/fpu/fenv_private.h (__libc_femergeenv_ppc): Likewise.
+ (libc_feholdsetround_noex_ppc_ctx): Likewise.
+
+2019-09-27 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_private.h
+ (libc_feholdsetround_noex_ppc_ctx): Call fesetenv_mode instead
+ of fesetenv_register.
+
+2019-09-27 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_status): Rename to
+ fegetenv_control.
+ * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Accommodate
+ rename of fegetenv_status to fegetenv_control.
+ * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Likewise.
+ * sysdeps/powerpc/fpu/fegetexcept.c (__fegetexcept): Likewise.
+ * sysdeps/powerpc/fpu/fegetmode.c (fegetmode): Likewise.
+ * sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Likewise.
+ * sysdeps/powerpc/fpu/fesetmode.c (fesetmode): Likewise.
+
+2019-09-27 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_libc.h (__fesetround_inline): Use
+ 'mffscrn' instruction on POWER9.
+ (__fesetround_inline_nocheck): Likewise.
+
+2019-09-27 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_libc.h (FPSCR_EXCEPTIONS_MASK): New.
+ * sysdeps/powerpc/fpu/fenv_private.h (__libc_femergeenv_ppc): Optimize
+ to write FPSCR control only, if exceptions have not changed.
+
+2019-09-27 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_libc.h:
+ (__TEST_AND_ENTER_NON_STOP): New.
+ (__TEST_AND_EXIT_NON_STOP): New.
+ * sysdeps/powerpc/fpu/fenv_private.h
+ (_FPU_ALL_TRAPS): Delete, replace with FPSCR_ENABLES_MASK.
+ (_FPU_MASK_RN): Delete.
+ (_FPU_MASK_NOT_RN_NI): Delete.
+ (_FPU_MASK_TRAPS_RN): Delete, replace with ~FPSCR_CONTROL_MASK.
+ (_FPU_MASK_FRAC_INEX_RET_CC): Delete, replace with ~FPSCR_STATUS_MASK.
+ (__libc_feholdbits_ppc): Delete, move code into
+ libc_feholdexcept_setround_ppc.
+ (libc_feholdexcept_ppc): Delete.
+ (libc_fesetround_ppc): Delete.
+ (libc_fetestexcept_ppc): Delete.
+ (libc_feholdsetround_ppc): Delete.
+ (__libc_femergeenv_ppc): Use __TEST_AND_ENTER/EXIT_NON_STOP.
+ (libc_feholdsetround_noex_ppc_ctx): Likewise.
+ (libc_feupdateenv_test_ppc): Use FPSCR defines.
+ * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Use
+ __TEST_AND_ENTER_NON_STOP.
+ * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Likewise.
+ * sysdeps/powerpc/fpu/feholdexcpt.c (__feholdexcept): Likewise.
+ * sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Likewise.
+ * sysdeps/powerpc/fpu/fesetmode.c (fesetmode): Likewise.
+ * sysdeps/powerpc/fpu/feupdateenv.c (__feupdateenv): Likewise.
+ (_FPU_MASK_ALL): Delete.
+
+2019-09-19 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_and_set_rn): New.
+ (__fe_mffscrn): New.
+ * sysdeps/powerpc/fpu/fenv_private.h (libc_feholdsetround_ppc_ctx):
+ Do not clear enable bits, remove obsolete code, use
+ fegetenv_and_set_rn.
+ (libc_feresetround_ppc): Remove obsolete code, use
+ fegetenv_and_set_rn.
+
+2019-08-28 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_status_ISA300): Delete.
+ (fegetenv_status): Generate 'mffsl' unconditionally.
+
+2019-08-28 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Utilize lightweight
+ FPSCR read.
+ (_FPU_MASK_ALL): Delete.
+
+2019-08-28 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_private.h (libc_feholdsetround_ppc_ctx):
+ Utilize lightweight FPSCR read if possible, set fewer FPSCR bits
+ if possible.
+ (libc_feresetround_ppc): Replace call to __libc_femergeenv_ppc
+ with simpler required steps, set fewer FPSCR bits if possible.
+
+2019-08-28 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_libc.h (fesetenv_mode): New.
+ (FPSCR_FPRF_MASK): New. (FPSCR_STATUS_MASK): New.
+ * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Use lighter-
+ weight access to FPSCR; remove unnecessary second FPSCR read and
+ validate.
+ * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Likewise.
+ * sysdeps/powerpc/fpu/fesetmode.c (fesetmode): Use lighter-weight
+ access to FPSCR; Use macros in fenv_libc.h in favor of local.
+
+2019-08-28 Paul A. Clarke <pc@us.ibm.com>
+
+ * sysdeps/powerpc/fpu/fenv_libc.h: Define FPSCR bitmasks.
+ (fenv_reg_to_exceptions): Replace bitwise operations with mask-shift.
+ (fenv_exceptions_to_reg): New.
+ * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Replace bitwise
+ operation with call to fenv_exceptions_to_reg().
+ * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Likewise.
+
+2019-09-20 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/riscv/vfork.S: Do not include
+ <linux/sched.h>.
+ (CLONE_VM): New macro.
+ (CLONE_VFORK): Likewise.
+
+2019-09-14 Aurelien Jarno <aurelien@aurel32.net>
+
+ [BZ #24986]
+ * sysdeps/unix/alpha/getegid.S: Move to ...
+ * sysdeps/unix/sysv/linux/alpha/getegid.S: ... here.
+ * sysdeps/unix/alpha/geteuid.S: Move to ...
+ * sysdeps/unix/sysv/linux/alpha/geteuid.S: ... here.
+ * sysdeps/unix/alpha/getppid.S: Move to ...
+ * sysdeps/unix/sysv/linux/alpha/getppid.S: ... here
+
+2019-09-08 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+ * sysdeps/hppa/fpu/libm-test-ulps: Update.
+
+2019-09-03 Aurelien Jarno <aurelien@aurel32.net>
+
+ * sysdeps/alpha/fpu/libm-test-ulps: Regenerated using GCC 9.2.
+
+2019-08-28 Rafal Luzynski <digitalfreak@lingonborough.com>
+
+ [BZ #24682]
+ * NEWS: Mention this bug fixed.
+ * localedata/locales/bo_CN (first_weekday): Add, set to 2 (Monday).
+ * localedata/locales/ug_CN (first_weekday): Likewise.
+ * localedata/locales/zh_CN (first_weekday): Likewise.
+
+2019-08-01 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #24867]
+ * malloc/malloc.c (__malloc_info): Remove unwanted leading
+ whitespace.
+
2019-08-01 Carlos O'Donell <carlos@redhat.com>
* version.h (RELEASE): Set to "stable".
diff --git a/NEWS b/NEWS
index 8715fd7..64fa988 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,19 @@ CVE-2020-1751: A defect in the PowerPC backtrace function could cause an
CVE-2020-1752: A use-after-free vulnerability in the glob function when
expanding ~user has been fixed.
+CVE-2020-27618: An infinite loop has been fixed in the iconv program when
+ invoked with input containing redundant shift sequences in the IBM1364,
+ IBM1371, IBM1388, IBM1390, or IBM1399 character sets.
+
+CVE-2020-29562: An assertion failure has been fixed in the iconv function
+ when invoked with UCS4 input containing an invalid character.
+
+ CVE-2021-3326: An assertion failure during conversion from the
+ ISO-20220-JP-3 character set using the iconv function has been fixed.
+ This assertion was triggered by certain valid inputs in which the
+ converted output contains a combined sequence of two wide characters
+ crossing a buffer boundary. Reported by Tavis Ormandy.
+
The following bugs are resolved with this release:
[20019] NULL pointer dereference in libc.so.6 IFUNC due to uninitialized GOT
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
index 75fbb88..7ea645d 100644
--- a/elf/get-dynamic-info.h
+++ b/elf/get-dynamic-info.h
@@ -142,10 +142,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
assert (info[DT_FLAGS] == NULL
|| (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
#endif
-#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP
- assert (info[DT_RUNPATH] == NULL);
- assert (info[DT_RPATH] == NULL);
-#else
+#if ! defined RTLD_BOOTSTRAP && ! defined STATIC_PIE_BOOTSTRAP
if (info[DT_FLAGS] != NULL)
{
/* Flags are used. Translate to the old form where available.
diff --git a/iconv/Makefile b/iconv/Makefile
index 74cd9bf..5f9104e 100644
--- a/iconv/Makefile
+++ b/iconv/Makefile
@@ -44,7 +44,7 @@ CFLAGS-linereader.c += -DNO_TRANSLITERATION
CFLAGS-simple-hash.c += -I../locale
tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \
- tst-iconv7 tst-iconv-mt
+ tst-iconv7 tst-iconv8 tst-iconv-mt
others = iconv_prog iconvconfig
install-others-programs = $(inst_bindir)/iconv
diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c
index 75ce8fb..5902c28 100644
--- a/iconv/gconv_simple.c
+++ b/iconv/gconv_simple.c
@@ -239,11 +239,9 @@ ucs4_internal_loop (struct __gconv_step *step,
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
- size_t cnt;
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
+ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
uint32_t inval;
@@ -307,11 +305,9 @@ ucs4_internal_loop_unaligned (struct __gconv_step *step,
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
- size_t cnt;
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
+ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
if (__glibc_unlikely (inptr[0] > 0x80))
{
@@ -613,11 +609,9 @@ ucs4le_internal_loop (struct __gconv_step *step,
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
- size_t cnt;
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
+ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
uint32_t inval;
@@ -684,11 +678,9 @@ ucs4le_internal_loop_unaligned (struct __gconv_step *step,
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
- size_t cnt;
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
+ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
if (__glibc_unlikely (inptr[3] > 0x80))
{
diff --git a/iconv/tst-iconv8.c b/iconv/tst-iconv8.c
new file mode 100644
index 0000000..0b92b19
--- /dev/null
+++ b/iconv/tst-iconv8.c
@@ -0,0 +1,50 @@
+/* Test iconv behavior on UCS4 conversions with //IGNORE.
+ Copyright (C) 2020 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/>. */
+
+/* Derived from BZ #26923 */
+#include <errno.h>
+#include <iconv.h>
+#include <stdio.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ iconv_t cd = iconv_open ("UTF-8//IGNORE", "ISO-10646/UCS4/");
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
+
+ /*
+ * Convert sequence beginning with an irreversible character into buffer that
+ * is too small.
+ */
+ char input[12] = "\xe1\x80\xa1" "AAAAAAAAA";
+ char *inptr = input;
+ size_t insize = sizeof (input);
+ char output[6];
+ char *outptr = output;
+ size_t outsize = sizeof (output);
+
+ TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == -1);
+ TEST_VERIFY (errno == E2BIG);
+
+ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/iconv/tst-iconv_prog.sh b/iconv/tst-iconv_prog.sh
new file mode 100644
index 0000000..d8db7b3
--- /dev/null
+++ b/iconv/tst-iconv_prog.sh
@@ -0,0 +1,284 @@
+#!/bin/bash
+# Test for some known iconv(1) hangs from bug 19519, and miscellaneous
+# iconv(1) program error conditions.
+# Copyright (C) 2020 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
+# <https://www.gnu.org/licenses/>.
+
+codir=$1
+test_wrapper_env="$2"
+run_program_env="$3"
+
+# We have to have some directories in the library path.
+LIBPATH=$codir:$codir/iconvdata
+
+# How the start the iconv(1) program. $from is not defined/expanded yet.
+ICONV='
+$codir/elf/ld.so --library-path $LIBPATH --inhibit-rpath ${from}.so
+$codir/iconv/iconv_prog
+'
+ICONV="$test_wrapper_env $run_program_env $ICONV"
+
+# List of known hangs;
+# Gathered by running an exhaustive 2 byte input search against glibc-2.28
+hangarray=(
+"\x00\x23;-c;ANSI_X3.110;UTF-8//TRANSLIT//IGNORE"
+"\x00\xa1;-c;ARMSCII-8;UTF-8//TRANSLIT//IGNORE"
+"\x00\xa1;-c;ASMO_449;UTF-8//TRANSLIT//IGNORE"
+"\x00\x81;-c;BIG5;UTF-8//TRANSLIT//IGNORE"
+"\x00\xff;-c;BIG5HKSCS;UTF-8//TRANSLIT//IGNORE"
+"\x00\xff;-c;BRF;UTF-8//TRANSLIT//IGNORE"
+"\x00\xff;-c;BS_4730;UTF-8//TRANSLIT//IGNORE"
+"\x00\x81;-c;CP1250;UTF-8//TRANSLIT//IGNORE"
+"\x00\x98;-c;CP1251;UTF-8//TRANSLIT//IGNORE"
+"\x00\x81;-c;CP1252;UTF-8//TRANSLIT//IGNORE"
+"\x00\x81;-c;CP1253;UTF-8//TRANSLIT//IGNORE"
+"\x00\x81;-c;CP1254;UTF-8//TRANSLIT//IGNORE"
+"\x00\x81;-c;CP1255;UTF-8//TRANSLIT//IGNORE"
+"\x00\x81;-c;CP1257;UTF-8//TRANSLIT//IGNORE"
+"\x00\x81;-c;CP1258;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;CP932;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;CSA_Z243.4-1985-1;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;CSA_Z243.4-1985-2;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;DEC-MCS;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;DIN_66003;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;DS_2089;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-AT-DE;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-AT-DE-A;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-CA-FR;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-DK-NO;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-DK-NO-A;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-ES;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-ES-A;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-ES-S;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-FI-SE;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-FI-SE-A;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-FR;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-IS-FRISS;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-IT;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-PT;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-UK;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;EBCDIC-US;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ES;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ES2;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;EUC-CN;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;EUC-JISX0213;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;EUC-JP;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;EUC-JP-MS;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;EUC-KR;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;EUC-TW;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;GB18030;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;GB_1988-80;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;GBK;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;GOST_19768-74;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;GREEK7;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;GREEK7-OLD;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;GREEK-CCITT;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;HP-GREEK8;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;HP-ROMAN8;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;HP-ROMAN9;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;HP-THAI8;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;HP-TURKISH8;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM038;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;IBM1004;UTF-8//TRANSLIT//IGNORE"
+"\x00\xff;-c;IBM1008;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;IBM1046;UTF-8//TRANSLIT//IGNORE"
+"\x00\x51;-c;IBM1132;UTF-8//TRANSLIT//IGNORE"
+"\x00\xa0;-c;IBM1133;UTF-8//TRANSLIT//IGNORE"
+"\x00\xce;-c;IBM1137;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;IBM1161;UTF-8//TRANSLIT//IGNORE"
+"\x00\xdb;-c;IBM1162;UTF-8//TRANSLIT//IGNORE"
+"\x00\x70;-c;IBM12712;UTF-8//TRANSLIT//IGNORE"
+"\x00\x0f;-c;IBM1364;UTF-8"
+"\x0e\x0e;-c;IBM1364;UTF-8"
+"\x00\x0f;-c;IBM1371;UTF-8"
+"\x0e\x0e;-c;IBM1371;UTF-8"
+"\x00\x0f;-c;IBM1388;UTF-8"
+"\x0e\x0e;-c;IBM1388;UTF-8"
+"\x00\x0f;-c;IBM1390;UTF-8"
+"\x0e\x0e;-c;IBM1390;UTF-8"
+"\x00\x0f;-c;IBM1399;UTF-8"
+"\x0e\x0e;-c;IBM1399;UTF-8"
+"\x00\x53;-c;IBM16804;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM274;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM275;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM281;UTF-8//TRANSLIT//IGNORE"
+"\x00\x57;-c;IBM290;UTF-8//TRANSLIT//IGNORE"
+"\x00\x45;-c;IBM420;UTF-8//TRANSLIT//IGNORE"
+"\x00\x68;-c;IBM423;UTF-8//TRANSLIT//IGNORE"
+"\x00\x70;-c;IBM424;UTF-8//TRANSLIT//IGNORE"
+"\x00\x53;-c;IBM4517;UTF-8//TRANSLIT//IGNORE"
+"\x00\x53;-c;IBM4899;UTF-8//TRANSLIT//IGNORE"
+"\x00\xa5;-c;IBM4909;UTF-8//TRANSLIT//IGNORE"
+"\x00\xdc;-c;IBM4971;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM803;UTF-8//TRANSLIT//IGNORE"
+"\x00\x91;-c;IBM851;UTF-8//TRANSLIT//IGNORE"
+"\x00\x9b;-c;IBM856;UTF-8//TRANSLIT//IGNORE"
+"\x00\xd5;-c;IBM857;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;IBM864;UTF-8//TRANSLIT//IGNORE"
+"\x00\x94;-c;IBM868;UTF-8//TRANSLIT//IGNORE"
+"\x00\x94;-c;IBM869;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;IBM874;UTF-8//TRANSLIT//IGNORE"
+"\x00\x6a;-c;IBM875;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM880;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;IBM891;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;IBM903;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;IBM904;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM905;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;IBM9066;UTF-8//TRANSLIT//IGNORE"
+"\x00\x48;-c;IBM918;UTF-8//TRANSLIT//IGNORE"
+"\x00\x57;-c;IBM930;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;IBM932;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM933;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM935;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM937;UTF-8//TRANSLIT//IGNORE"
+"\x00\x41;-c;IBM939;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;IBM943;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;INIS;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;INIS-8;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;INIS-CYRILLIC;UTF-8//TRANSLIT//IGNORE"
+"\x00\xec;-c;ISIRI-3342;UTF-8//TRANSLIT//IGNORE"
+"\x00\xec;-c;ISO_10367-BOX;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-2022-CN;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-2022-CN-EXT;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-2022-JP;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-2022-JP-2;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-2022-JP-3;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-2022-KR;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO_2033;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO_5427;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO_5427-EXT;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO_5428;UTF-8//TRANSLIT//IGNORE"
+"\x00\xa4;-c;ISO_6937;UTF-8//TRANSLIT//IGNORE"
+"\x00\xa0;-c;ISO_6937-2;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-8859-11;UTF-8//TRANSLIT//IGNORE"
+"\x00\xa5;-c;ISO-8859-3;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-8859-6;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-8859-7;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;ISO-8859-8;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;ISO-IR-197;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;ISO-IR-209;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;IT;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;JIS_C6220-1969-RO;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;JIS_C6229-1984-B;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;JOHAB;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;JUS_I.B1.002;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;KOI-8;UTF-8//TRANSLIT//IGNORE"
+"\x00\x88;-c;KOI8-T;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;KSC5636;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;LATIN-GREEK;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;LATIN-GREEK-1;UTF-8//TRANSLIT//IGNORE"
+"\x00\xf6;-c;MAC-IS;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;MSZ_7795.3;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;NATS-DANO;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;NATS-SEFI;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;NC_NC00-10;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;NF_Z_62-010;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;NF_Z_62-010_1973;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;NS_4551-1;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;NS_4551-2;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;PT;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;PT2;UTF-8//TRANSLIT//IGNORE"
+"\x00\x98;-c;RK1048;UTF-8//TRANSLIT//IGNORE"
+"\x00\x98;-c;SEN_850200_B;UTF-8//TRANSLIT//IGNORE"
+"\x00\x98;-c;SEN_850200_C;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;Shift_JISX0213;UTF-8//TRANSLIT//IGNORE"
+"\x00\x80;-c;SJIS;UTF-8//TRANSLIT//IGNORE"
+"\x00\x23;-c;T.61-8BIT;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;TIS-620;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;TSCII;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;UHC;UTF-8//TRANSLIT//IGNORE"
+"\x00\xd8;-c;UNICODE;UTF-8//TRANSLIT//IGNORE"
+"\x00\xdc;-c;UTF-16;UTF-8//TRANSLIT//IGNORE"
+"\xdc\x00;-c;UTF-16BE;UTF-8//TRANSLIT//IGNORE"
+"\x00\xdc;-c;UTF-16LE;UTF-8//TRANSLIT//IGNORE"
+"\xff\xff;-c;UTF-7;UTF-8//TRANSLIT//IGNORE"
+"\x00\x81;-c;WIN-SAMI-2;UTF-8//TRANSLIT//IGNORE"
+)
+
+# List of option combinations that *should* lead to an error
+errorarray=(
+# Converting from/to invalid character sets should cause error
+"\x00\x00;;INVALID;INVALID"
+"\x00\x00;;INVALID;UTF-8"
+"\x00\x00;;UTF-8;INVALID"
+)
+
+# Requires $twobyte input, $c flag, $from, and $to to be set; sets $ret
+execute_test ()
+{
+ eval PROG=\"$ICONV\"
+ echo -en "$twobyte" \
+ | timeout -k 4 3 $PROG $c -f $from -t "$to" &>/dev/null
+ ret=$?
+}
+
+check_hangtest_result ()
+{
+ if [ "$ret" -eq "124" ] || [ "$ret" -eq "137" ]; then # timeout/hang
+ result="HANG"
+ else
+ if [ "$ret" -eq "139" ]; then # segfault
+ result="SEGFAULT"
+ else
+ if [ "$ret" -gt "127" ]; then # unexpected error
+ result="UNEXPECTED"
+ else
+ result="OK"
+ fi
+ fi
+ fi
+
+ echo -n "$result: from: \"$from\", to: \"$to\","
+ echo " input \"$twobyte\", flags \"$c\""
+
+ if [ "$result" != "OK" ]; then
+ exit 1
+ fi
+}
+
+for hangcommand in "${hangarray[@]}"; do
+ twobyte="$(echo "$hangcommand" | cut -d";" -f 1)"
+ c="$(echo "$hangcommand" | cut -d";" -f 2)"
+ from="$(echo "$hangcommand" | cut -d";" -f 3)"
+ to="$(echo "$hangcommand" | cut -d";" -f 4)"
+ execute_test
+ check_hangtest_result
+done
+
+check_errtest_result ()
+{
+ if [ "$ret" -eq "1" ]; then # we errored out as expected
+ result="PASS"
+ else
+ result="FAIL"
+ fi
+ echo -n "$result: from: \"$from\", to: \"$to\","
+ echo " input \"$twobyte\", flags \"$c\", return code $ret"
+
+ if [ "$result" != "PASS" ]; then
+ exit 1
+ fi
+}
+
+for errorcommand in "${errorarray[@]}"; do
+ twobyte="$(echo "$errorcommand" | cut -d";" -f 1)"
+ c="$(echo "$errorcommand" | cut -d";" -f 2)"
+ from="$(echo "$errorcommand" | cut -d";" -f 3)"
+ to="$(echo "$errorcommand" | cut -d";" -f 4)"
+ execute_test
+ check_errtest_result
+done
diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c
index 32ebe5a..65d3587 100644
--- a/iconvdata/ibm1364.c
+++ b/iconvdata/ibm1364.c
@@ -158,24 +158,14 @@ enum
\
if (__builtin_expect (ch, 0) == SO) \
{ \
- /* Shift OUT, change to DBCS converter. */ \
- if (curcs == db) \
- { \
- result = __GCONV_ILLEGAL_INPUT; \
- break; \
- } \
+ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \
curcs = db; \
++inptr; \
continue; \
} \
if (__builtin_expect (ch, 0) == SI) \
{ \
- /* Shift IN, change to SBCS converter. */ \
- if (curcs == sb) \
- { \
- result = __GCONV_ILLEGAL_INPUT; \
- break; \
- } \
+ /* Shift IN, change to SBCS converter (redundant escape okay). */ \
curcs = sb; \
++inptr; \
continue; \
diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c
index 2872b1b..70dbc65 100644
--- a/sysdeps/powerpc/fpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/fpu/fedisblxcpt.c
@@ -26,32 +26,24 @@ fedisableexcept (int excepts)
int result, new;
/* Get current exception mask to return. */
- fe.fenv = curr.fenv = fegetenv_register ();
+ fe.fenv = curr.fenv = fegetenv_control ();
result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
+ new = fenv_exceptions_to_reg (excepts);
+
+ if (fenv_reg_to_exceptions (new) != excepts)
+ return -1;
+
/* Sets the new exception mask. */
- if (excepts & FE_INEXACT)
- fe.l &= ~(1 << (31 - FPSCR_XE));
- if (excepts & FE_DIVBYZERO)
- fe.l &= ~(1 << (31 - FPSCR_ZE));
- if (excepts & FE_UNDERFLOW)
- fe.l &= ~(1 << (31 - FPSCR_UE));
- if (excepts & FE_OVERFLOW)
- fe.l &= ~(1 << (31 - FPSCR_OE));
- if (excepts & FE_INVALID)
- fe.l &= ~(1 << (31 - FPSCR_VE));
+ fe.l &= ~new;
if (fe.l != curr.l)
- fesetenv_register (fe.fenv);
+ fesetenv_control (fe.fenv);
- new = __fegetexcept ();
- if (new == 0 && result != 0)
- (void)__fe_mask_env ();
+ __TEST_AND_ENTER_NON_STOP (-1ULL, fe.l);
- if ((new & excepts) != 0)
- result = -1;
return result;
}
diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c
index dbaffdc..8be82a0 100644
--- a/sysdeps/powerpc/fpu/feenablxcpt.c
+++ b/sysdeps/powerpc/fpu/feenablxcpt.c
@@ -26,33 +26,24 @@ feenableexcept (int excepts)
int result, new;
/* Get current exception mask to return. */
- fe.fenv = curr.fenv = fegetenv_register ();
+ fe.fenv = curr.fenv = fegetenv_control ();
result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
+ new = fenv_exceptions_to_reg (excepts);
+
+ if (fenv_reg_to_exceptions (new) != excepts)
+ return -1;
+
/* Sets the new exception mask. */
- if (excepts & FE_INEXACT)
- fe.l |= (1 << (31 - FPSCR_XE));
- if (excepts & FE_DIVBYZERO)
- fe.l |= (1 << (31 - FPSCR_ZE));
- if (excepts & FE_UNDERFLOW)
- fe.l |= (1 << (31 - FPSCR_UE));
- if (excepts & FE_OVERFLOW)
- fe.l |= (1 << (31 - FPSCR_OE));
- if (excepts & FE_INVALID)
- fe.l |= (1 << (31 - FPSCR_VE));
+ fe.l |= new;
if (fe.l != curr.l)
- fesetenv_register (fe.fenv);
-
- new = __fegetexcept ();
- if (new != 0 && result == 0)
- (void) __fe_nomask_env_priv ();
+ fesetenv_control (fe.fenv);
- if ((new & excepts) != excepts)
- result = -1;
+ __TEST_AND_EXIT_NON_STOP (0ULL, fe.l);
return result;
}
diff --git a/sysdeps/powerpc/fpu/fegetexcept.c b/sysdeps/powerpc/fpu/fegetexcept.c
index 10a37f0..68a67b9 100644
--- a/sysdeps/powerpc/fpu/fegetexcept.c
+++ b/sysdeps/powerpc/fpu/fegetexcept.c
@@ -24,7 +24,7 @@ __fegetexcept (void)
{
fenv_union_t fe;
- fe.fenv = fegetenv_status ();
+ fe.fenv = fegetenv_control ();
return fenv_reg_to_exceptions (fe.l);
}
diff --git a/sysdeps/powerpc/fpu/fegetmode.c b/sysdeps/powerpc/fpu/fegetmode.c
index 466f5b7..0483128 100644
--- a/sysdeps/powerpc/fpu/fegetmode.c
+++ b/sysdeps/powerpc/fpu/fegetmode.c
@@ -21,6 +21,6 @@
int
fegetmode (femode_t *modep)
{
- *modep = fegetenv_status ();
+ *modep = fegetenv_control ();
return 0;
}
diff --git a/sysdeps/powerpc/fpu/feholdexcpt.c b/sysdeps/powerpc/fpu/feholdexcpt.c
index b16d480..f105c7b 100644
--- a/sysdeps/powerpc/fpu/feholdexcpt.c
+++ b/sysdeps/powerpc/fpu/feholdexcpt.c
@@ -18,7 +18,6 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)
int
__feholdexcept (fenv_t *envp)
@@ -35,11 +34,7 @@ __feholdexcept (fenv_t *envp)
if (new.l == old.l)
return 0;
- /* If the old env had any 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 & _FPU_MASK_ALL) != 0)
- (void)__fe_mask_env ();
+ __TEST_AND_ENTER_NON_STOP (old.l, 0ULL);
/* Put the new state in effect. */
fesetenv_register (new.fenv);
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index 9861f18..df38487 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -27,6 +27,26 @@ extern const fenv_t *__fe_nomask_env_priv (void);
extern const fenv_t *__fe_mask_env (void) attribute_hidden;
+/* If the old env had any enabled 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. */
+#define __TEST_AND_ENTER_NON_STOP(old, new) \
+ do { \
+ if (((old) & FPSCR_ENABLES_MASK) != 0 && ((new) & FPSCR_ENABLES_MASK) == 0) \
+ (void) __fe_mask_env (); \
+ } while (0)
+
+/* If the old env has no enabled 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. */
+#define __TEST_AND_EXIT_NON_STOP(old, new) \
+ do { \
+ if (((old) & FPSCR_ENABLES_MASK) == 0 && ((new) & FPSCR_ENABLES_MASK) != 0) \
+ (void) __fe_nomask_env_priv (); \
+ } while (0)
+
/* The sticky bits in the FPSCR indicating exceptions have occurred. */
#define FPSCR_STICKY_BITS ((FE_ALL_EXCEPT | FE_ALL_INVALID) & ~FE_INVALID)
@@ -35,9 +55,12 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
#define fegetenv_register() __builtin_mffs()
/* Equivalent to fegetenv_register, but only returns bits for
- status, exception enables, and mode. */
-
-#define fegetenv_status_ISA300() \
+ status, exception enables, and mode.
+ Nicely, it turns out that the 'mffsl' instruction will decode to
+ 'mffs' on architectures older than "power9" because the additional
+ bits set for 'mffsl' are "don't care" for 'mffs'. 'mffs' is a superset
+ of 'mffsl'. */
+#define fegetenv_control() \
({register double __fr; \
__asm__ __volatile__ ( \
".machine push; .machine \"power9\"; mffsl %0; .machine pop" \
@@ -45,16 +68,36 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
__fr; \
})
+#define __fe_mffscrn(rn) \
+ ({register fenv_union_t __fr; \
+ if (__builtin_constant_p (rn)) \
+ __asm__ __volatile__ ( \
+ ".machine push; .machine \"power9\"; mffscrni %0,%1; .machine pop" \
+ : "=f" (__fr.fenv) : "i" (rn)); \
+ else \
+ { \
+ __fr.l = (rn); \
+ __asm__ __volatile__ ( \
+ ".machine push; .machine \"power9\"; mffscrn %0,%1; .machine pop" \
+ : "=f" (__fr.fenv) : "f" (__fr.fenv)); \
+ } \
+ __fr.fenv; \
+ })
+
+/* Like fegetenv_control, but also sets the rounding mode. */
#ifdef _ARCH_PWR9
-# define fegetenv_status() fegetenv_status_ISA300()
-#elif defined __BUILTIN_CPU_SUPPORTS__
-# define fegetenv_status() \
- (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \
- ? fegetenv_status_ISA300() \
- : fegetenv_register() \
- )
+#define fegetenv_and_set_rn(rn) __fe_mffscrn (rn)
#else
-# define fegetenv_status() fegetenv_register ()
+/* 'mffscrn' will decode to 'mffs' on ARCH < 3_00, which is still necessary
+ but not sufficient, because it does not set the rounding mode.
+ Explicitly set the rounding mode when 'mffscrn' actually doesn't. */
+#define fegetenv_and_set_rn(rn) \
+ ({register fenv_union_t __fr; \
+ __fr.fenv = __fe_mffscrn (rn); \
+ if (__glibc_unlikely (!(GLRO(dl_hwcap2) & PPC_FEATURE2_ARCH_3_00))) \
+ __fesetround_inline (rn); \
+ __fr.fenv; \
+ })
#endif
/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */
@@ -70,6 +113,11 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
__builtin_mtfsf (0xff, d); \
} while(0)
+/* Set the last 2 nibbles of the FPSCR, which contain the
+ exception enables and the rounding mode.
+ 'fegetenv_control' retrieves these bits by reading the FPSCR. */
+#define fesetenv_control(env) __builtin_mtfsf (0b00000011, (env));
+
/* This very handy macro:
- Sets the rounding mode to 'round to nearest';
- Sets the processor into IEEE mode; and
@@ -100,7 +148,12 @@ typedef union
static inline int
__fesetround_inline (int round)
{
- if ((unsigned int) round < 2)
+#ifdef _ARCH_PWR9
+ __fe_mffscrn (round);
+#else
+ if (__glibc_likely (GLRO(dl_hwcap2) & PPC_FEATURE2_ARCH_3_00))
+ __fe_mffscrn (round);
+ else if ((unsigned int) round < 2)
{
asm volatile ("mtfsb0 30");
if ((unsigned int) round == 0)
@@ -116,7 +169,7 @@ __fesetround_inline (int round)
else
asm volatile ("mtfsb1 31");
}
-
+#endif
return 0;
}
@@ -125,63 +178,125 @@ __fesetround_inline (int round)
static inline void
__fesetround_inline_nocheck (const int round)
{
- asm volatile ("mtfsfi 7,%0" : : "i" (round));
+#ifdef _ARCH_PWR9
+ __fe_mffscrn (round);
+#else
+ if (__glibc_likely (GLRO(dl_hwcap2) & PPC_FEATURE2_ARCH_3_00))
+ __fe_mffscrn (round);
+ else
+ asm volatile ("mtfsfi 7,%0" : : "i" (round));
+#endif
}
+#define FPSCR_MASK(bit) (1 << (31 - (bit)))
+
/* Definitions of all the FPSCR bit numbers */
enum {
FPSCR_FX = 0, /* exception summary */
+#define FPSCR_FX_MASK (FPSCR_MASK (FPSCR_FX))
FPSCR_FEX, /* enabled exception summary */
+#define FPSCR_FEX_MASK (FPSCR_MASK FPSCR_FEX))
FPSCR_VX, /* invalid operation summary */
+#define FPSCR_VX_MASK (FPSCR_MASK (FPSCR_VX))
FPSCR_OX, /* overflow */
+#define FPSCR_OX_MASK (FPSCR_MASK (FPSCR_OX))
FPSCR_UX, /* underflow */
+#define FPSCR_UX_MASK (FPSCR_MASK (FPSCR_UX))
FPSCR_ZX, /* zero divide */
+#define FPSCR_ZX_MASK (FPSCR_MASK (FPSCR_ZX))
FPSCR_XX, /* inexact */
+#define FPSCR_XX_MASK (FPSCR_MASK (FPSCR_XX))
FPSCR_VXSNAN, /* invalid operation for sNaN */
+#define FPSCR_VXSNAN_MASK (FPSCR_MASK (FPSCR_VXSNAN))
FPSCR_VXISI, /* invalid operation for Inf-Inf */
+#define FPSCR_VXISI_MASK (FPSCR_MASK (FPSCR_VXISI))
FPSCR_VXIDI, /* invalid operation for Inf/Inf */
+#define FPSCR_VXIDI_MASK (FPSCR_MASK (FPSCR_VXIDI))
FPSCR_VXZDZ, /* invalid operation for 0/0 */
+#define FPSCR_VXZDZ_MASK (FPSCR_MASK (FPSCR_VXZDZ))
FPSCR_VXIMZ, /* invalid operation for Inf*0 */
+#define FPSCR_VXIMZ_MASK (FPSCR_MASK (FPSCR_VXIMZ))
FPSCR_VXVC, /* invalid operation for invalid compare */
+#define FPSCR_VXVC_MASK (FPSCR_MASK (FPSCR_VXVC))
FPSCR_FR, /* fraction rounded [fraction was incremented by round] */
+#define FPSCR_FR_MASK (FPSCR_MASK (FPSCR_FR))
FPSCR_FI, /* fraction inexact */
+#define FPSCR_FI_MASK (FPSCR_MASK (FPSCR_FI))
FPSCR_FPRF_C, /* result class descriptor */
+#define FPSCR_FPRF_C_MASK (FPSCR_MASK (FPSCR_FPRF_C))
FPSCR_FPRF_FL, /* result less than (usually, less than 0) */
+#define FPSCR_FPRF_FL_MASK (FPSCR_MASK (FPSCR_FPRF_FL))
FPSCR_FPRF_FG, /* result greater than */
+#define FPSCR_FPRF_FG_MASK (FPSCR_MASK (FPSCR_FPRF_FG))
FPSCR_FPRF_FE, /* result equal to */
+#define FPSCR_FPRF_FE_MASK (FPSCR_MASK (FPSCR_FPRF_FE))
FPSCR_FPRF_FU, /* result unordered */
+#define FPSCR_FPRF_FU_MASK (FPSCR_MASK (FPSCR_FPRF_FU))
FPSCR_20, /* reserved */
FPSCR_VXSOFT, /* invalid operation set by software */
+#define FPSCR_VXSOFT_MASK (FPSCR_MASK (FPSCR_VXSOFT))
FPSCR_VXSQRT, /* invalid operation for square root */
+#define FPSCR_VXSQRT_MASK (FPSCR_MASK (FPSCR_VXSQRT))
FPSCR_VXCVI, /* invalid operation for invalid integer convert */
+#define FPSCR_VXCVI_MASK (FPSCR_MASK (FPSCR_VXCVI))
FPSCR_VE, /* invalid operation exception enable */
+#define FPSCR_VE_MASK (FPSCR_MASK (FPSCR_VE))
FPSCR_OE, /* overflow exception enable */
+#define FPSCR_OE_MASK (FPSCR_MASK (FPSCR_OE))
FPSCR_UE, /* underflow exception enable */
+#define FPSCR_UE_MASK (FPSCR_MASK (FPSCR_UE))
FPSCR_ZE, /* zero divide exception enable */
+#define FPSCR_ZE_MASK (FPSCR_MASK (FPSCR_ZE))
FPSCR_XE, /* inexact exception enable */
+#define FPSCR_XE_MASK (FPSCR_MASK (FPSCR_XE))
#ifdef _ARCH_PWR6
FPSCR_29, /* Reserved in ISA 2.05 */
+#define FPSCR_NI_MASK (FPSCR_MASK (FPSCR_29))
#else
- FPSCR_NI /* non-IEEE mode (typically, no denormalised numbers) */
+ FPSCR_NI, /* non-IEEE mode (typically, no denormalised numbers) */
+#define FPSCR_NI_MASK (FPSCR_MASK (FPSCR_NI))
#endif /* _ARCH_PWR6 */
/* the remaining two least-significant bits keep the rounding mode */
+ FPSCR_RN_hi,
+#define FPSCR_RN_hi_MASK (FPSCR_MASK (FPSCR_RN_hi))
+ FPSCR_RN_lo
+#define FPSCR_RN_lo_MASK (FPSCR_MASK (FPSCR_RN_lo))
};
+#define FPSCR_RN_MASK (FPSCR_RN_hi_MASK|FPSCR_RN_lo_MASK)
+#define FPSCR_ENABLES_MASK \
+ (FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK)
+#define FPSCR_BASIC_EXCEPTIONS_MASK \
+ (FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK)
+#define FPSCR_EXCEPTIONS_MASK (FPSCR_BASIC_EXCEPTIONS_MASK| \
+ FPSCR_VXSNAN_MASK|FPSCR_VXISI_MASK|FPSCR_VXIDI_MASK|FPSCR_VXZDZ_MASK| \
+ FPSCR_VXIMZ_MASK|FPSCR_VXVC_MASK|FPSCR_VXSOFT_MASK|FPSCR_VXSQRT_MASK| \
+ FPSCR_VXCVI_MASK)
+#define FPSCR_FPRF_MASK \
+ (FPSCR_FPRF_C_MASK|FPSCR_FPRF_FL_MASK|FPSCR_FPRF_FG_MASK| \
+ FPSCR_FPRF_FE_MASK|FPSCR_FPRF_FU_MASK)
+#define FPSCR_CONTROL_MASK (FPSCR_ENABLES_MASK|FPSCR_NI_MASK|FPSCR_RN_MASK)
+#define FPSCR_STATUS_MASK (FPSCR_FR_MASK|FPSCR_FI_MASK|FPSCR_FPRF_MASK)
+
+/* The bits in the FENV(1) ABI for exceptions correspond one-to-one with bits
+ in the FPSCR, albeit shifted to different but corresponding locations.
+ Similarly, the exception indicator bits in the FPSCR correspond one-to-one
+ with the exception enable bits. It is thus possible to map the FENV(1)
+ exceptions directly to the FPSCR enables with a simple mask and shift,
+ and vice versa. */
+#define FPSCR_EXCEPT_TO_ENABLE_SHIFT 22
+
static inline int
fenv_reg_to_exceptions (unsigned long long l)
{
- int result = 0;
- if (l & (1 << (31 - FPSCR_XE)))
- result |= FE_INEXACT;
- if (l & (1 << (31 - FPSCR_ZE)))
- result |= FE_DIVBYZERO;
- if (l & (1 << (31 - FPSCR_UE)))
- result |= FE_UNDERFLOW;
- if (l & (1 << (31 - FPSCR_OE)))
- result |= FE_OVERFLOW;
- if (l & (1 << (31 - FPSCR_VE)))
- result |= FE_INVALID;
- return result;
+ return (((int)l) & FPSCR_ENABLES_MASK) << FPSCR_EXCEPT_TO_ENABLE_SHIFT;
+}
+
+static inline unsigned long long
+fenv_exceptions_to_reg (int excepts)
+{
+ return (unsigned long long)
+ (excepts & FE_ALL_EXCEPT) >> FPSCR_EXCEPT_TO_ENABLE_SHIFT;
}
#ifdef _ARCH_PWR6
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index 8c126f9..0eb1b08 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -23,73 +23,31 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-/* Mask for the exception enable bits. */
-#define _FPU_ALL_TRAPS (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM \
- | _FPU_MASK_XM | _FPU_MASK_IM)
-
-/* Mask the rounding mode bits. */
-#define _FPU_MASK_RN 0xfffffffffffffffcLL
-
-/* Mask everything but the rounding modes and non-IEEE arithmetic flags. */
-#define _FPU_MASK_NOT_RN_NI 0xffffffff00000807LL
-
-/* Mask restore rounding mode and exception enabled. */
-#define _FPU_MASK_TRAPS_RN 0xffffffffffffff00LL
-
-/* Mask FP result flags, preserve fraction rounded/inexact bits. */
-#define _FPU_MASK_FRAC_INEX_RET_CC 0xfffffffffff80fffLL
+#ifdef _ARCH_PWR8
+/* There is no performance advantage to non-stop mode. */
+/* The odd syntax here is to innocuously reference the given variables
+ to prevent warnings about unused variables. */
+#define __TEST_AND_BEGIN_NON_STOP(old, new) do {} while ((old) * (new) * 0 != 0)
+#define __TEST_AND_END_NON_STOP(old, new) do {} while ((old) * (new) * 0 != 0)
+#else
+#define __TEST_AND_BEGIN_NON_STOP __TEST_AND_ENTER_NON_STOP
+#define __TEST_AND_END_NON_STOP __TEST_AND_EXIT_NON_STOP
+#endif
static __always_inline void
-__libc_feholdbits_ppc (fenv_t *envp, unsigned long long mask,
- unsigned long long bits)
+libc_feholdexcept_setround_ppc (fenv_t *envp, int r)
{
fenv_union_t old, new;
old.fenv = *envp = fegetenv_register ();
- new.l = (old.l & mask) | bits;
-
- /* If the old env had any 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 & _FPU_ALL_TRAPS) != 0)
- (void) __fe_mask_env ();
+ __TEST_AND_BEGIN_NON_STOP (old.l, 0ULL);
+ /* Clear everything and set the rounding mode. */
+ new.l = r;
fesetenv_register (new.fenv);
}
-static __always_inline void
-libc_feholdexcept_ppc (fenv_t *envp)
-{
- __libc_feholdbits_ppc (envp, _FPU_MASK_NOT_RN_NI, 0LL);
-}
-
-static __always_inline void
-libc_feholdexcept_setround_ppc (fenv_t *envp, int r)
-{
- __libc_feholdbits_ppc (envp, _FPU_MASK_NOT_RN_NI & _FPU_MASK_RN, r);
-}
-
-static __always_inline void
-libc_fesetround_ppc (int r)
-{
- __fesetround_inline (r);
-}
-
-static __always_inline int
-libc_fetestexcept_ppc (int e)
-{
- fenv_union_t u;
- u.fenv = fegetenv_register ();
- return u.l & e;
-}
-
-static __always_inline void
-libc_feholdsetround_ppc (fenv_t *e, int r)
-{
- __libc_feholdbits_ppc (e, _FPU_MASK_TRAPS_RN, r);
-}
-
static __always_inline unsigned long long
__libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask,
unsigned long long new_mask)
@@ -102,22 +60,23 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask,
/* Merge bits while masking unwanted bits from new and old env. */
new.l = (old.l & old_mask) | (new.l & new_mask);
- /* If the old env has no enabled 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 & _FPU_ALL_TRAPS) == 0 && (new.l & _FPU_ALL_TRAPS) != 0)
- (void) __fe_nomask_env_priv ();
-
- /* If the old env had any enabled 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 & _FPU_ALL_TRAPS) != 0 && (new.l & _FPU_ALL_TRAPS) == 0)
- (void) __fe_mask_env ();
-
- /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
- fesetenv_register (new.fenv);
+ __TEST_AND_END_NON_STOP (old.l, new.l);
+ __TEST_AND_BEGIN_NON_STOP (old.l, new.l);
+
+ /* If requesting to keep status, replace control, and merge exceptions,
+ and exceptions haven't changed, we can just set new control instead
+ of the whole FPSCR. */
+ if ((old_mask & (FPSCR_CONTROL_MASK|FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK))
+ == (FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK) &&
+ (new_mask & (FPSCR_CONTROL_MASK|FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK))
+ == (FPSCR_CONTROL_MASK|FPSCR_EXCEPTIONS_MASK) &&
+ (old.l & FPSCR_EXCEPTIONS_MASK) == (new.l & FPSCR_EXCEPTIONS_MASK))
+ {
+ fesetenv_control (new.fenv);
+ }
+ else
+ /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
+ fesetenv_register (new.fenv);
return old.l;
}
@@ -132,14 +91,15 @@ libc_fesetenv_ppc (const fenv_t *envp)
static __always_inline void
libc_feresetround_ppc (fenv_t *envp)
{
- __libc_femergeenv_ppc (envp, _FPU_MASK_TRAPS_RN, _FPU_MASK_FRAC_INEX_RET_CC);
+ fenv_union_t new = { .fenv = *envp };
+ fegetenv_and_set_rn (new.l & FPSCR_RN_MASK);
}
static __always_inline int
libc_feupdateenv_test_ppc (fenv_t *envp, int ex)
{
- return __libc_femergeenv_ppc (envp, _FPU_MASK_TRAPS_RN,
- _FPU_MASK_FRAC_INEX_RET_CC) & ex;
+ return __libc_femergeenv_ppc (envp, ~FPSCR_CONTROL_MASK,
+ ~FPSCR_STATUS_MASK) & ex;
}
static __always_inline void
@@ -174,18 +134,26 @@ libc_feupdateenv_ppc (fenv_t *e)
static __always_inline void
libc_feholdsetround_ppc_ctx (struct rm_ctx *ctx, int r)
{
+ fenv_union_t old;
+
+ ctx->env = old.fenv = fegetenv_and_set_rn (r);
+ ctx->updated_status = (r != (old.l & FPSCR_RN_MASK));
+}
+
+static __always_inline void
+libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r)
+{
fenv_union_t old, new;
old.fenv = fegetenv_register ();
- new.l = (old.l & _FPU_MASK_TRAPS_RN) | r;
+ new.l = (old.l & ~(FPSCR_ENABLES_MASK|FPSCR_RN_MASK)) | r;
ctx->env = old.fenv;
if (__glibc_unlikely (new.l != old.l))
{
- if ((old.l & _FPU_ALL_TRAPS) != 0)
- (void) __fe_mask_env ();
- fesetenv_register (new.fenv);
+ __TEST_AND_BEGIN_NON_STOP (old.l, 0ULL);
+ fesetenv_control (new.fenv);
ctx->updated_status = true;
}
else
@@ -218,6 +186,9 @@ libc_feresetround_ppc_ctx (struct rm_ctx *ctx)
#define libc_feholdsetround_ctx libc_feholdsetround_ppc_ctx
#define libc_feholdsetroundf_ctx libc_feholdsetround_ppc_ctx
#define libc_feholdsetroundl_ctx libc_feholdsetround_ppc_ctx
+#define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_ppc_ctx
+#define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ppc_ctx
+#define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ppc_ctx
#define libc_feresetround_ctx libc_feresetround_ppc_ctx
#define libc_feresetroundf_ctx libc_feresetround_ppc_ctx
#define libc_feresetroundl_ctx libc_feresetround_ppc_ctx
diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c
index 009a4f0..7e0176b 100644
--- a/sysdeps/powerpc/fpu/fesetenv.c
+++ b/sysdeps/powerpc/fpu/fesetenv.c
@@ -19,8 +19,6 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)
-
int
__fesetenv (const fenv_t *envp)
{
@@ -28,25 +26,12 @@ __fesetenv (const fenv_t *envp)
/* get the currently set exceptions. */
new.fenv = *envp;
- old.fenv = fegetenv_register ();
- if (old.l == new.l)
- return 0;
-
- /* If the old env has no enabled 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 & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0)
- (void) __fe_nomask_env_priv ();
-
- /* If the old env had any enabled 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 & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0)
- (void)__fe_mask_env ();
-
- fesetenv_register (*envp);
+ old.fenv = fegetenv_control ();
+
+ __TEST_AND_EXIT_NON_STOP (old.l, new.l);
+ __TEST_AND_ENTER_NON_STOP (old.l, new.l);
+
+ fesetenv_register (new.fenv);
/* Success. */
return 0;
diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c
index 4f4f71a..72acdaf 100644
--- a/sysdeps/powerpc/fpu/fesetmode.c
+++ b/sysdeps/powerpc/fpu/fesetmode.c
@@ -19,11 +19,6 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM \
- | _FPU_MASK_XM | _FPU_MASK_IM)
-
-#define FPU_STATUS 0xbffff700ULL
-
int
fesetmode (const femode_t *modep)
{
@@ -32,18 +27,15 @@ fesetmode (const femode_t *modep)
/* Logic regarding enabled exceptions as in fesetenv. */
new.fenv = *modep;
- old.fenv = fegetenv_register ();
- new.l = (new.l & ~FPU_STATUS) | (old.l & FPU_STATUS);
+ old.fenv = fegetenv_control ();
+ new.l = (new.l & ~FPSCR_STATUS_MASK) | (old.l & FPSCR_STATUS_MASK);
if (old.l == new.l)
return 0;
- if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0)
- (void) __fe_nomask_env_priv ();
-
- if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0)
- (void) __fe_mask_env ();
+ __TEST_AND_EXIT_NON_STOP (old.l, new.l);
+ __TEST_AND_ENTER_NON_STOP (old.l, new.l);
- fesetenv_register (new.fenv);
+ fesetenv_control (new.fenv);
return 0;
}
diff --git a/sysdeps/powerpc/fpu/feupdateenv.c b/sysdeps/powerpc/fpu/feupdateenv.c
index 39b08e7..ff4d902 100644
--- a/sysdeps/powerpc/fpu/feupdateenv.c
+++ b/sysdeps/powerpc/fpu/feupdateenv.c
@@ -20,8 +20,6 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)
-
int
__feupdateenv (const fenv_t *envp)
{
@@ -36,19 +34,8 @@ __feupdateenv (const fenv_t *envp)
unchanged. */
new.l = (old.l & 0xffffffff1fffff00LL) | (new.l & 0x1ff80fff);
- /* If the old env has no enabled 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 & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0)
- (void) __fe_nomask_env_priv ();
-
- /* If the old env had any enabled 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 & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0)
- (void)__fe_mask_env ();
+ __TEST_AND_EXIT_NON_STOP (old.l, new.l);
+ __TEST_AND_ENTER_NON_STOP (old.l, new.l);
/* Atomically enable and raise (if appropriate) exceptions set in `new'. */
fesetenv_register (new.fenv);