diff options
-rw-r--r-- | ChangeLog | 168 | ||||
-rw-r--r-- | NEWS | 13 | ||||
-rw-r--r-- | elf/get-dynamic-info.h | 5 | ||||
-rw-r--r-- | iconv/Makefile | 2 | ||||
-rw-r--r-- | iconv/gconv_simple.c | 16 | ||||
-rw-r--r-- | iconv/tst-iconv8.c | 50 | ||||
-rw-r--r-- | iconv/tst-iconv_prog.sh | 284 | ||||
-rw-r--r-- | iconvdata/ibm1364.c | 14 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fedisblxcpt.c | 26 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/feenablxcpt.c | 27 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fegetexcept.c | 2 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fegetmode.c | 2 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/feholdexcpt.c | 7 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fenv_libc.h | 169 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fenv_private.h | 129 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fesetenv.c | 27 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/fesetmode.c | 18 | ||||
-rw-r--r-- | sysdeps/powerpc/fpu/feupdateenv.c | 17 |
18 files changed, 749 insertions, 227 deletions
@@ -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". @@ -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); |