Hello, This change adds soft-fp support for SDE bare-iron targets.
The settings have been mostly based on the version already present in glibc, except that the ABI variations have been merged into a single file and conditionalised on preprocessor macros (and the file reformatted to follow the GNU coding standard that the glibc variants don't). Only n32 has to be treated somewhat specially as it is ILP32 but its "long long" type is 64-bit with native support (using single registers rather than pairs). The rest is handled generically, based on the width of the types chosen. This has been regression tested for the mips-sde-elf target with no new failures, using the o32 and n64 ABI multilibs, with and without -msoft-float, o32 also with MIPS16 variants. There's currently no SDE runtime support for n32, however despite the unability to test I decided the configuration shouldn't be pessimised by default (by avoiding the special exception and using the 32-bit "long" type) as glibc already uses such an arrangement so it's been verified elsewhere and if a platform that supports the n32 ABI decides later on to enable soft-fp too, it will be verified in libgcc anyway. I believe this is reasonable and avoids the risk of someone chooing the "long" type by omission. Comments or questions are welcome, otherwise OK to apply? 2012-06-28 Catherine Moore <c...@codesourcery.com> Maciej W. Rozycki <ma...@codesourcery.com> libgcc/ * config/mips/sfp-machine.h: New file. * config.host <mips*-sde-elf*>: Enable soft-fp. Maciej gcc-mips-softfp.diff Index: gcc-trunk-4.6/libgcc/config/mips/sfp-machine.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc-trunk-4.6/libgcc/config/mips/sfp-machine.h 2012-06-24 14:38:40.083663725 +0100 @@ -0,0 +1,101 @@ +#if defined _ABIN32 && _MIPS_SIM == _ABIN32 + +#define _FP_W_TYPE_SIZE 64 +#define _FP_W_TYPE unsigned long long +#define _FP_WS_TYPE signed long long +#define _FP_I_TYPE long long + +#else + +#define _FP_W_TYPE_SIZE _MIPS_SZLONG +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long + +#endif + +#if _FP_W_TYPE_SIZE < 64 + +#define _FP_MUL_MEAT_S(R, X, Y) \ + _FP_MUL_MEAT_1_wide (_FP_WFRACBITS_S, R, X, Y, umul_ppmm) +#define _FP_MUL_MEAT_D(R, X, Y) \ + _FP_MUL_MEAT_2_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm) +#define _FP_MUL_MEAT_Q(R, X, Y) \ + _FP_MUL_MEAT_4_wide (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm) + +#define _FP_DIV_MEAT_S(R, X, Y) \ + _FP_DIV_MEAT_1_udiv_norm (S, R, X, Y) +#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) + +#else + +#define _FP_MUL_MEAT_S(R, X, Y) \ + _FP_MUL_MEAT_1_imm (_FP_WFRACBITS_S, R, X, Y) +#define _FP_MUL_MEAT_D(R, X, Y) \ + _FP_MUL_MEAT_1_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm) +#define _FP_MUL_MEAT_Q(R, X, Y) \ + _FP_MUL_MEAT_2_wide_3mul (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm) + +#define _FP_DIV_MEAT_S(R, X, Y) \ + _FP_DIV_MEAT_1_imm (S, R, X, Y, _FP_DIV_HELP_imm) +#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) + +#endif + +#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 +#define _FP_NANSIGN_S 0 +#define _FP_NANSIGN_D 0 +#define _FP_NANSIGN_Q 0 + +#define _FP_KEEPNANFRACP 1 +/* From my experiments it seems X is chosen unless one of the + NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if ((_FP_FRAC_HIGH_RAW_##fs (X) \ + | _FP_FRAC_HIGH_RAW_##fs (Y)) & _FP_QNANBIT_##fs) \ + { \ + R##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ + } \ + else \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc (R, X); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#define FP_EX_INVALID (1 << 4) +#define FP_EX_DIVZERO (1 << 3) +#define FP_EX_OVERFLOW (1 << 2) +#define FP_EX_UNDERFLOW (1 << 1) +#define FP_EX_INEXACT (1 << 0) + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#if defined MIPS_EB || defined __MIPSEB__ || defined MIPSEB || defined _MIPSEB +# if defined MIPS_EL || defined __MIPSEL__ || defined MIPSEL || defined _MIPSEL +# error "Both BIG_ENDIAN and LITTLE_ENDIAN defined!" +# endif +# define __BYTE_ORDER __BIG_ENDIAN +#elif defined MIPS_EL || defined __MIPSEL__ || defined MIPSEL || defined _MIPSEL +# define __BYTE_ORDER __LITTLE_ENDIAN +#else +# error "Cannot determine current byte order" +#endif + + +/* Define ALIASNAME as a strong alias for NAME. */ +#define strong_alias(name, aliasname) _strong_alias (name, aliasname) +#define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); Index: gcc-trunk-4.6/libgcc/config.host =================================================================== --- gcc-trunk-4.6.orig/libgcc/config.host 2012-06-22 20:31:35.000000000 +0100 +++ gcc-trunk-4.6/libgcc/config.host 2012-06-22 20:31:37.654759477 +0100 @@ -737,7 +737,7 @@ mips*-*-linux*) # Linux MIPS, either fi ;; mips*-sde-elf*) - tmake_file="$tmake_file mips/t-crtstuff mips/t-mips16" + tmake_file="$tmake_file mips/t-crtstuff mips/t-mips16 t-softfp-sfdf t-softfp-excl t-softfp" case "${with_newlib}" in yes) # newlib / libgloss.