xref: /rk3399_rockchip-uboot/post/lib_powerpc/fpu/darwin-ldouble.c (revision 326ea986ac150acdc7656d57fca647db80b50158)
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