diff options
Diffstat (limited to 'ports/sysdeps/mips')
-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 |
9 files changed, 256 insertions, 21 deletions
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. */ |