]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
MIPS: IEEE 754-2008 NaN encoding support
authorMaciej W. Rozycki <macro@codesourcery.com>
Wed, 18 Sep 2013 20:04:27 +0000 (21:04 +0100)
committerMaciej W. Rozycki <macro@codesourcery.com>
Wed, 18 Sep 2013 20:33:50 +0000 (21:33 +0100)
It has been a long practice for software using IEEE 754 floating-point
arithmetic run on MIPS processors to use an encoding of Not-a-Number
(NaN) data different to one used by software run on other processors.
And as of IEEE 754-2008 revision [1] this encoding does not follow one
recommended in the standard, as specified in section 6.2.1, where it
is stated that quiet NaNs should have the first bit (d1) of their
significand set to 1 while signalling NaNs should have that bit set to
0, but MIPS software interprets the two bits in the opposite manner.

As from revision 3.50 [2][3] the MIPS Architecture provides for
processors that support the IEEE 754-2008 preferred NaN encoding format.
As the two formats (further referred to as "legacy NaN" and "2008 NaN")
are incompatible to each other, tools have to provide support for the
two formats to help people avoid using incompatible binary modules.

The change is comprised of two functional groups of features, both of
which are required for correct support.

1. Dynamic linker support.

   To enforce the NaN encoding requirement in dynamic linking a new ELF
   file header flag has been defined.  This flag is set for 2008-NaN
   shared modules and executables and clear for legacy-NaN ones.  The
   dynamic linker silently ignores any incompatible modules it
   encounters in dependency processing.

   To avoid unnecessary processing of incompatible modules in the
   presence of a shared module cache, a set of new cache flags has been
   defined to mark 2008-NaN modules for the three ABIs supported.
   Changes to sysdeps/unix/sysv/linux/mips/readelflib.c have been made
   following an earlier code quality suggestion made here:

   http://sourceware.org/ml/libc-ports/2009-03/msg00036.html

   and are therefore a little bit more extensive than the minimum
   required.

   Finally a new name has been defined for the dynamic linker so that
   2008-NaN and legacy-NaN binaries can coexist on a single system that
   supports dual-mode operation and that a legacy dynamic linker that
   does not support verifying the 2008-NaN ELF file header flag is not
   chosen to interpret a 2008-NaN binary by accident.

2. Floating environment support.

   IEEE 754-2008 features are controlled in the Floating-Point Control
   and Status (FCSR) register and updates are needed to floating
   environment support so that the 2008-NaN flag is set correctly and
   the kernel default, inferred from the 2008-NaN ELF file header flag
   at the time an executable is loaded, respected.

As the NaN encoding format is a property of GCC code generation that is
both a user-selected GCC configuration default and can be overridden
with GCC options, code that needs to know what NaN encoding standard it
has been configured for checks for the __mips_nan2008 macro that is
defined internally by GCC whenever the 2008-NaN mode has been selected.
This mode is determined at the glibc configuration time and therefore a
few consistency checks have been added to catch cases where compilation
flags have been overridden by the user.

The 2008 NaN set of features relies on kernel support as the in-kernel
floating-point emulator needs to be aware of the NaN encoding used even
on hard-float processors and configure the FPU context according to the
value of the 2008 NaN ELF file header flag of the executable being
started.  As at this time work on kernel support is still in progress
and the relevant changes have not made their way yet to linux.org master
repository.

Therefore the minimum version supported has been artificially set to
10.0.0 so that 2008-NaN code is not accidentally run on a Linux kernel
that does not suppport it.  It is anticipated that the version is
adjusted later on to the actual initial linux.org kernel version to
support this feature.  Legacy NaN encoding support is unaffected, older
kernel versions remain supported.

[1] "IEEE Standard for Floating-Point Arithmetic", IEEE Computer
    Society, IEEE Std 754-2008, 29 August 2008

[2] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS32 Architecture", MIPS Technologies, Inc., Document Number:
    MD00082, Revision 3.50, September 20, 2012

[3] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS64 Architecture", MIPS Technologies, Inc., Document Number:
    MD00083, Revision 3.50, September 20, 2012

20 files changed:
ChangeLog
config.h.in
elf/cache.c
elf/elf.h
ports/ChangeLog.mips
ports/sysdeps/mips/bits/nan.h
ports/sysdeps/mips/configure
ports/sysdeps/mips/configure.in
ports/sysdeps/mips/dl-machine.h
ports/sysdeps/mips/fpu_control.h
ports/sysdeps/mips/math_private.h
ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h
ports/sysdeps/mips/shlib-versions
ports/sysdeps/mips/soft-fp/sfp-machine.h
ports/sysdeps/unix/sysv/linux/mips/Makefile
ports/sysdeps/unix/sysv/linux/mips/configure
ports/sysdeps/unix/sysv/linux/mips/configure.in
ports/sysdeps/unix/sysv/linux/mips/dl-cache.h
ports/sysdeps/unix/sysv/linux/mips/readelflib.c
sysdeps/generic/ldconfig.h

index 19fcc3ca157e1a929b7983e251676a0b837d1957..ded04870829dc71959f6ef59425eb3de2d582385 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-09-18  Maciej W. Rozycki  <macro@codesourcery.com>
+
+       * config.h.in (HAVE_MIPS_NAN2008): New macro.
+       * elf/elf.h (EF_MIPS_NAN2008): Likewise.
+       * sysdeps/generic/ldconfig.h (FLAG_MIPS_LIB32_NAN2008): Likewise.
+       (FLAG_MIPS64_LIBN32_NAN2008): Likewise.
+       (FLAG_MIPS64_LIBN64_NAN2008): Likewise.
+       * elf/cache.c (print_entry): Handle the new cache flags.
+
 2013-09-18  Joseph Myers  <joseph@codesourcery.com>
            Aldy Hernandez  <aldyh@redhat.com>
 
