diff options
Diffstat (limited to 'ports')
-rw-r--r-- | ports/ChangeLog.mips | 68 | ||||
-rw-r--r-- | ports/sysdeps/mips/bits/nan.h | 23 | ||||
-rw-r--r-- | ports/sysdeps/mips/configure | 160 | ||||
-rw-r--r-- | ports/sysdeps/mips/configure.in | 9 | ||||
-rw-r--r-- | ports/sysdeps/mips/dl-machine.h | 14 | ||||
-rw-r--r-- | ports/sysdeps/mips/fpu_control.h | 25 | ||||
-rw-r--r-- | ports/sysdeps/mips/math_private.h | 6 | ||||
-rw-r--r-- | ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h | 18 | ||||
-rw-r--r-- | ports/sysdeps/mips/shlib-versions | 4 | ||||
-rw-r--r-- | ports/sysdeps/mips/soft-fp/sfp-machine.h | 18 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/mips/Makefile | 90 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/mips/configure | 171 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/mips/configure.in | 23 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/mips/dl-cache.h | 26 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/mips/readelflib.c | 35 |
15 files changed, 640 insertions, 50 deletions
diff --git a/ports/ChangeLog.mips b/ports/ChangeLog.mips index 5844bf5897..017b2c27eb 100644 --- a/ports/ChangeLog.mips +++ b/ports/ChangeLog.mips @@ -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. diff --git a/ports/sysdeps/mips/bits/nan.h b/ports/sysdeps/mips/bits/nan.h index 80f7866a97..c322523275 100644 --- a/ports/sysdeps/mips/bits/nan.h +++ b/ports/sysdeps/mips/bits/nan.h @@ -22,10 +22,11 @@ /* 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; }) \ @@ -43,10 +46,18 @@ # 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 diff --git a/ports/sysdeps/mips/configure b/ports/sysdeps/mips/configure index 898e4c3f20..de8092c970 100644 --- a/ports/sysdeps/mips/configure +++ b/ports/sysdeps/mips/configure @@ -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 diff --git a/ports/sysdeps/mips/configure.in b/ports/sysdeps/mips/configure.in index be9672d823..bcbdaffd9f 100644 --- a/ports/sysdeps/mips/configure.in +++ b/ports/sysdeps/mips/configure.in @@ -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 diff --git a/ports/sysdeps/mips/dl-machine.h b/ports/sysdeps/mips/dl-machine.h index dae938f039..722c8a0ba8 100644 --- a/ports/sysdeps/mips/dl-machine.h +++ b/ports/sysdeps/mips/dl-machine.h @@ -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: diff --git a/ports/sysdeps/mips/fpu_control.h b/ports/sysdeps/mips/fpu_control.h index 770cbb31d8..40469627a7 100644 --- a/ports/sysdeps/mips/fpu_control.h +++ b/ports/sysdeps/mips/fpu_control.h @@ -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__))); diff --git a/ports/sysdeps/mips/math_private.h b/ports/sysdeps/mips/math_private.h index f0ba4ee706..6b99957c7b 100644 --- a/ports/sysdeps/mips/math_private.h +++ b/ports/sysdeps/mips/math_private.h @@ -18,9 +18,13 @@ #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> diff --git a/ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h b/ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h index 9cfd6fbb7b..5be50927d0 100644 --- a/ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h +++ b/ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h @@ -24,15 +24,25 @@ #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. */ diff --git a/ports/sysdeps/mips/shlib-versions b/ports/sysdeps/mips/shlib-versions index 780939369b..b153732c27 100644 --- a/ports/sysdeps/mips/shlib-versions +++ b/ports/sysdeps/mips/shlib-versions @@ -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 diff --git a/ports/sysdeps/mips/soft-fp/sfp-machine.h b/ports/sysdeps/mips/soft-fp/sfp-machine.h index a60bef7665..fff3b3c613 100644 --- a/ports/sysdeps/mips/soft-fp/sfp-machine.h +++ b/ports/sysdeps/mips/soft-fp/sfp-machine.h @@ -21,15 +21,25 @@ #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. */ diff --git a/ports/sysdeps/unix/sysv/linux/mips/Makefile b/ports/sysdeps/unix/sysv/linux/mips/Makefile index 1e54036bfe..9070b775c4 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/Makefile +++ b/ports/sysdeps/unix/sysv/linux/mips/Makefile @@ -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) diff --git a/ports/sysdeps/unix/sysv/linux/mips/configure b/ports/sysdeps/unix/sysv/linux/mips/configure index b4ee83e3ae..088210ff97 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/configure +++ b/ports/sysdeps/unix/sysv/linux/mips/configure @@ -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 diff --git a/ports/sysdeps/unix/sysv/linux/mips/configure.in b/ports/sysdeps/unix/sysv/linux/mips/configure.in index b8dde6ef7a..7087a14a5e 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/configure.in +++ b/ports/sysdeps/unix/sysv/linux/mips/configure.in @@ -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 diff --git a/ports/sysdeps/unix/sysv/linux/mips/dl-cache.h b/ports/sysdeps/unix/sysv/linux/mips/dl-cache.h index 4a7f3f1f2a..49ad99ab92 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/dl-cache.h +++ b/ports/sysdeps/unix/sysv/linux/mips/dl-cache.h @@ -18,11 +18,27 @@ #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 diff --git a/ports/sysdeps/unix/sysv/linux/mips/readelflib.c b/ports/sysdeps/unix/sysv/linux/mips/readelflib.c index 10f0ff7022..fd57a735c3 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/readelflib.c +++ b/ports/sysdeps/unix/sysv/linux/mips/readelflib.c @@ -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; |