1132718Skan/* 128-bit long double support routines for Darwin. 2169689Skan Copyright (C) 1993, 2003, 2004, 2005, 2006, 2007 3169689Skan Free Software Foundation, Inc. 4132718Skan 5132718SkanThis file is part of GCC. 6132718Skan 7132718SkanGCC is free software; you can redistribute it and/or modify it under 8132718Skanthe terms of the GNU General Public License as published by the Free 9132718SkanSoftware Foundation; either version 2, or (at your option) any later 10132718Skanversion. 11132718Skan 12132718SkanIn addition to the permissions in the GNU General Public License, the 13132718SkanFree Software Foundation gives you unlimited permission to link the 14132718Skancompiled version of this file into combinations with other programs, 15132718Skanand to distribute those combinations without any restriction coming 16132718Skanfrom the use of this file. (The General Public License restrictions 17132718Skando apply in other respects; for example, they cover modification of 18132718Skanthe file, and distribution when not linked into a combine 19132718Skanexecutable.) 20132718Skan 21132718SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 22132718SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 23132718SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 24132718Skanfor more details. 25132718Skan 26132718SkanYou should have received a copy of the GNU General Public License 27132718Skanalong with GCC; see the file COPYING. If not, write to the Free 28169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 29169689Skan02110-1301, USA. */ 30132718Skan 31132718Skan/* Implementations of floating-point long double basic arithmetic 32132718Skan functions called by the IBM C compiler when generating code for 33132718Skan PowerPC platforms. In particular, the following functions are 34169689Skan implemented: __gcc_qadd, __gcc_qsub, __gcc_qmul, and __gcc_qdiv. 35169689Skan Double-double algorithms are based on the paper "Doubled-Precision 36169689Skan IEEE Standard 754 Floating-Point Arithmetic" by W. Kahan, February 26, 37169689Skan 1987. An alternative published reference is "Software for 38169689Skan Doubled-Precision Floating-Point Computations", by Seppo Linnainmaa, 39169689Skan ACM TOMS vol 7 no 3, September 1981, pages 272-283. */ 40132718Skan 41132718Skan/* Each long double is made up of two IEEE doubles. The value of the 42132718Skan long double is the sum of the values of the two parts. The most 43132718Skan significant part is required to be the value of the long double 44132718Skan rounded to the nearest double, as specified by IEEE. For Inf 45132718Skan values, the least significant part is required to be one of +0.0 or 46132718Skan -0.0. No other requirements are made; so, for example, 1.0 may be 47132718Skan represented as (1.0, +0.0) or (1.0, -0.0), and the low part of a 48132718Skan NaN is don't-care. 49132718Skan 50132718Skan This code currently assumes big-endian. */ 51132718Skan 52169689Skan#if ((!defined (__NO_FPRS__) || defined (_SOFT_FLOAT)) \ 53169689Skan && !defined (__LITTLE_ENDIAN__) \ 54169689Skan && (defined (__MACH__) || defined (__powerpc__) || defined (_AIX))) 55132718Skan 56132718Skan#define fabs(x) __builtin_fabs(x) 57169689Skan#define isless(x, y) __builtin_isless (x, y) 58169689Skan#define inf() __builtin_inf() 59132718Skan 60132718Skan#define unlikely(x) __builtin_expect ((x), 0) 61132718Skan 62169689Skan#define nonfinite(a) unlikely (! isless (fabs (a), inf ())) 63169689Skan 64169689Skan/* Define ALIASNAME as a strong alias for NAME. */ 65169689Skan# define strong_alias(name, aliasname) _strong_alias(name, aliasname) 66169689Skan# define _strong_alias(name, aliasname) \ 67169689Skan extern __typeof (name) aliasname __attribute__ ((alias (#name))); 68169689Skan 69132718Skan/* All these routines actually take two long doubles as parameters, 70132718Skan but GCC currently generates poor code when a union is used to turn 71132718Skan a long double into a pair of doubles. */ 72132718Skan 73169689Skanlong double __gcc_qadd (double, double, double, double); 74169689Skanlong double __gcc_qsub (double, double, double, double); 75169689Skanlong double __gcc_qmul (double, double, double, double); 76169689Skanlong double __gcc_qdiv (double, double, double, double); 77132718Skan 78169689Skan#if defined __ELF__ && defined SHARED \ 79169689Skan && (defined __powerpc64__ || !(defined __linux__ || defined __gnu_hurd__)) 80169689Skan/* Provide definitions of the old symbol names to satisfy apps and 81146895Skan shared libs built against an older libgcc. To access the _xlq 82146895Skan symbols an explicit version reference is needed, so these won't 83146895Skan satisfy an unadorned reference like _xlqadd. If dot symbols are 84146895Skan not needed, the assembler will remove the aliases from the symbol 85146895Skan table. */ 86146895Skan__asm__ (".symver __gcc_qadd,_xlqadd@GCC_3.4\n\t" 87169689Skan ".symver __gcc_qsub,_xlqsub@GCC_3.4\n\t" 88169689Skan ".symver __gcc_qmul,_xlqmul@GCC_3.4\n\t" 89169689Skan ".symver __gcc_qdiv,_xlqdiv@GCC_3.4\n\t" 90169689Skan ".symver .__gcc_qadd,._xlqadd@GCC_3.4\n\t" 91169689Skan ".symver .__gcc_qsub,._xlqsub@GCC_3.4\n\t" 92169689Skan ".symver .__gcc_qmul,._xlqmul@GCC_3.4\n\t" 93169689Skan ".symver .__gcc_qdiv,._xlqdiv@GCC_3.4"); 94146895Skan#endif 95146895Skan 96132718Skantypedef union 97132718Skan{ 98132718Skan long double ldval; 99132718Skan double dval[2]; 100132718Skan} longDblUnion; 101132718Skan 102132718Skan/* Add two 'long double' values and return the result. */ 103132718Skanlong double 104169689Skan__gcc_qadd (double a, double aa, double c, double cc) 105132718Skan{ 106169689Skan longDblUnion x; 107169689Skan double z, q, zz, xh; 108132718Skan 109169689Skan z = a + c; 110132718Skan 111169689Skan if (nonfinite (z)) 112132718Skan { 113169689Skan z = cc + aa + c + a; 114169689Skan if (nonfinite (z)) 115169689Skan return z; 116169689Skan x.dval[0] = z; /* Will always be DBL_MAX. */ 117169689Skan zz = aa + cc; 118169689Skan if (fabs(a) > fabs(c)) 119169689Skan x.dval[1] = a - z + c + zz; 120169689Skan else 121169689Skan x.dval[1] = c - z + a + zz; 122132718Skan } 123169689Skan else 124132718Skan { 125169689Skan q = a - z; 126169689Skan zz = q + c + (a - (q + z)) + aa + cc; 127132718Skan 128169689Skan /* Keep -0 result. */ 129169689Skan if (zz == 0.0) 130169689Skan return z; 131132718Skan 132169689Skan xh = z + zz; 133169689Skan if (nonfinite (xh)) 134169689Skan return xh; 135169689Skan 136169689Skan x.dval[0] = xh; 137169689Skan x.dval[1] = z - xh + zz; 138132718Skan } 139169689Skan return x.ldval; 140132718Skan} 141132718Skan 142132718Skanlong double 143146895Skan__gcc_qsub (double a, double b, double c, double d) 144132718Skan{ 145146895Skan return __gcc_qadd (a, b, -c, -d); 146132718Skan} 147132718Skan 148169689Skan#ifdef _SOFT_FLOAT 149169689Skanstatic double fmsub (double, double, double); 150169689Skan#endif 151169689Skan 152132718Skanlong double 153146895Skan__gcc_qmul (double a, double b, double c, double d) 154132718Skan{ 155132718Skan longDblUnion z; 156169689Skan double t, tau, u, v, w; 157132718Skan 158132718Skan t = a * c; /* Highest order double term. */ 159132718Skan 160169689Skan if (unlikely (t == 0) /* Preserve -0. */ 161169689Skan || nonfinite (t)) 162132718Skan return t; 163132718Skan 164169689Skan /* Sum terms of two highest orders. */ 165132718Skan 166169689Skan /* Use fused multiply-add to get low part of a * c. */ 167169689Skan#ifndef _SOFT_FLOAT 168132718Skan asm ("fmsub %0,%1,%2,%3" : "=f"(tau) : "f"(a), "f"(c), "f"(t)); 169169689Skan#else 170169689Skan tau = fmsub (a, c, t); 171169689Skan#endif 172132718Skan v = a*d; 173132718Skan w = b*c; 174132718Skan tau += v + w; /* Add in other second-order terms. */ 175132718Skan u = t + tau; 176132718Skan 177132718Skan /* Construct long double result. */ 178169689Skan if (nonfinite (u)) 179169689Skan return u; 180132718Skan z.dval[0] = u; 181132718Skan z.dval[1] = (t - u) + tau; 182132718Skan return z.ldval; 183132718Skan} 184132718Skan 185132718Skanlong double 186146895Skan__gcc_qdiv (double a, double b, double c, double d) 187132718Skan{ 188132718Skan longDblUnion z; 189169689Skan double s, sigma, t, tau, u, v, w; 190132718Skan 191132718Skan t = a / c; /* highest order double term */ 192132718Skan 193169689Skan if (unlikely (t == 0) /* Preserve -0. */ 194169689Skan || nonfinite (t)) 195132718Skan return t; 196132718Skan 197132718Skan /* Finite nonzero result requires corrections to the highest order term. */ 198132718Skan 199169689Skan s = c * t; /* (s,sigma) = c*t exactly. */ 200132718Skan w = -(-b + d * t); /* Written to get fnmsub for speed, but not 201132718Skan numerically necessary. */ 202132718Skan 203132718Skan /* Use fused multiply-add to get low part of c * t. */ 204169689Skan#ifndef _SOFT_FLOAT 205132718Skan asm ("fmsub %0,%1,%2,%3" : "=f"(sigma) : "f"(c), "f"(t), "f"(s)); 206169689Skan#else 207169689Skan sigma = fmsub (c, t, s); 208169689Skan#endif 209132718Skan v = a - s; 210132718Skan 211169689Skan tau = ((v-sigma)+w)/c; /* Correction to t. */ 212132718Skan u = t + tau; 213132718Skan 214169689Skan /* Construct long double result. */ 215169689Skan if (nonfinite (u)) 216169689Skan return u; 217132718Skan z.dval[0] = u; 218132718Skan z.dval[1] = (t - u) + tau; 219132718Skan return z.ldval; 220132718Skan} 221132718Skan 222169689Skan#if defined (_SOFT_FLOAT) && defined (__LONG_DOUBLE_128__) 223169689Skan 224169689Skanlong double __gcc_qneg (double, double); 225169689Skanint __gcc_qeq (double, double, double, double); 226169689Skanint __gcc_qne (double, double, double, double); 227169689Skanint __gcc_qge (double, double, double, double); 228169689Skanint __gcc_qle (double, double, double, double); 229169689Skanint __gcc_qunord (double, double, double, double); 230169689Skanlong double __gcc_stoq (float); 231169689Skanlong double __gcc_dtoq (double); 232169689Skanfloat __gcc_qtos (double, double); 233169689Skandouble __gcc_qtod (double, double); 234169689Skanint __gcc_qtoi (double, double); 235169689Skanunsigned int __gcc_qtou (double, double); 236169689Skanlong double __gcc_itoq (int); 237169689Skanlong double __gcc_utoq (unsigned int); 238169689Skan 239169689Skanextern int __eqdf2 (double, double); 240169689Skanextern int __ledf2 (double, double); 241169689Skanextern int __gedf2 (double, double); 242169689Skanextern int __unorddf2 (double, double); 243169689Skan 244169689Skan/* Negate 'long double' value and return the result. */ 245169689Skanlong double 246169689Skan__gcc_qneg (double a, double aa) 247169689Skan{ 248169689Skan longDblUnion x; 249169689Skan 250169689Skan x.dval[0] = -a; 251169689Skan x.dval[1] = -aa; 252169689Skan return x.ldval; 253169689Skan} 254169689Skan 255169689Skan/* Compare two 'long double' values for equality. */ 256169689Skanint 257169689Skan__gcc_qeq (double a, double aa, double c, double cc) 258169689Skan{ 259169689Skan if (__eqdf2 (a, c) == 0) 260169689Skan return __eqdf2 (aa, cc); 261169689Skan return 1; 262169689Skan} 263169689Skan 264169689Skanstrong_alias (__gcc_qeq, __gcc_qne); 265169689Skan 266169689Skan/* Compare two 'long double' values for less than or equal. */ 267169689Skanint 268169689Skan__gcc_qle (double a, double aa, double c, double cc) 269169689Skan{ 270169689Skan if (__eqdf2 (a, c) == 0) 271169689Skan return __ledf2 (aa, cc); 272169689Skan return __ledf2 (a, c); 273169689Skan} 274169689Skan 275169689Skanstrong_alias (__gcc_qle, __gcc_qlt); 276169689Skan 277169689Skan/* Compare two 'long double' values for greater than or equal. */ 278169689Skanint 279169689Skan__gcc_qge (double a, double aa, double c, double cc) 280169689Skan{ 281169689Skan if (__eqdf2 (a, c) == 0) 282169689Skan return __gedf2 (aa, cc); 283169689Skan return __gedf2 (a, c); 284169689Skan} 285169689Skan 286169689Skanstrong_alias (__gcc_qge, __gcc_qgt); 287169689Skan 288169689Skan/* Compare two 'long double' values for unordered. */ 289169689Skanint 290169689Skan__gcc_qunord (double a, double aa, double c, double cc) 291169689Skan{ 292169689Skan if (__eqdf2 (a, c) == 0) 293169689Skan return __unorddf2 (aa, cc); 294169689Skan return __unorddf2 (a, c); 295169689Skan} 296169689Skan 297169689Skan/* Convert single to long double. */ 298169689Skanlong double 299169689Skan__gcc_stoq (float a) 300169689Skan{ 301169689Skan longDblUnion x; 302169689Skan 303169689Skan x.dval[0] = (double) a; 304169689Skan x.dval[1] = 0.0; 305169689Skan 306169689Skan return x.ldval; 307169689Skan} 308169689Skan 309169689Skan/* Convert double to long double. */ 310169689Skanlong double 311169689Skan__gcc_dtoq (double a) 312169689Skan{ 313169689Skan longDblUnion x; 314169689Skan 315169689Skan x.dval[0] = a; 316169689Skan x.dval[1] = 0.0; 317169689Skan 318169689Skan return x.ldval; 319169689Skan} 320169689Skan 321169689Skan/* Convert long double to single. */ 322169689Skanfloat 323169689Skan__gcc_qtos (double a, double aa __attribute__ ((__unused__))) 324169689Skan{ 325169689Skan return (float) a; 326169689Skan} 327169689Skan 328169689Skan/* Convert long double to double. */ 329169689Skandouble 330169689Skan__gcc_qtod (double a, double aa __attribute__ ((__unused__))) 331169689Skan{ 332169689Skan return a; 333169689Skan} 334169689Skan 335169689Skan/* Convert long double to int. */ 336169689Skanint 337169689Skan__gcc_qtoi (double a, double aa) 338169689Skan{ 339169689Skan double z = a + aa; 340169689Skan return (int) z; 341169689Skan} 342169689Skan 343169689Skan/* Convert long double to unsigned int. */ 344169689Skanunsigned int 345169689Skan__gcc_qtou (double a, double aa) 346169689Skan{ 347169689Skan double z = a + aa; 348169689Skan return (unsigned int) z; 349169689Skan} 350169689Skan 351169689Skan/* Convert int to long double. */ 352169689Skanlong double 353169689Skan__gcc_itoq (int a) 354169689Skan{ 355169689Skan return __gcc_dtoq ((double) a); 356169689Skan} 357169689Skan 358169689Skan/* Convert unsigned int to long double. */ 359169689Skanlong double 360169689Skan__gcc_utoq (unsigned int a) 361169689Skan{ 362169689Skan return __gcc_dtoq ((double) a); 363169689Skan} 364169689Skan 365169689Skan#include "config/soft-fp/soft-fp.h" 366169689Skan#include "config/soft-fp/double.h" 367169689Skan#include "config/soft-fp/quad.h" 368169689Skan 369169689Skan/* Compute floating point multiply-subtract with higher (quad) precision. */ 370169689Skanstatic double 371169689Skanfmsub (double a, double b, double c) 372169689Skan{ 373169689Skan FP_DECL_EX; 374169689Skan FP_DECL_D(A); 375169689Skan FP_DECL_D(B); 376169689Skan FP_DECL_D(C); 377169689Skan FP_DECL_Q(X); 378169689Skan FP_DECL_Q(Y); 379169689Skan FP_DECL_Q(Z); 380169689Skan FP_DECL_Q(U); 381169689Skan FP_DECL_Q(V); 382169689Skan FP_DECL_D(R); 383169689Skan double r; 384169689Skan long double u, v, x, y, z; 385169689Skan 386169689Skan FP_INIT_ROUNDMODE; 387169689Skan FP_UNPACK_RAW_D (A, a); 388169689Skan FP_UNPACK_RAW_D (B, b); 389169689Skan FP_UNPACK_RAW_D (C, c); 390169689Skan 391169689Skan /* Extend double to quad. */ 392169689Skan#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q 393169689Skan FP_EXTEND(Q,D,4,2,X,A); 394169689Skan FP_EXTEND(Q,D,4,2,Y,B); 395169689Skan FP_EXTEND(Q,D,4,2,Z,C); 396169689Skan#else 397169689Skan FP_EXTEND(Q,D,2,1,X,A); 398169689Skan FP_EXTEND(Q,D,2,1,Y,B); 399169689Skan FP_EXTEND(Q,D,2,1,Z,C); 400132718Skan#endif 401169689Skan FP_PACK_RAW_Q(x,X); 402169689Skan FP_PACK_RAW_Q(y,Y); 403169689Skan FP_PACK_RAW_Q(z,Z); 404169689Skan FP_HANDLE_EXCEPTIONS; 405169689Skan 406169689Skan /* Multiply. */ 407169689Skan FP_INIT_ROUNDMODE; 408169689Skan FP_UNPACK_Q(X,x); 409169689Skan FP_UNPACK_Q(Y,y); 410169689Skan FP_MUL_Q(U,X,Y); 411169689Skan FP_PACK_Q(u,U); 412169689Skan FP_HANDLE_EXCEPTIONS; 413169689Skan 414169689Skan /* Subtract. */ 415169689Skan FP_INIT_ROUNDMODE; 416169689Skan FP_UNPACK_SEMIRAW_Q(U,u); 417169689Skan FP_UNPACK_SEMIRAW_Q(Z,z); 418169689Skan FP_SUB_Q(V,U,Z); 419169689Skan FP_PACK_SEMIRAW_Q(v,V); 420169689Skan FP_HANDLE_EXCEPTIONS; 421169689Skan 422169689Skan /* Truncate quad to double. */ 423169689Skan FP_INIT_ROUNDMODE; 424169689Skan FP_UNPACK_SEMIRAW_Q(V,v); 425169689Skan#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q 426169689Skan FP_TRUNC(D,Q,2,4,R,V); 427169689Skan#else 428169689Skan FP_TRUNC(D,Q,1,2,R,V); 429169689Skan#endif 430169689Skan FP_PACK_SEMIRAW_D(r,R); 431169689Skan FP_HANDLE_EXCEPTIONS; 432169689Skan 433169689Skan return r; 434169689Skan} 435169689Skan 436169689Skan#endif 437169689Skan 438169689Skan#endif 439