From: dje Date: Tue, 16 Jan 2007 16:03:26 +0000 (+0000) Subject: * config/rs6000/darwin-ldouble.c: Build file for SOFT_FLOAT. X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=23ee07771e8bcc4dfae2fc4e408df118990ef0f3;hp=34b0e09cd2ed4f463f7168b8ca0fb8f15443d455 * config/rs6000/darwin-ldouble.c: Build file for SOFT_FLOAT. (strong_alias): Define. (__gcc_qmul): Provide non-FMA for soft-float. (__gcc_qdiv): Same. (__gcc_qneg): New. (__gcc_qeq): New. (__gcc_qle): New. (__gcc_qge): New. (__gcc_qunord): New. (__gcc_stoq): New. (__gcc_dtoq): New. (__gcc_qtos): New. (__gcc_qtod): New. (__gcc_qtoi): New. (__gcc_qtou): New. (__gcc_itoq): New. (__gcc_utoq): New. (fmsub): New. * config/rs6000/rs6000.c (rs6000_init_libfuncs): Initialize soft-float functions. * config/rs6000/libgcc-ppc-glibc.ver: Version soft-float symbols. * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Do not warn about long double soft float. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120828 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 45029c3f3ee..cf4cd24f51d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2007-01-16 David Edelsohn + + * config/rs6000/darwin-ldouble.c: Build file for SOFT_FLOAT. + (strong_alias): Define. + (__gcc_qmul): Provide non-FMA for soft-float. + (__gcc_qdiv): Same. + (__gcc_qneg): New. + (__gcc_qeq): New. + (__gcc_qle): New. + (__gcc_qge): New. + (__gcc_qunord): New. + (__gcc_stoq): New. + (__gcc_dtoq): New. + (__gcc_qtos): New. + (__gcc_qtod): New. + (__gcc_qtoi): New. + (__gcc_qtou): New. + (__gcc_itoq): New. + (__gcc_utoq): New. + (fmsub): New. + * config/rs6000/rs6000.c (rs6000_init_libfuncs): Initialize + soft-float functions. + * config/rs6000/libgcc-ppc-glibc.ver: Version soft-float symbols. + * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Do not warn + about long double soft float. + 2007-01-16 Dorit Nuzman Tehila Meyzels diff --git a/gcc/config/rs6000/darwin-ldouble.c b/gcc/config/rs6000/darwin-ldouble.c index 356bc18b57e..8ac69f2e627 100644 --- a/gcc/config/rs6000/darwin-ldouble.c +++ b/gcc/config/rs6000/darwin-ldouble.c @@ -49,7 +49,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA This code currently assumes big-endian. */ -#if (!defined (__NO_FPRS__) && !defined (__LITTLE_ENDIAN__) \ +#if ((!defined (__NO_FPRS__) || defined (_SOFT_FLOAT)) \ + && !defined (__LITTLE_ENDIAN__) \ && (defined (__MACH__) || defined (__powerpc__) || defined (_AIX))) #define fabs(x) __builtin_fabs(x) @@ -60,14 +61,19 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #define nonfinite(a) unlikely (! isless (fabs (a), inf ())) +/* 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))); + /* All these routines actually take two long doubles as parameters, but GCC currently generates poor code when a union is used to turn a long double into a pair of doubles. */ -extern long double __gcc_qadd (double, double, double, double); -extern long double __gcc_qsub (double, double, double, double); -extern long double __gcc_qmul (double, double, double, double); -extern long double __gcc_qdiv (double, double, double, double); +long double __gcc_qadd (double, double, double, double); +long double __gcc_qsub (double, double, double, double); +long double __gcc_qmul (double, double, double, double); +long double __gcc_qdiv (double, double, double, double); #if defined __ELF__ && defined SHARED \ && (defined __powerpc64__ || !(defined __linux__ || defined __gnu_hurd__)) @@ -139,6 +145,10 @@ __gcc_qsub (double a, double b, double c, double d) return __gcc_qadd (a, b, -c, -d); } +#ifdef _SOFT_FLOAT +static double fmsub (double, double, double); +#endif + long double __gcc_qmul (double a, double b, double c, double d) { @@ -154,7 +164,11 @@ __gcc_qmul (double a, double b, double c, double d) /* Sum terms of two highest orders. */ /* Use fused multiply-add to get low part of a * c. */ +#ifndef _SOFT_FLOAT asm ("fmsub %0,%1,%2,%3" : "=f"(tau) : "f"(a), "f"(c), "f"(t)); +#else + tau = fmsub (a, c, t); +#endif v = a*d; w = b*c; tau += v + w; /* Add in other second-order terms. */ @@ -187,7 +201,11 @@ __gcc_qdiv (double a, double b, double c, double d) numerically necessary. */ /* Use fused multiply-add to get low part of c * t. */ +#ifndef _SOFT_FLOAT asm ("fmsub %0,%1,%2,%3" : "=f"(sigma) : "f"(c), "f"(t), "f"(s)); +#else + sigma = fmsub (c, t, s); +#endif v = a - s; tau = ((v-sigma)+w)/c; /* Correction to t. */ @@ -201,4 +219,220 @@ __gcc_qdiv (double a, double b, double c, double d) return z.ldval; } +#ifdef _SOFT_FLOAT + +long double __gcc_qneg (double, double); +int __gcc_qeq (double, double, double, double); +int __gcc_qne (double, double, double, double); +int __gcc_qge (double, double, double, double); +int __gcc_qle (double, double, double, double); +int __gcc_qunord (double, double, double, double); +long double __gcc_stoq (float); +long double __gcc_dtoq (double); +float __gcc_qtos (double, double); +double __gcc_qtod (double, double); +int __gcc_qtoi (double, double); +unsigned int __gcc_qtou (double, double); +long double __gcc_itoq (int); +long double __gcc_utoq (unsigned int); + +extern int __eqdf2 (double, double); +extern int __ledf2 (double, double); +extern int __gedf2 (double, double); +extern int __unorddf2 (double, double); + +/* Negate 'long double' value and return the result. */ +long double +__gcc_qneg (double a, double aa) +{ + longDblUnion x; + + x.dval[0] = -a; + x.dval[1] = -aa; + return x.ldval; +} + +/* Compare two 'long double' values for equality. */ +int +__gcc_qeq (double a, double aa, double c, double cc) +{ + if (__eqdf2 (a, c) == 0) + return __eqdf2 (aa, cc); + return 1; +} + +strong_alias (__gcc_qeq, __gcc_qne); + +/* Compare two 'long double' values for less than or equal. */ +int +__gcc_qle (double a, double aa, double c, double cc) +{ + if (__eqdf2 (a, c) == 0) + return __ledf2 (aa, cc); + return __ledf2 (a, c); +} + +strong_alias (__gcc_qle, __gcc_qlt); + +/* Compare two 'long double' values for greater than or equal. */ +int +__gcc_qge (double a, double aa, double c, double cc) +{ + if (__eqdf2 (a, c) == 0) + return __gedf2 (aa, cc); + return __gedf2 (a, c); +} + +strong_alias (__gcc_qge, __gcc_qgt); + +/* Compare two 'long double' values for unordered. */ +int +__gcc_qunord (double a, double aa, double c, double cc) +{ + if (__eqdf2 (a, c) == 0) + return __unorddf2 (aa, cc); + return __unorddf2 (a, c); +} + +/* Convert single to long double. */ +long double +__gcc_stoq (float a) +{ + longDblUnion x; + + x.dval[0] = (double) a; + x.dval[1] = 0.0; + + return x.ldval; +} + +/* Convert double to long double. */ +long double +__gcc_dtoq (double a) +{ + longDblUnion x; + + x.dval[0] = a; + x.dval[1] = 0.0; + + return x.ldval; +} + +/* Convert long double to single. */ +float +__gcc_qtos (double a, double aa __attribute__ ((__unused__))) +{ + return (float) a; +} + +/* Convert long double to double. */ +double +__gcc_qtod (double a, double aa __attribute__ ((__unused__))) +{ + return a; +} + +/* Convert long double to int. */ +int +__gcc_qtoi (double a, double aa) +{ + double z = a + aa; + return (int) z; +} + +/* Convert long double to unsigned int. */ +unsigned int +__gcc_qtou (double a, double aa) +{ + double z = a + aa; + return (unsigned int) z; +} + +/* Convert int to long double. */ +long double +__gcc_itoq (int a) +{ + return __gcc_dtoq ((double) a); +} + +/* Convert unsigned int to long double. */ +long double +__gcc_utoq (unsigned int a) +{ + return __gcc_dtoq ((double) a); +} + +#include "config/soft-fp/soft-fp.h" +#include "config/soft-fp/double.h" +#include "config/soft-fp/quad.h" + +/* Compute floating point multiply-subtract with higher (quad) precision. */ +static double +fmsub (double a, double b, double c) +{ + FP_DECL_EX; + FP_DECL_D(A); + FP_DECL_D(B); + FP_DECL_D(C); + FP_DECL_Q(X); + FP_DECL_Q(Y); + FP_DECL_Q(Z); + FP_DECL_Q(U); + FP_DECL_Q(V); + FP_DECL_D(R); + double r; + long double u, v, x, y, z; + + FP_INIT_ROUNDMODE; + FP_UNPACK_RAW_D (A, a); + FP_UNPACK_RAW_D (B, b); + FP_UNPACK_RAW_D (C, c); + + /* Extend double to quad. */ +#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q + FP_EXTEND(Q,D,4,2,X,A); + FP_EXTEND(Q,D,4,2,Y,B); + FP_EXTEND(Q,D,4,2,Z,C); +#else + FP_EXTEND(Q,D,2,1,X,A); + FP_EXTEND(Q,D,2,1,Y,B); + FP_EXTEND(Q,D,2,1,Z,C); +#endif + FP_PACK_RAW_Q(x,X); + FP_PACK_RAW_Q(y,Y); + FP_PACK_RAW_Q(z,Z); + FP_HANDLE_EXCEPTIONS; + + /* Multiply. */ + FP_INIT_ROUNDMODE; + FP_UNPACK_Q(X,x); + FP_UNPACK_Q(Y,y); + FP_MUL_Q(U,X,Y); + FP_PACK_Q(u,U); + FP_HANDLE_EXCEPTIONS; + + /* Subtract. */ + FP_INIT_ROUNDMODE; + FP_UNPACK_SEMIRAW_Q(U,u); + FP_UNPACK_SEMIRAW_Q(Z,z); + FP_SUB_Q(V,U,Z); + FP_PACK_SEMIRAW_Q(v,V); + FP_HANDLE_EXCEPTIONS; + + /* Truncate quad to double. */ + FP_INIT_ROUNDMODE; + FP_UNPACK_SEMIRAW_Q(V,v); +#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q + FP_TRUNC(D,Q,2,4,R,V); +#else + FP_TRUNC(D,Q,1,2,R,V); +#endif + FP_PACK_SEMIRAW_D(r,R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +#endif + #endif diff --git a/gcc/config/rs6000/libgcc-ppc-glibc.ver b/gcc/config/rs6000/libgcc-ppc-glibc.ver index 988ed76aa8e..d8ffd2ad282 100644 --- a/gcc/config/rs6000/libgcc-ppc-glibc.ver +++ b/gcc/config/rs6000/libgcc-ppc-glibc.ver @@ -21,11 +21,32 @@ GCC_4.1.0 { %else GCC_3.4.4 { %endif +%else +GCC_4.2.0 { +%endif # long double support __gcc_qadd __gcc_qsub __gcc_qmul __gcc_qdiv -} + +%ifdef _SOFT_FLOAT + __gcc_qneg + __gcc_qeq + __gcc_qne + __gcc_ggt + __gcc_qge + __gcc_qlt + __gcc_qle + __gcc_qunord + __gcc_stoq + __gcc_dtoq + __gcc_qtos + __gcc_qtod + __gcc_qtoi + __gcc_qtou + __gcc_itoq + __gcc_utoq %endif +} diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 7ef7551764f..ce178140ef0 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -9401,9 +9401,6 @@ rs6000_common_init_builtins (void) static void rs6000_init_libfuncs (void) { - if (!TARGET_HARD_FLOAT) - return; - if (DEFAULT_ABI != ABI_V4 && TARGET_XCOFF && !TARGET_POWER2 && !TARGET_POWERPC) { @@ -9422,6 +9419,27 @@ rs6000_init_libfuncs (void) set_optab_libfunc (sub_optab, TFmode, "__gcc_qsub"); set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul"); set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv"); + + if (TARGET_SOFT_FLOAT) + { + set_optab_libfunc (neg_optab, TFmode, "__gcc_qneg"); + set_optab_libfunc (eq_optab, TFmode, "__gcc_qeq"); + set_optab_libfunc (ne_optab, TFmode, "__gcc_qne"); + set_optab_libfunc (gt_optab, TFmode, "__gcc_qgt"); + set_optab_libfunc (ge_optab, TFmode, "__gcc_qge"); + set_optab_libfunc (lt_optab, TFmode, "__gcc_qlt"); + set_optab_libfunc (le_optab, TFmode, "__gcc_qle"); + set_optab_libfunc (unord_optab, TFmode, "__gcc_qunord"); + + set_conv_libfunc (sext_optab, TFmode, SFmode, "__gcc_stoq"); + set_conv_libfunc (sext_optab, TFmode, DFmode, "__gcc_dtoq"); + set_conv_libfunc (trunc_optab, SFmode, TFmode, "__gcc_qtos"); + set_conv_libfunc (trunc_optab, DFmode, TFmode, "__gcc_qtod"); + set_conv_libfunc (sfix_optab, SImode, TFmode, "__gcc_qtoi"); + set_conv_libfunc (ufix_optab, SImode, TFmode, "__gcc_qtou"); + set_conv_libfunc (sfloat_optab, TFmode, SImode, "__gcc_itoq"); + set_conv_libfunc (ufloat_optab, TFmode, SImode, "__gcc_utoq"); + } } else { diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 29430c8270e..d7c10028a79 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -215,10 +215,6 @@ do { \ error ("-msecure-plt not supported by your assembler"); \ } \ \ - if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128 \ - && rs6000_explicit_options.long_double) \ - warning (0, "-msoft-float and -mlong-double-128 not supported"); \ - \ /* Treat -fPIC the same as -mrelocatable. */ \ if (flag_pic > 1 && DEFAULT_ABI != ABI_AIX) \ { \