1139e1875SWolfgang Denk /*
2139e1875SWolfgang Denk * Borrowed from GCC 4.2.2 (which still was GPL v2+)
3139e1875SWolfgang Denk */
4139e1875SWolfgang Denk /* 128-bit long double support routines for Darwin.
5139e1875SWolfgang Denk Copyright (C) 1993, 2003, 2004, 2005, 2006, 2007
6139e1875SWolfgang Denk Free Software Foundation, Inc.
7139e1875SWolfgang Denk
8139e1875SWolfgang Denk This file is part of GCC.
9139e1875SWolfgang Denk
10*1a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
11*1a459660SWolfgang Denk */
12139e1875SWolfgang Denk
13139e1875SWolfgang Denk /*
14139e1875SWolfgang Denk * Implementations of floating-point long double basic arithmetic
15139e1875SWolfgang Denk * functions called by the IBM C compiler when generating code for
16139e1875SWolfgang Denk * PowerPC platforms. In particular, the following functions are
17139e1875SWolfgang Denk * implemented: __gcc_qadd, __gcc_qsub, __gcc_qmul, and __gcc_qdiv.
18139e1875SWolfgang Denk * Double-double algorithms are based on the paper "Doubled-Precision
19139e1875SWolfgang Denk * IEEE Standard 754 Floating-Point Arithmetic" by W. Kahan, February 26,
20139e1875SWolfgang Denk * 1987. An alternative published reference is "Software for
21139e1875SWolfgang Denk * Doubled-Precision Floating-Point Computations", by Seppo Linnainmaa,
22139e1875SWolfgang Denk * ACM TOMS vol 7 no 3, September 1981, pages 272-283.
23139e1875SWolfgang Denk */
24139e1875SWolfgang Denk
25139e1875SWolfgang Denk /*
26139e1875SWolfgang Denk * Each long double is made up of two IEEE doubles. The value of the
27139e1875SWolfgang Denk * long double is the sum of the values of the two parts. The most
28139e1875SWolfgang Denk * significant part is required to be the value of the long double
29139e1875SWolfgang Denk * rounded to the nearest double, as specified by IEEE. For Inf
30139e1875SWolfgang Denk * values, the least significant part is required to be one of +0.0 or
31139e1875SWolfgang Denk * -0.0. No other requirements are made; so, for example, 1.0 may be
32139e1875SWolfgang Denk * represented as (1.0, +0.0) or (1.0, -0.0), and the low part of a
33139e1875SWolfgang Denk * NaN is don't-care.
34139e1875SWolfgang Denk *
35139e1875SWolfgang Denk * This code currently assumes big-endian.
36139e1875SWolfgang Denk */
37139e1875SWolfgang Denk
38139e1875SWolfgang Denk #define fabs(x) __builtin_fabs(x)
39139e1875SWolfgang Denk #define isless(x, y) __builtin_isless(x, y)
40139e1875SWolfgang Denk #define inf() __builtin_inf()
41139e1875SWolfgang Denk #define unlikely(x) __builtin_expect((x), 0)
42139e1875SWolfgang Denk #define nonfinite(a) unlikely(!isless(fabs(a), inf()))
43139e1875SWolfgang Denk
44139e1875SWolfgang Denk typedef union {
45139e1875SWolfgang Denk long double ldval;
46139e1875SWolfgang Denk double dval[2];
47139e1875SWolfgang Denk } longDblUnion;
48139e1875SWolfgang Denk
49139e1875SWolfgang Denk /* Add two 'long double' values and return the result. */
__gcc_qadd(double a,double aa,double c,double cc)50139e1875SWolfgang Denk long double __gcc_qadd(double a, double aa, double c, double cc)
51139e1875SWolfgang Denk {
52139e1875SWolfgang Denk longDblUnion x;
53139e1875SWolfgang Denk double z, q, zz, xh;
54139e1875SWolfgang Denk
55139e1875SWolfgang Denk z = a + c;
56139e1875SWolfgang Denk
57139e1875SWolfgang Denk if (nonfinite(z)) {
58139e1875SWolfgang Denk z = cc + aa + c + a;
59139e1875SWolfgang Denk if (nonfinite(z))
60139e1875SWolfgang Denk return z;
61139e1875SWolfgang Denk x.dval[0] = z; /* Will always be DBL_MAX. */
62139e1875SWolfgang Denk zz = aa + cc;
63139e1875SWolfgang Denk if (fabs(a) > fabs(c))
64139e1875SWolfgang Denk x.dval[1] = a - z + c + zz;
65139e1875SWolfgang Denk else
66139e1875SWolfgang Denk x.dval[1] = c - z + a + zz;
67139e1875SWolfgang Denk } else {
68139e1875SWolfgang Denk q = a - z;
69139e1875SWolfgang Denk zz = q + c + (a - (q + z)) + aa + cc;
70139e1875SWolfgang Denk
71139e1875SWolfgang Denk /* Keep -0 result. */
72139e1875SWolfgang Denk if (zz == 0.0)
73139e1875SWolfgang Denk return z;
74139e1875SWolfgang Denk
75139e1875SWolfgang Denk xh = z + zz;
76139e1875SWolfgang Denk if (nonfinite(xh))
77139e1875SWolfgang Denk return xh;
78139e1875SWolfgang Denk
79139e1875SWolfgang Denk x.dval[0] = xh;
80139e1875SWolfgang Denk x.dval[1] = z - xh + zz;
81139e1875SWolfgang Denk }
82139e1875SWolfgang Denk return x.ldval;
83139e1875SWolfgang Denk }
84139e1875SWolfgang Denk
__gcc_qsub(double a,double b,double c,double d)85139e1875SWolfgang Denk long double __gcc_qsub(double a, double b, double c, double d)
86139e1875SWolfgang Denk {
87139e1875SWolfgang Denk return __gcc_qadd(a, b, -c, -d);
88139e1875SWolfgang Denk }
89139e1875SWolfgang Denk
__gcc_qmul(double a,double b,double c,double d)90139e1875SWolfgang Denk long double __gcc_qmul(double a, double b, double c, double d)
91139e1875SWolfgang Denk {
92139e1875SWolfgang Denk longDblUnion z;
93139e1875SWolfgang Denk double t, tau, u, v, w;
94139e1875SWolfgang Denk
95139e1875SWolfgang Denk t = a * c; /* Highest order double term. */
96139e1875SWolfgang Denk
97139e1875SWolfgang Denk if (unlikely(t == 0) /* Preserve -0. */
98139e1875SWolfgang Denk || nonfinite(t))
99139e1875SWolfgang Denk return t;
100139e1875SWolfgang Denk
101139e1875SWolfgang Denk /* Sum terms of two highest orders. */
102139e1875SWolfgang Denk
103139e1875SWolfgang Denk /* Use fused multiply-add to get low part of a * c. */
104139e1875SWolfgang Denk #ifndef __NO_FPRS__
105139e1875SWolfgang Denk asm("fmsub %0,%1,%2,%3" : "=f"(tau) : "f"(a), "f"(c), "f"(t));
106139e1875SWolfgang Denk #else
107139e1875SWolfgang Denk tau = fmsub(a, c, t);
108139e1875SWolfgang Denk #endif
109139e1875SWolfgang Denk v = a * d;
110139e1875SWolfgang Denk w = b * c;
111139e1875SWolfgang Denk tau += v + w; /* Add in other second-order terms. */
112139e1875SWolfgang Denk u = t + tau;
113139e1875SWolfgang Denk
114139e1875SWolfgang Denk /* Construct long double result. */
115139e1875SWolfgang Denk if (nonfinite(u))
116139e1875SWolfgang Denk return u;
117139e1875SWolfgang Denk z.dval[0] = u;
118139e1875SWolfgang Denk z.dval[1] = (t - u) + tau;
119139e1875SWolfgang Denk return z.ldval;
120139e1875SWolfgang Denk }
121