index 30568e3af6ac2582b16201275ae418094acd6943..0ee1ec6f5698cd1a50ba3ecd79b14ce23a4ebc54 100644 (file)
 /* The pt_chown binary is being built and used by grantpt.  */
 #undef HAVE_PT_CHOWN
 
+/* ports/sysdeps/mips/configure.in  */
+/* Define if using the IEEE 754-2008 NaN encoding on the MIPS target.  */
+#undef HAVE_MIPS_NAN2008
+
 #endif
index 9bf261cd298db8baf8a4c8ca4ff5faea6c19d89d..1a43dd77654e62bdb22ab0a0abebaf69b99ba1df 100644 (file)
@@ -105,6 +105,15 @@ print_entry (const char *lib, int flag, unsigned int osversion,
     case FLAG_ARM_LIBSF:
       fputs (",soft-float", stdout);
       break;
+    case FLAG_MIPS_LIB32_NAN2008:
+      fputs (",nan2008", stdout);
+      break;
+    case FLAG_MIPS64_LIBN32_NAN2008:
+      fputs (",N32,nan2008", stdout);
+      break;
+    case FLAG_MIPS64_LIBN64_NAN2008:
+      fputs (",64bit,nan2008", stdout);
+      break;
     case 0:
       break;
     default:
index fe55c928cdcd8e7ae929f0cfc21693a16c5c414a..058c20f5bd62a489ef2d9b964be23d13110679d9 100644 (file)
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1383,6 +1383,7 @@ typedef struct
 #define EF_MIPS_64BIT_WHIRL    16
 #define EF_MIPS_ABI2           32
 #define EF_MIPS_ABI_ON32       64
+#define EF_MIPS_NAN2008        1024  /* Uses IEEE 754-2008 NaN encoding.  */
 #define EF_MIPS_ARCH           0xf0000000 /* MIPS architecture level.  */
 
 /* Legal values for MIPS architecture level.  */
index 5844bf5897856c9df5ab9f9656ceb63c1d254237..017b2c27eb4d982c7d054e66468de5d7ae149cb7 100644 (file)
@@ -1,3 +1,71 @@
+2013-09-18  Maciej W. Rozycki  <macro@codesourcery.com>
+            Thomas Schwinge  <thomas@codesourcery.com>
+
+       * sysdeps/mips/dl-machine.h (ELF_MACHINE_NAN2008): New macro.
+       (elf_machine_matches_host): Reject objects that use a different
+       NaN encoding convention.
+       * sysdeps/mips/fpu_control.h: Document IEEE 754-2008 feature
+       control bits.
+       (_FPU_ABS2008, _FPU_NAN2008): New macros.
+       (_FPU_RESERVED): Clear bits #20 and #19.
+       (_FPU_DEFAULT) [__mips_nan2008]: Set bit #18.
+       (_FPU_IEEE) [__mips_nan2008]: Likewise.
+       * sysdeps/mips/math_private.h [__mips_nan2008]
+       (HIGH_ORDER_BIT_IS_SET_FOR_SNAN): Don't define.
+       * sysdeps/mips/bits/nan.h [__mips_nan2008] (__qnan_bytes): Define
+       appropriately.
+       * sysdeps/mips/mips64/soft-fp/sfp-machine.h [__mips_nan2008]
+       (_FP_NANFRAC_S, _FP_NANFRAC_D, _FP_NANFRAC_Q): Define 2008-NaN
+       payloads.
+       (_FP_QNANNEGATEDP): Set to 0.
+       * sysdeps/mips/soft-fp/sfp-machine.h [__mips_nan2008]
+       (_FP_NANFRAC_S, _FP_NANFRAC_D, _FP_NANFRAC_Q): Define 2008-NaN
+       payloads.
+       (_FP_QNANNEGATEDP): Set to 0.
+       * sysdeps/unix/sysv/linux/mips/dl-cache.h (_DL_CACHE_DEFAULT_ID):
+       Define 2008 NaN encoding values.
+       * sysdeps/unix/sysv/linux/mips/readelflib.c (process_elf_file):
+       Handle 2008-NaN libraries.
+       * sysdeps/mips/shlib-versions [HAVE_MIPS_NAN2008]: Set
+       ld=ld-linux-mipsn8.so.1.
+       * sysdeps/mips/configure.in: Define HAVE_MIPS_NAN2008 if the
+       2008 NaN encoding is used.
+       * sysdeps/unix/sysv/linux/mips/Makefile (abi-variants): Add
+       2008-NaN ABI variants.
+       (abi-o32_soft-options, abi-o32_soft-condition): Update with the
+       __mips_nan2008 macro.
+       (abi-o32_hard-options, abi-o32_hard-condition): Likewise.
+       (abi-n32_soft-options, abi-n32_soft-condition): Likewise.
+       (abi-n32_hard-options, abi-n32_hard-condition): Likewise.
+       (abi-n64_soft-options, abi-n64_soft-condition): Likewise.
+       (abi-n64_hard-options, abi-n64_hard-condition): Likewise.
+       (abi-o32_soft-ld-soname, abi-o32_hard-ld-soname): New macros.
+       (abi-n32_soft-ld-soname, abi-n32_hard-ld-soname): Likewise.
+       (abi-n64_soft-ld-soname, abi-n64_hard-ld-soname): Likewise.
+       (abi-o32_soft_2008-options): Likewise.
+       (abi-o32_soft_2008-condition): Likewise.
+       (abi-o32_hard_2008-options): Likewise.
+       (abi-o32_hard_2008-condition): Likewise.
+       (abi-n32_soft_2008-options): Likewise.
+       (abi-n32_soft_2008-condition): Likewise.
+       (abi-n32_hard_2008-options): Likewise.
+       (abi-n32_hard_2008-condition): Likewise.
+       (abi-n64_soft_2008-options): Likewise.
+       (abi-n64_soft_2008-condition): Likewise.
+       (abi-n64_hard_2008-options): Likewise.
+       (abi-n64_hard_2008-condition): Likewise.
+       (abi-o32_soft_2008-ld-soname): Likewise.
+       (abi-o32_hard_2008-ld-soname): Likewise.
+       (abi-n32_soft_2008-ld-soname): Likewise.
+       (abi-n32_hard_2008-ld-soname): Likewise.
+       (abi-n64_soft_2008-ld-soname): Likewise.
+       (abi-n64_hard_2008-ld-soname): Likewise.
+       * sysdeps/unix/sysv/linux/mips/configure.in: Include the NaN
+       encoding selection in default-abi.  Set arch_minimum_kernel to
+       10.0.0 if 2008 NaN encoding is used.
+       * sysdeps/mips/configure: Regenerate.
+       * sysdeps/unix/sysv/linux/mips/configure: Regenerate.
+
 2013-08-30   Ondřej Bílka  <neleai@seznam.cz>
 
        * sysdeps/mips/memcpy.S: Fix then/than typos.
index 80f7866a97d793df021c7a260e1f8ade40b49428..c322523275fba65bb751e15ae5c03b336022cb02 100644 (file)
 
 
 /* IEEE Not A Number.  */
-/* Note that MIPS has the qNaN and sNaN patterns reversed compared to most
-   other architectures.  IEEE 754-1985 left the definition of this open to
-   implementations, and for MIPS the top bit of the mantissa must be SET to
-   indicate a sNaN.  */
+/* In legacy-NaN mode MIPS has the qNaN and sNaN patterns reversed
+   compared to most other architectures.  IEEE 754-1985 left the
+   definition of this open to implementations, and for MIPS the top bit
+   of the mantissa must be SET to indicate a sNaN.  In 2008-NaN mode
+   MIPS aligned to IEEE 754-2008.  */
 
 #if __GNUC_PREREQ(3,3)
 
@@ -33,6 +34,8 @@
 
 #elif defined __GNUC__
 
+/* No 2008-NaN mode support in any GCC version before 4.9.  */
+
 # define NAN \
   (__extension__                                                             \
    ((union { unsigned __l __attribute__ ((__mode__ (__SI__))); float __d; })  \
 # include <endian.h>
 
 # if __BYTE_ORDER == __BIG_ENDIAN
-#  define __qnan_bytes         { 0x7f, 0xbf, 0xff, 0xff }
+#  ifdef __mips_nan2008
+#   define __qnan_bytes                { 0x7f, 0xc0, 0, 0 }
+#  else
+#   define __qnan_bytes                { 0x7f, 0xbf, 0xff, 0xff }
+#  endif
 # endif
 # if __BYTE_ORDER == __LITTLE_ENDIAN
-#  define __qnan_bytes         { 0xff, 0xff, 0xbf, 0x7f }
+#  ifdef __mips_nan2008
+#   define __qnan_bytes                { 0, 0, 0xc0, 0x7f }
+#  else
+#   define __qnan_bytes                { 0xff, 0xff, 0xbf, 0x7f }
+#  endif
 # endif
 
 static union { unsigned char __c[4]; float __d; } __qnan_union
index 898e4c3f208cfceea59d43fe683464045bfa39c2..de8092c970a19f32f63891058ae40fd6e898ac16 100644 (file)
@@ -1,3 +1,163 @@
 # This file is generated from configure.in by Autoconf.  DO NOT EDIT!
  # Local configure fragment for sysdeps/mips.
 
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler is using the 2008 NaN encoding" >&5
+$as_echo_n "checking whether the compiler is using the 2008 NaN encoding... " >&6; }
+if ${libc_cv_mips_nan2008+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+dnl
+#ifdef __mips_nan2008
+yes
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then :
+  libc_cv_mips_nan2008=yes
+else
+  libc_cv_mips_nan2008=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mips_nan2008" >&5
+$as_echo "$libc_cv_mips_nan2008" >&6; }
+if test x$libc_cv_mips_nan2008 = xyes; then
+  $as_echo "#define HAVE_MIPS_NAN2008 1" >>confdefs.h
+
+fi
index be9672d8234bcb49a443674c99673af835f59695..bcbdaffd9fe3b427ec73b4a15b2968448824ca43 100644 (file)
@@ -4,3 +4,12 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
 dnl No MIPS GCC supports accessing static and hidden symbols in an
 dnl position independent way.
 dnl AC_DEFINE(PI_STATIC_AND_HIDDEN)
+
+AC_CACHE_CHECK([whether the compiler is using the 2008 NaN encoding],
+  libc_cv_mips_nan2008, [AC_EGREP_CPP(yes, [dnl
+#ifdef __mips_nan2008
+yes
+#endif], libc_cv_mips_nan2008=yes, libc_cv_mips_nan2008=no)])
+if test x$libc_cv_mips_nan2008 = xyes; then
+  AC_DEFINE(HAVE_MIPS_NAN2008)
+fi
index dae938f03959e1d557de09ea9eb078165beb3059..722c8a0ba8e78db8f2974c788bae257fdec35db0 100644 (file)
@@ -73,6 +73,16 @@ do { if ((l)->l_info[DT_MIPS (RLD_MAP)]) \
        (ElfW(Addr)) (r); \
    } while (0)
 
+#if ((defined __mips_nan2008 && !defined HAVE_MIPS_NAN2008) \
+     || (!defined __mips_nan2008 && defined HAVE_MIPS_NAN2008))
+# error "Configuration inconsistency: __mips_nan2008 != HAVE_MIPS_NAN2008, overridden CFLAGS?"
+#endif
+#ifdef __mips_nan2008
+# define ELF_MACHINE_NAN2008 EF_MIPS_NAN2008
+#else
+# define ELF_MACHINE_NAN2008 0
+#endif
+
 /* Return nonzero iff ELF header is compatible with the running host.  */
 static inline int __attribute_used__
 elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
@@ -83,6 +93,10 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
     return 0;
 #endif
 
+  /* Don't link 2008-NaN and legacy-NaN objects together.  */
+  if ((ehdr->e_flags & EF_MIPS_NAN2008) != ELF_MACHINE_NAN2008)
+    return 0;
+
   switch (ehdr->e_machine)
     {
     case EM_MIPS:
index 770cbb31d843ab661d0a674d70af0075e3dd411a..40469627a792c939f5ce5fffb957fada2486ecce 100644 (file)
@@ -29,7 +29,9 @@
  *           available for MIPS III and newer.
  * 23     -> Condition bit
  * 22-21  -> reserved for architecture implementers
- * 20-18  -> reserved (read as 0, write with 0)
+ * 20     -> reserved (read as 0, write with 0)
+ * 19     -> IEEE 754-2008 non-arithmetic ABS.fmt and NEG.fmt enable
+ * 18     -> IEEE 754-2008 recommended NaN encoding enable
  * 17     -> cause bit for unimplemented operation
  * 16     -> cause bit for invalid exception
  * 15     -> cause bit for division by zero exception
@@ -79,22 +81,33 @@ extern fpu_control_t __fpu_control;
 /* flush denormalized numbers to zero */
 #define _FPU_FLUSH_TZ   0x1000000
 
+/* IEEE 754-2008 compliance control.  */
+#define _FPU_ABS2008    0x80000
+#define _FPU_NAN2008    0x40000
+
 /* rounding control */
 #define _FPU_RC_NEAREST 0x0     /* RECOMMENDED */
 #define _FPU_RC_ZERO    0x1
 #define _FPU_RC_UP      0x2
 #define _FPU_RC_DOWN    0x3
 
-#define _FPU_RESERVED 0xfe9c0000  /* Reserved bits in cw */
+#define _FPU_RESERVED 0xfe840000  /* Reserved bits in cw, incl NAN2008.  */
 
 
 /* The fdlibm code requires strict IEEE double precision arithmetic,
    and no interrupts for exceptions, rounding to nearest.  */
+#ifdef __mips_nan2008
+# define _FPU_DEFAULT 0x00040000
+#else
+# define _FPU_DEFAULT 0x00000000
+#endif
 
-#define _FPU_DEFAULT  0x00000000
-
-/* IEEE:  same as above, but exceptions */
-#define _FPU_IEEE     0x00000F80
+/* IEEE: same as above, but exceptions.  */
+#ifdef __mips_nan2008
+# define _FPU_IEEE    0x00040F80
+#else
+# define _FPU_IEEE    0x00000F80
+#endif
 
 /* Type of the control word.  */
 typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
index f0ba4ee7064decf9f1ca6a44159c99e31f97734a..6b99957c7b464d6703ae656ef3f94a8af30d9a6d 100644 (file)
 
 #ifndef _MATH_PRIVATE_H
 
+#ifdef __mips_nan2008
+/* MIPS aligned to IEEE 754-2008.  */
+#else
 /* One of the few architectures where the meaning of the quiet/signaling bit is
    inverse to IEEE 754-2008 (as well as common practice for IEEE 754-1985).  */
-#define HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+# define HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+#endif
 
 #include_next <math_private.h>
 
index 9cfd6fbb7b73dfdd44959105d61ef0b287f5fdbb..5be50927d0698d5b92c05b4e4bb575ccff7d05d9 100644 (file)
 #define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
 #define _FP_DIV_MEAT_Q(R,X,Y)  _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
 
-#define _FP_NANFRAC_S          (_FP_QNANBIT_S - 1)
-#define _FP_NANFRAC_D          (_FP_QNANBIT_D - 1)
-#define _FP_NANFRAC_Q          (_FP_QNANBIT_Q - 1), -1
+#ifdef __mips_nan2008
+# define _FP_NANFRAC_S         ((_FP_QNANBIT_S << 1) - 1)
+# define _FP_NANFRAC_D         ((_FP_QNANBIT_D << 1) - 1)
+# define _FP_NANFRAC_Q         ((_FP_QNANBIT_Q << 1) - 1), -1
+#else
+# define _FP_NANFRAC_S         (_FP_QNANBIT_S - 1)
+# define _FP_NANFRAC_D         (_FP_QNANBIT_D - 1)
+# define _FP_NANFRAC_Q         (_FP_QNANBIT_Q - 1), -1
+#endif
 #define _FP_NANSIGN_S          0
 #define _FP_NANSIGN_D          0
 #define _FP_NANSIGN_Q          0
 
 #define _FP_KEEPNANFRACP 1
-#define _FP_QNANNEGATEDP 1
+#ifdef __mips_nan2008
+# define _FP_QNANNEGATEDP 0
+#else
+# define _FP_QNANNEGATEDP 1
+#endif
 
 /* From my experiments it seems X is chosen unless one of the
    NaNs is sNaN,  in which case the result is NANSIGN/NANFRAC.  */
index 780939369b213fd44483718f9a4bdca229d14356..b153732c27f285f4c79d0b9269f9133ac7fa4e81 100644 (file)
@@ -3,7 +3,11 @@ mips.*-.*-linux.*      libm=6                  GLIBC_2.0 GLIBC_2.2
 # Working mips versions were never released between 2.0 and 2.2.
 mips.*-.*-linux.*      libc=6                  GLIBC_2.0 GLIBC_2.2
 
+%ifdef HAVE_MIPS_NAN2008
+mips.*-.*-linux.*      ld=ld-linux-mipsn8.so.1 GLIBC_2.0 GLIBC_2.2
+%else
 mips.*-.*-linux.*      ld=ld.so.1              GLIBC_2.0 GLIBC_2.2
+%endif
 mips.*-.*-linux.*      libdl=2                 GLIBC_2.0 GLIBC_2.2
 
 mips.*-.*-linux.*      libresolv=2             GLIBC_2.0 GLIBC_2.2
index a60bef7665a7504b8667d3127732fc0d0a081821..fff3b3c613882e94d263678f3f320254a5ae6a28 100644 (file)
 #define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_2_udiv(D,R,X,Y)
 #define _FP_DIV_MEAT_Q(R,X,Y)  _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
 
-#define _FP_NANFRAC_S          (_FP_QNANBIT_S - 1)
-#define _FP_NANFRAC_D          (_FP_QNANBIT_D - 1), -1
-#define _FP_NANFRAC_Q          (_FP_QNANBIT_Q - 1), -1, -1, -1
+#ifdef __mips_nan2008
+# define _FP_NANFRAC_S         ((_FP_QNANBIT_S << 1) - 1)
+# define _FP_NANFRAC_D         ((_FP_QNANBIT_D << 1) - 1), -1
+# define _FP_NANFRAC_Q         ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#else
+# define _FP_NANFRAC_S         (_FP_QNANBIT_S - 1)
+# define _FP_NANFRAC_D         (_FP_QNANBIT_D - 1), -1
+# define _FP_NANFRAC_Q         (_FP_QNANBIT_Q - 1), -1, -1, -1
+#endif
 #define _FP_NANSIGN_S          0
 #define _FP_NANSIGN_D          0
 #define _FP_NANSIGN_Q          0
 
 #define _FP_KEEPNANFRACP 1
-#define _FP_QNANNEGATEDP 1
+#ifdef __mips_nan2008
+# define _FP_QNANNEGATEDP 0
+#else
+# define _FP_QNANNEGATEDP 1
+#endif
 
 /* From my experiments it seems X is chosen unless one of the
    NaNs is sNaN,  in which case the result is NANSIGN/NANFRAC.  */
index 1e54036bfe94a62b55d221c29a412a30c391eb77..9070b775c4ffb45f73dc469c7d942a6e5d65b90c 100644 (file)
@@ -8,7 +8,9 @@ sysdep_routines += cachectl cacheflush sysmips _test_and_set
 sysdep_headers += sys/cachectl.h sys/sysmips.h sys/tas.h
 endif
 
-abi-variants := o32_soft o32_hard n32_soft n32_hard n64_soft n64_hard
+abi-variants := o32_soft o32_hard o32_soft_2008 o32_hard_2008
+abi-variants += n32_soft n32_hard n32_soft_2008 n32_hard_2008
+abi-variants += n64_soft n64_hard n64_soft_2008 n64_hard_2008
 
 ifeq (,$(filter $(default-abi),$(abi-variants)))
 Unknown ABI, must be one of $(abi-variants)
@@ -18,29 +20,89 @@ abi-includes := sgidefs.h
 
 # _MIPS_SIM_ABI32 == 1, _MIPS_SIM_NABI32 == 2, _MIPS_SIM_ABI64 == 3
 abi-o32_soft-options := -U_MIPS_SIM -D_MIPS_SIM=1 \
-                       -D__mips_soft_float -U__mips_hard_float
-abi-o32_soft-condition := defined(__mips_soft_float) \
-                          && (_MIPS_SIM == _MIPS_SIM_ABI32)
+                       -D__mips_soft_float -U__mips_hard_float \
+                       -U__mips_nan2008
+abi-o32_soft-condition := !defined(__mips_nan2008) \
+                         && defined(__mips_soft_float) \
+                         && (_MIPS_SIM == _MIPS_SIM_ABI32)
+abi-o32_soft-ld-soname := ld.so.1
 abi-o32_hard-options := -U_MIPS_SIM -D_MIPS_SIM=1 \
-                       -D__mips_hard_float -U__mips_soft_float
-abi-o32_hard-condition := defined(__mips_hard_float) \
+                       -D__mips_hard_float -U__mips_soft_float \
+                       -U__mips_nan2008
+abi-o32_hard-condition := !defined(__mips_nan2008) \
+                         && defined(__mips_hard_float) \
                          && (_MIPS_SIM == _MIPS_SIM_ABI32)
+abi-o32_hard-ld-soname := ld.so.1
+abi-o32_soft_2008-options := -U_MIPS_SIM -D_MIPS_SIM=1 \
+                            -D__mips_soft_float -U__mips_hard_float \
+                            -D__mips_nan2008
+abi-o32_soft_2008-condition := defined(__mips_nan2008) \
+                              && defined(__mips_soft_float) \
+                              && (_MIPS_SIM == _MIPS_SIM_ABI32)
+abi-o32_soft_2008-ld-soname := ld-linux-mipsn8.so.1
+abi-o32_hard_2008-options := -U_MIPS_SIM -D_MIPS_SIM=1 \
+                            -D__mips_hard_float -U__mips_soft_float \
+                            -D__mips_nan2008
+abi-o32_hard_2008-condition := defined(__mips_nan2008) \
+                              && defined(__mips_hard_float) \
+                              && (_MIPS_SIM == _MIPS_SIM_ABI32)
+abi-o32_hard_2008-ld-soname := ld-linux-mipsn8.so.1
 abi-n32_soft-options := -U_MIPS_SIM -D_MIPS_SIM=2 \
-                       -D__mips_soft_float -U__mips_hard_float
-abi-n32_soft-condition := defined(__mips_soft_float) \
+                       -D__mips_soft_float -U__mips_hard_float \
+                       -U__mips_nan2008
+abi-n32_soft-condition := !defined(__mips_nan2008) \
+                         && defined(__mips_soft_float) \
                          && (_MIPS_SIM == _MIPS_SIM_NABI32)
+abi-n32_soft-ld-soname := ld.so.1
 abi-n32_hard-options := -U_MIPS_SIM -D_MIPS_SIM=2 \
-                       -D__mips_hard_float -U__mips_soft_float
-abi-n32_hard-condition := defined(__mips_hard_float) \
+                       -D__mips_hard_float -U__mips_soft_float \
+                       -U__mips_nan2008
+abi-n32_hard-condition := !defined(__mips_nan2008) \
+                         && defined(__mips_hard_float) \
                          && (_MIPS_SIM == _MIPS_SIM_NABI32)
+abi-n32_hard-ld-soname := ld.so.1
+abi-n32_soft_2008-options := -U_MIPS_SIM -D_MIPS_SIM=2 \
+                            -D__mips_soft_float -U__mips_hard_float \
+                            -D__mips_nan2008
+abi-n32_soft_2008-condition := defined(__mips_nan2008) \
+                              && defined(__mips_soft_float) \
+                              && (_MIPS_SIM == _MIPS_SIM_NABI32)
+abi-n32_soft_2008-ld-soname := ld-linux-mipsn8.so.1
+abi-n32_hard_2008-options := -U_MIPS_SIM -D_MIPS_SIM=2 \
+                            -D__mips_hard_float -U__mips_soft_float \
+                            -D__mips_nan2008
+abi-n32_hard_2008-condition := defined(__mips_nan2008) \
+                              && defined(__mips_hard_float) \
+                              && (_MIPS_SIM == _MIPS_SIM_NABI32)
+abi-n32_hard_2008-ld-soname := ld-linux-mipsn8.so.1
 abi-n64_soft-options := -U_MIPS_SIM -D_MIPS_SIM=3 \
-                       -D__mips_soft_float -U__mips_hard_float
-abi-n64_soft-condition := defined(__mips_soft_float) \
+                       -D__mips_soft_float -U__mips_hard_float \
+                       -U__mips_nan2008
+abi-n64_soft-condition := !defined(__mips_nan2008) \
+                         && defined(__mips_soft_float) \
                          && (_MIPS_SIM == _MIPS_SIM_ABI64)
+abi-n64_soft-ld-soname := ld.so.1
 abi-n64_hard-options := -U_MIPS_SIM -D_MIPS_SIM=3 \
-                       -D__mips_hard_float -U__mips_soft_float
-abi-n64_hard-condition := defined(__mips_hard_float) \
+                       -D__mips_hard_float -U__mips_soft_float \
+                       -U__mips_nan2008
+abi-n64_hard-condition := !defined(__mips_nan2008) \
+                         && defined(__mips_hard_float) \
                          && (_MIPS_SIM == _MIPS_SIM_ABI64)
+abi-n64_hard-ld-soname := ld.so.1
+abi-n64_soft_2008-options := -U_MIPS_SIM -D_MIPS_SIM=3 \
+                            -D__mips_soft_float -U__mips_hard_float \
+                            -D__mips_nan2008
+abi-n64_soft_2008-condition := defined(__mips_nan2008) \
+                              && defined(__mips_soft_float) \
+                              && (_MIPS_SIM == _MIPS_SIM_ABI64)
+abi-n64_soft_2008-ld-soname := ld-linux-mipsn8.so.1
+abi-n64_hard_2008-options := -U_MIPS_SIM -D_MIPS_SIM=3 \
+                            -D__mips_hard_float -U__mips_soft_float \
+                            -D__mips_nan2008
+abi-n64_hard_2008-condition := defined(__mips_nan2008) \
+                              && defined(__mips_hard_float) \
+                              && (_MIPS_SIM == _MIPS_SIM_ABI64)
+abi-n64_hard_2008-ld-soname := ld-linux-mipsn8.so.1
 
 ifeq ($(subdir),elf)
 ifeq ($(build-shared),yes)
index b4ee83e3ae8e8c7ace9b5d53b88c4f28223a3154..088210ff977d3704886d21c4e890ef7b85563546 100644 (file)
@@ -105,8 +105,168 @@ if test -z "$libc_mips_float"; then
   as_fn_error $? "could not determine if compiler is using hard or soft floating point ABI" "$LINENO" 5
 fi
 
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler is using the 2008 NaN encoding" >&5
+$as_echo_n "checking whether the compiler is using the 2008 NaN encoding... " >&6; }
+if ${libc_cv_mips_nan2008+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+dnl
+#ifdef __mips_nan2008
+yes
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then :
+  libc_cv_mips_nan2008=yes
+else
+  libc_cv_mips_nan2008=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mips_nan2008" >&5
+$as_echo "$libc_cv_mips_nan2008" >&6; }
+
+libc_mips_nan=
+if test x"$libc_cv_mips_nan2008" = xyes; then
+  libc_mips_nan=_2008
+fi
+
 config_vars="$config_vars
-default-abi = ${libc_mips_abi}_${libc_mips_float}"
+default-abi = ${libc_mips_abi}_${libc_mips_float}${libc_mips_nan}"
 
 case "$prefix" in
 /usr | /usr/)
@@ -138,3 +298,12 @@ case "$prefix" in
 esac
 
 libc_cv_gcc_unwind_find_fde=yes
+
+if test -z "$arch_minimum_kernel"; then
+  if test x$libc_cv_mips_nan2008 = xyes; then
+    # FIXME: Adjust this setting to the actual first upstream kernel
+    # version to support the 2008 NaN encoding and then remove this
+    # comment.
+    arch_minimum_kernel=10.0.0
+  fi
+fi
index b8dde6ef7a9ab4cd2c17c1bf6248a93c6b2e881f..7087a14a5efddee6f950a98b7dd3e24f58400af1 100644 (file)
@@ -44,7 +44,19 @@ if test -z "$libc_mips_float"; then
   AC_MSG_ERROR([could not determine if compiler is using hard or soft floating point ABI])
 fi
 
-LIBC_CONFIG_VAR([default-abi], [${libc_mips_abi}_${libc_mips_float}])
+AC_CACHE_CHECK([whether the compiler is using the 2008 NaN encoding],
+  libc_cv_mips_nan2008, [AC_EGREP_CPP(yes, [dnl
+#ifdef __mips_nan2008
+yes
+#endif], libc_cv_mips_nan2008=yes, libc_cv_mips_nan2008=no)])
+
+libc_mips_nan=
+if test x"$libc_cv_mips_nan2008" = xyes; then
+  libc_mips_nan=_2008
+fi
+
+LIBC_CONFIG_VAR([default-abi],
+  [${libc_mips_abi}_${libc_mips_float}${libc_mips_nan}])
 
 case "$prefix" in
 /usr | /usr/)
@@ -76,3 +88,12 @@ case "$prefix" in
 esac
 
 libc_cv_gcc_unwind_find_fde=yes
+
+if test -z "$arch_minimum_kernel"; then
+  if test x$libc_cv_mips_nan2008 = xyes; then
+    # FIXME: Adjust this setting to the actual first upstream kernel
+    # version to support the 2008 NaN encoding and then remove this
+    # comment.
+    arch_minimum_kernel=10.0.0
+  fi
+fi
index 4a7f3f1f2a5512e65a257498c3700e25f71efa72..49ad99ab92d3d3f15c4f2def3d2c31ea6e015d96 100644 (file)
 
 #include <ldconfig.h>
 
-/* Redefine the cache ID for new ABIs; o32 keeps using the generic check.  */
-#if _MIPS_SIM == _ABI64
-# define _DL_CACHE_DEFAULT_ID  (FLAG_MIPS64_LIBN64 | FLAG_ELF_LIBC6)
-#elif _MIPS_SIM == _ABIN32
-# define _DL_CACHE_DEFAULT_ID  (FLAG_MIPS64_LIBN32 | FLAG_ELF_LIBC6)
+#if ((defined __mips_nan2008 && !defined HAVE_MIPS_NAN2008) \
+     || (!defined __mips_nan2008 && defined HAVE_MIPS_NAN2008))
+# error "Configuration inconsistency: __mips_nan2008 != HAVE_MIPS_NAN2008, overridden CFLAGS?"
+#endif
+
+/* Redefine the cache ID for new ABIs and 2008 NaN support; legacy o32
+   keeps using the generic check.  */
+#ifdef __mips_nan2008
+# if _MIPS_SIM == _ABIO32
+#  define _DL_CACHE_DEFAULT_ID (FLAG_MIPS_LIB32_NAN2008 | FLAG_ELF_LIBC6)
+# elif _MIPS_SIM == _ABI64
+#  define _DL_CACHE_DEFAULT_ID (FLAG_MIPS64_LIBN64_NAN2008 | FLAG_ELF_LIBC6)
+# elif _MIPS_SIM == _ABIN32
+#  define _DL_CACHE_DEFAULT_ID (FLAG_MIPS64_LIBN32_NAN2008 | FLAG_ELF_LIBC6)
+# endif
+#else
+# if _MIPS_SIM == _ABI64
+#  define _DL_CACHE_DEFAULT_ID (FLAG_MIPS64_LIBN64 | FLAG_ELF_LIBC6)
+# elif _MIPS_SIM == _ABIN32
+#  define _DL_CACHE_DEFAULT_ID (FLAG_MIPS64_LIBN32 | FLAG_ELF_LIBC6)
+# endif
 #endif
 
 #ifdef _DL_CACHE_DEFAULT_ID
index 10f0ff7022d40f2080976a29fc2d00bee2c6cbe8..fd57a735c35b487d1078d664b4916998fde089a5 100644 (file)
@@ -33,19 +33,32 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
                  unsigned int *osversion, char **soname, void *file_contents,
                  size_t file_length)
 {
-  ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents;
+  union
+    {
+      Elf64_Ehdr *eh64;
+      Elf32_Ehdr *eh32;
+      ElfW(Ehdr) *eh;
+    }
+  elf_header;
   int ret;
 
-  if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
+  elf_header.eh = file_contents;
+  if (elf_header.eh->e_ident [EI_CLASS] == ELFCLASS32)
     {
-      Elf32_Ehdr *elf32_header = (Elf32_Ehdr *) elf_header;
-
       ret = process_elf32_file (file_name, lib, flag, osversion, soname,
                                file_contents, file_length);
+      if (!ret)
+       {
+         Elf32_Word flags = elf_header.eh32->e_flags;
+         int nan2008 = (flags & EF_MIPS_NAN2008) != 0;
 
-      /* n32 libraries are always libc.so.6+.  */
-      if (!ret && (elf32_header->e_flags & EF_MIPS_ABI2) != 0)
-       *flag = FLAG_MIPS64_LIBN32|FLAG_ELF_LIBC6;
+         /* n32 libraries are always libc.so.6+, o32 only if 2008 NaN.  */
+         if ((flags & EF_MIPS_ABI2) != 0)
+           *flag = (nan2008 ? FLAG_MIPS64_LIBN32_NAN2008
+                    : FLAG_MIPS64_LIBN32) | FLAG_ELF_LIBC6;
+         else if (nan2008)
+           *flag = FLAG_MIPS_LIB32_NAN2008 | FLAG_ELF_LIBC6;
+       }
     }
   else
     {
@@ -53,7 +66,13 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
                                file_contents, file_length);
       /* n64 libraries are always libc.so.6+.  */
       if (!ret)
-       *flag = FLAG_MIPS64_LIBN64|FLAG_ELF_LIBC6;
+       {
+         Elf64_Word flags = elf_header.eh64->e_flags;
+         int nan2008 = (flags & EF_MIPS_NAN2008) != 0;
+
+         *flag = (nan2008 ? FLAG_MIPS64_LIBN64_NAN2008
+                  : FLAG_MIPS64_LIBN64) | FLAG_ELF_LIBC6;
+       }
     }
 
   return ret;
index d96089d492cf000a6ce9124b41d97369a6ab5ed7..037f9599543626e591d35a67c99e0788d92d501f 100644 (file)
 
 #include <stdint.h>
 
-#define FLAG_ANY               -1
-#define FLAG_TYPE_MASK         0x00ff
-#define FLAG_LIBC4             0x0000
-#define FLAG_ELF               0x0001
-#define FLAG_ELF_LIBC5         0x0002
-#define FLAG_ELF_LIBC6         0x0003
-#define FLAG_REQUIRED_MASK     0xff00
-#define FLAG_SPARC_LIB64       0x0100
-#define FLAG_IA64_LIB64                0x0200
-#define FLAG_X8664_LIB64       0x0300
-#define FLAG_S390_LIB64                0x0400
-#define FLAG_POWERPC_LIB64     0x0500
-#define FLAG_MIPS64_LIBN32     0x0600
-#define FLAG_MIPS64_LIBN64     0x0700
-#define FLAG_X8664_LIBX32      0x0800
-#define FLAG_ARM_LIBHF         0x0900
-#define FLAG_AARCH64_LIB64     0x0a00
-#define FLAG_ARM_LIBSF         0x0b00
+#define FLAG_ANY                       -1
+#define FLAG_TYPE_MASK                 0x00ff
+#define FLAG_LIBC4                     0x0000
+#define FLAG_ELF                       0x0001
+#define FLAG_ELF_LIBC5                 0x0002
+#define FLAG_ELF_LIBC6                 0x0003
+#define FLAG_REQUIRED_MASK             0xff00
+#define FLAG_SPARC_LIB64               0x0100
+#define FLAG_IA64_LIB64                        0x0200
+#define FLAG_X8664_LIB64               0x0300
+#define FLAG_S390_LIB64                        0x0400
+#define FLAG_POWERPC_LIB64             0x0500
+#define FLAG_MIPS64_LIBN32             0x0600
+#define FLAG_MIPS64_LIBN64             0x0700
+#define FLAG_X8664_LIBX32              0x0800
+#define FLAG_ARM_LIBHF                 0x0900
+#define FLAG_AARCH64_LIB64             0x0a00
+#define FLAG_ARM_LIBSF                 0x0b00
+#define FLAG_MIPS_LIB32_NAN2008                0x0c00
+#define FLAG_MIPS64_LIBN32_NAN2008     0x0d00
+#define FLAG_MIPS64_LIBN64_NAN2008     0x0e00
 
 /* Name of auxiliary cache.  */
 #define _PATH_LDCONFIG_AUX_CACHE "/var/cache/ldconfig/aux-cache"