+#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
+